HTTP/1.1 -1 Read error in cache disk data: SuccessContent-Type: text/plain; charset="utf-8"
Last-Modified: Sat, 22 Jan 2022 03:46:49 GMT
Content-length: 10958
Connection: Close
Proxy-Connection: Close
X-Cache: HIT from web1.osuosl.org
Server: ProxyTrack 0.5 (HTTrack 3.49.2)
The purpose of the PCC branch is to unify the internal implementation of the calling conventions into one code path. The current implementation of subroutine, method, and NCI invocation uses multiple different styles of passing and receiving arguments. A call to a subroutine or method from PIR saves a pointer to the location of the opcode where the arguments were passed, and later extracts the variables or constants from that opcode instruction. A call to a subroutine or method from C may pass around a varargs list and extract the arguments from it later or create a call state struct.
The new implementation standardizes argument passing for all calls (whether from PIR or C). Each call creates a call signature object right away, inserting arguments into the signature object from the opcode pointer or varargs list as soon as the call is made. Parameters are always extracted from a call signature object, and know nothing about the source of the call (they don't need to know what kind of environment invoked them, since all calls follow the same code path, and pass arguments the same way). NCI calls and what was previously known as PCCMETHOD calls also use the same argument passing strategy. Signature strings will be standardized on the PCC form (e.g. PI->S, for a call with a pmc and an integer argument, that returns a string result). The exception is NCI signatures, which will be left alone for now, but may be standardized later.
The following opcodes will be kept, but their implementation changed.
{{{
src/ops/core.ops:
set_args
get_params
set_returns
get_results
}}}
The following functions are deprecated and will be removed, as well as any functions only called by these functions.
{{{
src/call/pcc.c:
parrot_pass_args
parrot_pass_args_fromc
Parrot_PCCINVOKE
Parrot_init_ret_nci
Parrot_init_arg_nci
count_signature_elements (static)
set_context_sig_returns_varargs (static)
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
src/extend.c (these functions are part of the defined public API, so will
be modified to be backward compatible for now, and removed after 2.0):
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
src/nci.c
set_nci_I
set_nci_N
set_nci_S
set_nci_P
}}}
The following code generators have been updated to produce new-style argument retrieval, instead of old-style argument retreival:
{{{
tools/build/nativecall.pl
lib/Parrot/Pmc2c/PCCMETHOD.pm
}}}
The following functions are added and act as replacements for the deprecated functions.
{{{
src/call/pcc.c:
Parrot_pcc_invoke_sub_from_c_args
Parrot_pcc_build_sig_object_from_op
Parrot_pcc_build_sig_object_returns_from_op
Parrot_pcc_build_sig_object_from_varargs (added in an earlier refactor, but for this purpose)
Parrot_pcc_fill_params_from_op
Parrot_pcc_fill_params_from_c_args
Parrot_pcc_fill_returns_from_op
Parrot_pcc_fill_returns_from_c_args
}}}
The following static functions are added, and support the new argument passing behavior:
{{{
src/call/pcc.c:
dissect_aggregate_arg
extract_named_arg_from_op
parse_signature_string
src/call/callsignature.c
Parrot_pcc_get_call_sig_raw_args
Parrot_pcc_get_call_sig_raw_returns
Parrot_pcc_set_call_sig_raw_args
Parrot_pcc_set_call_sig_raw_returns
}}}
The signature object is stored in the current_sig element of the caller's context. This means that argument storing and return value extraction happens on current_sig in CURRENT_CONTEXT(interp), while parameter extraction and return value storing must retrieve the caller's context and use its current_sig element. The reason for this distinction is that the subroutine's local current_sig element will be set for every call it makes. (This will be simplified when contexts and call_signatures are collapsed into one.)
See also the earlier wishlist/tasklist CallingConventionsTasklist which mentions some of the motivations and reasoning for these changes.
== Known issues ==
- ~~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.~~
- 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)
- 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)
== Argument Processing Algorithms ==
Here is some documentation for ways that the argument processing algorithm ({{{Parrot_pcc_fill_params_from_op and Parrot_pcc_fill_params_from_varargs}}}) work. There are two possible ways, depending on whether we iterate over the list of parameters and pull arguments, or iterate over the list of arguments and push them into parameters. First, iterating over parameters (similar to what is done now):
{{{
Infinite loop
get next positional arg
get next positional parameter slot
if parameter slot is NULL
if positional arg is NULL # No more of either, done. Break
break
if error checking
throw exception
if positional arg is NULL
if error checking
throw exception
if parameter slot is slurpy
create new RPA PMC
insert new RPA PMC into destination context parameter slot
if we have a slurpy array pmc
add positional arg to slurpy array pmc
else
Insert positional into destination context parameter slot
if current parameter slot is optional
set corresponding opt_flag TRUE
Infinite loop
get next named arg name
get next named arg value
get next named parameter slot
if arg name/value pair is NULL
if parameter slot is NULL
break # Even, we're done
else if error checking
throw exception
if parameter slot is NULL
throw exception
if parmeter slot is slurpy
create new Hash PMC
insert new Hash PMC into destination context parameter slot
if we have a slurpy hash PMC
add name/value pair to slurpy hash PMC
else
Insert value into destination context parameter slot
if current parameter slot is optional
set corresponding opt_flag to TRUE
Loop over all remaining opt_flag parameters
set to FALSE
}}}
Next, iterating over arguments. This requires iterator functionality installed into CallSignature, which does not currently exist:
{{{
Infinite loop
get next positional arg
get next parameter flag
if no parameter flag
if no positional arg # No more of either, done.
end loop
if error checking
throw exception
if no positional arg
set all remaining positional opt_flags to FALSE
if error checking
throw exception
if parameter flag is slurpy
create new RPA PMC
insert new RPA PMC into destination context parameter slot
add positional arg to slurpy array pmc
add all remaining positional args to slurpy array pmc
end loop
Insert positional into destination context parameter slot
if current parameter slot is optional
set corresponding opt_flag TRUE
Infinite loop
get next named arg name
get next named arg value
get next parameter flag
if no parameter flag
if no arg name/value pair
end loop # Even, we're done
if error checking
throw exception
if no arg name/value pair
set all remaining named opt_flags to FALSE
if error checking
throw exception
if parameter flag is slurpy
create new Hash PMC
insert new Hash PMC into destination context parameter slot
add name/value pair to slurpy hash PMC
add all remaining name/value pairs to slurpy hash PMC
Insert value into destination context parameter slot
if current parameter slot is optional
set corresponding opt_flag to TRUE
}}}
pe">
Type