Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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 4fd9292
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 3 deletions.
19 changes: 18 additions & 1 deletion src/QAST/Operations.nqp
Expand Up @@ -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');

Expand Down
61 changes: 59 additions & 2 deletions src/ops/nqp.ops
Expand Up @@ -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)) {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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()
Expand Down

0 comments on commit 4fd9292

Please sign in to comment.