Permalink
Browse files

Change the way we do invokewithcapture.

This avoids a bunch of nested runloops and all the problems that come
with them. Re-working this, once a tweak is done in Rakudo, gets rid
of the couple of exit-time SEGVs in the md-nqp branch.
  • Loading branch information...
jnthn committed Mar 16, 2013
1 parent ed35b15 commit 4fd929201516fb43d02672113b601b1608fa244d
Showing with 77 additions and 3 deletions.
  1. +18 −1 src/QAST/Operations.nqp
  2. +59 −2 src/ops/nqp.ops
View
@@ -1072,7 +1072,24 @@ QAST::Operations.add_core_pirop_mapping('captureexistsnamed', 'exists', 'IQs');
QAST::Operations.add_core_pirop_mapping('captureposprimspec', 'captureposprimspec', 'IPi');
# Multiple dispatch related.
-QAST::Operations.add_core_pirop_mapping('invokewithcapture', 'invoke_with_capture', 'PPP');
+QAST::Operations.add_core_op('invokewithcapture', -> $qastcomp, $op {
+ unless $op.list == 2 {
+ nqp::die("The 'invokewithcapture' op requires two children");
+ }
+ my $pos_reg := $*REGALLOC.fresh_p();
+ my $nam_reg := $*REGALLOC.fresh_p();
+ my $res_reg := $*REGALLOC.fresh_p();
+ my $inv_post := $qastcomp.coerce($qastcomp.as_post($op[0]), 'P');
+ my $cap_post := $qastcomp.coerce($qastcomp.as_post($op[1]), 'P');
+ my $ops := PIRT::Ops.new();
+ $ops.push($inv_post);
+ $ops.push($cap_post);
+ $ops.push_pirop('deconstruct_capture', $cap_post.result, $pos_reg, $nam_reg);
+ $ops.push_pirop('call', $inv_post.result, $pos_reg ~ ' :flat',
+ $nam_reg ~ ' :flat :named', :result($res_reg));
+ $ops.result($res_reg);
+ $ops
+});
QAST::Operations.add_core_pirop_mapping('multicacheadd', 'multi_cache_add', 'PPPP');
QAST::Operations.add_core_pirop_mapping('multicachefind', 'multi_cache_find', 'PPP');
View
@@ -54,6 +54,9 @@ PMC *compiling_scs = NULL;
* number of nested enable/disable we are in. */
INTVAL sc_write_barrier_off_depth = 0;
+/* Empty hash, used in deconstruct op. */
+static PMC *empty_hash = NULL;
+
/* SC write barrier for objects. */
static void SC_write_barrier_obj(PARROT_INTERP, PMC *obj) {
if (!sc_write_barrier_off_depth && VTABLE_get_bool(interp, compiling_scs)) {
@@ -340,6 +343,10 @@ inline op nqp_dynop_setup() :base_core {
nfa_nextst = Parrot_pmc_new(interp, enum_class_ResizableIntegerArray);
Parrot_pmc_gc_register(interp, nfa_nextst);
+ /* Create and anchor empty hash. */
+ empty_hash = Parrot_pmc_new(interp, enum_class_Hash);
+ Parrot_pmc_gc_register(interp, empty_hash);
+
/* Mark initialized. */
initialized = 1;
}
@@ -1576,14 +1583,64 @@ Invokes the specified target with the specified capture.
inline op invoke_with_capture(out PMC, in PMC, in PMC) :base_core {
PMC *arg_copy = VTABLE_clone(interp, $3);
PMC *result;
- PMC *prev_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
+ /*PMC *prev_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));*/
Parrot_pcc_invoke_from_sig_object(interp, $2, arg_copy);
result = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
- Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), prev_ctx);
+ /*Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), prev_ctx);*/
$1 = VTABLE_get_pmc_keyed_int(interp, result, 0);
}
+/*
+
+=item deconstruct_capture()
+
+Puts something that will flatten to the position part of the capture in $1
+into $2, and soemthing that will flatten to the named part into $3.
+
+=cut
+
+*/
+inline op deconstruct_capture(invar PMC, out PMC, out PMC) :base_core {
+ PMC *capture = $1;
+ if (capture->vtable->base_type == enum_class_CallContext) {
+ Hash *nameds;
+ INTVAL has_nameds;
+
+ /* The call context itself will do for the positionals. */
+ $2 = capture;
+
+ /* See if there are any nameds */
+ GETATTR_CallContext_hash(interp, capture, nameds);
+ has_nameds = nameds && Parrot_hash_size(interp, nameds) ? 1 : 0;
+
+ /* If there's a named part, create a hash with the values. */
+ if (has_nameds) {
+ PMC *result = Parrot_pmc_new(interp, enum_class_Hash);
+ PMC *named_names = VTABLE_get_attr_str(interp, capture,
+ Parrot_str_new_constant(interp, "named"));
+ INTVAL n = VTABLE_elements(interp, named_names);
+ INTVAL i;
+ for (i = 0; i < n; i++) {
+ STRING *name = VTABLE_get_string_keyed_int(interp, named_names, i);
+ VTABLE_set_pmc_keyed_str(interp, result, name,
+ VTABLE_get_pmc_keyed_str(interp, capture, name));
+ }
+ $3 = result;
+ }
+
+ /* Otherwise, use empty hash. */
+ else {
+ $3 = empty_hash;
+ }
+ }
+ else {
+ $2 = $1;
+ $3 = empty_hash;
+ }
+}
+
+
/*
=item multi_cache_add()

0 comments on commit 4fd9292

Please sign in to comment.