See CallingConventionsOverview for an explanation of changes that have already gone in.

Args/Returns Unification Refactor

Because 'get_results' and 'set_returns' are currently implemented to be used in reverse order, passing return arguments requires taking a pointer to the location where return arguments will be passed *to*, so the pointers can be set when the subroutine actually returns.

(These refactors are interdependent.)

* Refactor PASM calling code so that set_returns is called before get_results (done for PBC generation from IMCC; not yet done for PASM)

* Unify argument passing and returns passing to use a single codepath.

  • Collapse 'Parrot_pcc_build_sig_object_returns_from_op' into 'Parrot_pcc_build_sig_object_from_op' (and call it from 'set_returns' instead of 'get_results')
  • Collapse 'assign_default_result_value' into 'assign_default_param_value'.
  • Collapse 'Parrot_pcc_fill_returns_from_op' into 'Parrot_pcc_fill_params_from_op'
  • Collapse 'Parrot_pcc_fill_returns_from_c_args' into 'Parrot_pcc_fill_params_from_c_args'
  • Collapse 'fill_results' into 'fill_params'

* Rename 'Parrot_pcc_fill_returns_from_continuation' to 'Parrot_pcc_fill_params_from_continuation' (or see if there's some way to merge it with another existing parameter filling function) (removed, function longer necessary now that all returns are continuation invokes)

* Remove deprecated (temporary) function 'Parrot_pcc_append_result'

* Modify 'Parrot_pcc_build_sig_object_from_op' ('Parrot_pcc_build_sig_object_returns_from_op'), 'extract_named_arg_from_op', and 'Parrot_pcc_build_sig_object_from_varargs' to use the same function pointers as 'fill_params', where possible.

* Remove sections of CallContext PMC that were used for storing and manipulating returns inside the parameters signature. (Returns will reuse the arg/param call context object, or create a new one.)

  • 'results_signature', 'current_results', 'returns_values', 'returns_size', and 'returns_resize_threshold' ATTRs
  • 'results' and 'return_flags' accessors in set_attr_str and get_attr_str

General tasks

* Move static 'csr_*' functions (src/call/args.c) that define an interface to manipulating the CallContext PMC into src/call/context.c.

* Review the current functions in src/call/context.c and src/call/context_accessors.c, to see what's still useful after the move to the CallContext PMC.

* Optimize PCC dispatch, refactor to slim down the code (much of that will happen in the args/returns refactor, but worth another look after that's done).

* Add lots of documentation about signature strings, CallContext, dispatch, etc

- Make sure the API and documentation consistently uses "args" and "returns" to mean "the things passed into the call or return" and "params" and "results" to mean "the things extracted from the call or return".

* Add :call_sig parameter flag type. Can be used to get access to the raw CallSignature object.

* Add :call_sig argument flag type. Can be used to pass in a CallSignature object instead of building one.

* Add a :lookahead option for Sub parameters. A lookahead parameter takes a named argument preferably, takes a positional otherwise.

* Reduce marshalling and demarshalling between C calling conventions and Parrot Calling Conventions (especially in hot paths, such as MMD and vtables)

Invoke Refactor

* Make VTABLE_invoke consistent between different sub-like PMCs (Sub, NCI, etc). See #1094

* Allow VTABLE_invoke to be properly overridden from PIR. See #103

* Allow Sub, Continuation, etc. to be properly subclassed from PIR

Completed items

* Add an :invocant flag so that we can name the method invocant something besides "self"

* Standardize on PCC-style signature description strings throughout the system, instead of different signature description strings for different calling APIs. Excludes NCI signatures.

* Remove 'Parrot_call_*' functions (deprecated in TT # 1145)

* Remove 'Parrot_PCCINVOKE', it has been replaced by 'Parrot_pcc_invoke_method_from_c_args' (the bodies of the two functions are exact copies). (falls under blanket deprecation in TT #443, may deserve its own deprecation ticket)

* Remove the TODO mark from t/pmc/multidispatch.t test 32 (see RT #59628) (r41812).

* Merge inter_call.c and inter_run.c, or completely rename and resort the existing functions. Possibly src/calling.c and src/opcode_runloop.c or src/calling/pcc.c and src/calling/opcodes.c? (Done in r36595)

* Enable dispatching by CallContext PMC everywhere (check if there are places it isn't enabled where it should be possible).

* Refactor Integer PMC's overflow mechanism to do a VTABLE call rather than directly performing an MMD call (to allow for vtable overrides). See #60

* Modify Parrot_build_sig_object_from_varargs to check if an invocant is present and if "Pi" doesn't already exist at the beginning of the string.

* Delete all old call-related functions that are no longer used.

* Convert all calls to 'Parrot_runops_fromc_args*' into calls to 'Parrot_pcc_invoke_sub_from_c_args'.

- The Parrot_call_sub_* and Parrot_call_method_* variants in src/extend.c don't all have the necessary changes to allow them to work with the new calling conventions (these are temporary implementations for backward compatibility before they're removed at the next deprecation point). Parrot_call_sub does have the right changes, and the others can be largely copied from it.

- NCI hasn't been fully updated on caller and receiver side to use the new argument passing style.

* There's a huge hodge-podge of functions that do basically the same thing. Trim these down to a logical set that handle the basic cases. (calling from PIR, calling from C, calling from a CallSignature PMC).

* Converge on one calling convention for all invocation. Different entry points for calling from PIR, C, or CallSignature PMC. Different exit points, depending on whether the call is a Sub (Closure, Contintuation, etc) or a CFunction. But same code pattern, and same core routines for all.

* Refactor to remove code duplication between the various dispatch systems.

* Add adverb modifier "i" to signature string for an invocant.

* Change the default vtable function generator for Object PMC to generate 'Parrot_pcc_invoke_sub_from_c_args' calls instead of 'Parrot_runops_fromc_args*' calls.

* Refactor CallSignature to store arguments as a typed array, instead of as a PMC array. The types we know from the signature, so can store and retrieve the elements in a type-safe way. (Suggestion from IRC discussion was to use a union for the value storage.) This will reduce the number of PMCs created, since integer, number, and string arguments can be stored directly instead of boxed in PMCs.

* Refactor CallSignature to store arguments directly in CallSignature data structure, instead of creating two additional PMCs (array for positionals and hash for named) to hold them. This refactor can be done at the same time as the typed array refactor.

* Refactor CallSignature to merge it with Context, only need one PMC to hold all that information. (Question: what's the implication of this combined with the previous refactor? Do returns get passed out in the same struct members that the arguments came in on?)

- Return argument processing (Parrot_pcc_fill_returns_from_op and Parrot_pcc_fill_returns_from_c_args) doesn't currently support :named, :slurpy, :flatten, :optional, :opt_flag etc. (t/compilers/imcc/syn/tail.t, t/pmc/coroutine.t)

- Parrot_pcc_fill_params_from_op and Parrot_pcc_fill_params_from_c_args are monolithic functions (basically finite state machines iterating over the arguments), that contain a great deal of nearly repeated code (one or two things different each time). Parrot_pcc_fill_returns_from_op and Parrot_pcc_fill_returns_from_c_args will be just as bad once they support all the options. Not a requirement before the merge, but these should be refactored into smaller subroutines. Needs to be thought through carefully though, it was a similar plan that lead to the current mess.

- Flattening an argument doesn't alter the signature string stored, so multiple dispatch can't handle the resulting string. Need to modify the signature string while building the CallSignature object. (t/pmc/multisub.t and t/pmc/multidispatch.t)

- Edge cases on auto boxing/unboxing argument types, e.g. "Unable to set PMC value, the pointer is not a PMC" (t/oo/methods.t, t/oo/subclass.t, t/pmc/hashiteratorkey.t, t/pmc/object-meths.t, t/pmc/resizablestringarray.t, t/pmc/string.t)

- GC attempting to mark a bad variable (t/op/box.t) (Actually IMCC creates bad PackFile_Constants segment for box.t)

- Insufficient checking on positional arguments passed inside named arguments (t/op/calling.t)

- Insufficient checking on missing named arguments (t/op/cc_state.t)

- Insufficient checking on too many arguments passed (t/pmc/exporter.t)

- Some tests need to be updated to match the current error messages (t/op/calling.t, t/op/cc_params.t)

- Segfault in set_returns, possibly a null call object? (t/op/gc.t, t/pmc/exceptionhandler.t)

- Probably a problem with argument handling (t/op/lexicals.t, t/pmc/class.t, t/pmc/codestring.t, t/pmc/object-meths.t, t/pmc/sub.t)

- Two NCI edge cases (t/pmc/nci.t)

- Likely cases of code still calling into the old functions for invoking from C, instead of the new functions (t/pmc/sub.t, t/pmc/threads.t)

- Likely bug in Parrot_call_sub reimplementation (t/src/embed.t)

- miniparrot fails to compile if an installed parrot is not already present, because it has -lparrot in the compile options

- Currently, test_more.pir cannot be used on pcc_reapply. Attempting to use test_more.pir results in

FixedIntegerArray: index out of bounds!
current instr.: 'parrot;Test;Builder;Test;_initialize' pc 44 (runtime/parrot/library/Test/Builder/Test.pir:46)
called from Sub 'parrot;Test;Builder;_initialize' pc 0 (runtime/parrot/library/Test/Builder.pir:51)
... call repeated 1 times