Version 1 (modified by allison, 4 years ago)

--

This page provides some details on migrating external code to use the new Parrot calling conventions implementation. The core focus of this change was to move all sub or method calls throughout the system to store their arguments and returns in a CallSignature PMC, instead of various different ways depending on how the sub/method was called (varargs list, call state struct, direct pointer to the memory location of the opcode where the args were passed, in the interpreter structure, etc).

PIR/PASM/PBC interface

Unchanged. The opcodes for sub and method calls are the same, called in the same order. The PIR syntactic sugar for sub and method calls is the same. (This is to meet the Parrot support policy, there will be some small changes to the opcode order after 2.0.)

C API Functions

The following functions have been preserved for backward compatibility with the existing defined C API. The internals of the functions have been completely replaced, but they exactly preserve the old interface, including accepting only old-style signature strings (with the return value type as the first character in the string).

src/extend.c:
  Parrot_call_sub
  Parrot_call_sub_ret_int
  Parrot_call_sub_ret_float
  Parrot_call_method
  Parrot_call_method_ret_int
  Parrot_call_method_ret_float

These functions are only preserved for backward compatibility under the support policy, and have been deprecated to be removed after 2.0. (See TT #1145.) The replacement function is 'Parrot_ext_call', and it handles all the cases that the previous set of functions handled. (Recommended to go ahead and migrate to the new function, even though the old functions will be around until 2.0.)

'Parrot_ext_call' takes a new-style signature string, where the return value type(s) are listed at the end of the signature, separated from the args by an arrow ('->'). The variables for the return values to be stored in are also passed as references after all the arguments in the call. (See the documentation for 'Parrot_ext_call' for more details.)

INTVAL result;
Parrot_ext_call(interp, cmp, "PP->I", a, b, &result);
return result;

The following functions have been deprecated and removed. Calls to any of these functions can be replaced by a call to 'Parrot_ext_call' (with an appropriate signature string).

src/call/ops.c:
  runops_args
  Parrot_run_meth_fromc
  Parrot_runops_fromc_args
  Parrot_runops_fromc_args_event
  Parrot_runops_fromc_args_reti
  Parrot_runops_fromc_args_retf
  Parrot_run_meth_fromc_args
  Parrot_run_meth_fromc_args_reti
  Parrot_run_meth_fromc_args_retf
  Parrot_runops_fromc_arglist
  Parrot_runops_fromc_arglist_reti
  Parrot_runops_fromc_arglist_retf
  Parrot_run_meth_fromc_arglist
  Parrot_run_meth_fromc_arglist_reti
  Parrot_run_meth_fromc_arglist_retf

The following functions have been deprecated and removed. They were only used internally, so shouldn't require migration, but if you were using them for any reason, there's a good chance you'll what to move to 'Parrot_ext_call' instead.

src/call/pcc.c:
  parrot_pass_args
  parrot_pass_args_fromc
  Parrot_init_ret_nci
  Parrot_init_arg_nci

'parrot_pass_args' has been replaced by 'Parrot_pcc_fill_params_from_op', and 'parrot_pass_args_fromc' has been replaced by 'Parrot_pcc_fill_params_from_c_args'.

The following functions will be deprecated in the future:

src/call/pcc.c:
  Parrot_pcc_invoke_sub_from_c_args
  Parrot_PCCINVOKE

'Parrot_pcc_invoke_sub_from_c_args' is exactly the same as 'Parrot_ext_call', but with a worse name, so use 'Parrot_ext_call' instead. 'Parrot_PCCINVOKE' is exactly the same as 'Parrot_pcc_invoke_method_from_c_args', but with a worse name. (See TT #443.)

Other C API pieces

The interpreter structure no longer has 'interp->current_args', 'interp->current_params', 'interp->current_returns', 'interp->args_signature', 'interp->params_signature', or 'interp->returns_signature' elements. The closest equivalent is 'CURRENT_CONTEXT(interp)->current_sig' (that is, the 'current_sig' element of the current context) which is the CallSignature PMC for the current call (and contains the arguments and results). Don't access this struct element directly, use the interface functions 'Parrot_pcc_get_signature' and 'Parrot_pcc_set_signature' instead.

PMC * const this_call_sig   = Parrot_pcc_get_signature(interp, ctx);

The 'interp->current_object' element still exists, but will go away once we merge all calls to store the object for method invocations in the CallSignature. (Certain parts of IMCC were left unchanged for now.)

Testing

Added a 'throws_substring' test function to Test::More, to capture inexact exception messages without depending on PGE in the core tests.