Permalink
Browse files

Fix tailcalls to NCI, #38724

* unit Compiler.invoke and NCI.invoke
* free call frame in NCI.invoke, if tailcalled
* get rid of more dead code regarding tailcalla and arg passing


git-svn-id: https://svn.parrot.org/parrot/trunk@11896 d31e2699-5ff4-0310-a27c-f18f2fbe73fe
  • Loading branch information...
1 parent d51f835 commit 92c390d5bfa31739bcab46ef0811307ccfa788ba Leopold Toetsch committed Mar 14, 2006
Showing with 32 additions and 34 deletions.
  1. +0 −16 src/inter_call.c
  2. +1 −6 src/pmc/compiler.pmc
  3. +13 −11 src/pmc/nci.pmc
  4. +18 −1 t/op/calling.t
View
@@ -1116,22 +1116,6 @@ parrot_pass_args(Interp *interpreter, parrot_context_t *src_ctx,
if (!PARROT_ERRORS_test(interpreter, PARROT_ERRORS_PARAM_COUNT_FLAG))
err_check = 0;
}
- if (src_pc && (src_pc[-3] == PARROT_OP_tailcallmethod_p_sc ||
- src_pc[-3] == PARROT_OP_tailcallmethod_p_s)) {
- /*
- * If we have this sequence:
- *
- * tailcallmethod_p_s?
- * set_returns_pc '()'
- * return_cc
- *
- * we are returning 1 retval to caller on behalf
- * of the NCI (a PIR method had already returned
- * all and doesn't run anything after the
- * tailcall - ignore arg_count
- */
- err_check = 0;
- }
process_args(interpreter, &st, action, err_check);
/* skip the get_params opcode - all done here */
View
@@ -36,12 +36,7 @@ C<Eval> PMC with a new PackFile attached.
*/
void* invoke (void * code_ptr) {
- typedef INTVAL (*nci_sub_t)(Interp * , PMC * );
- nci_sub_t func = (nci_sub_t)D2FPTR(PMC_data(SELF));
-
- INTERP->current_cont = NULL;
- func(INTERP, SELF);
- return code_ptr;
+ return SUPER(code_ptr);
}
}
View
@@ -124,23 +124,25 @@ shifted down.
void* invoke (void * next) {
typedef INTVAL (*nci_sub_t)(Interp * , PMC * );
nci_sub_t func = (nci_sub_t)D2FPTR(PMC_data(SELF));
+ PMC *cont;
- INTERP->current_cont = NULL;
if (!func)
real_exception(INTERP, NULL, INVALID_OPERATION,
"attempt to call NULL function");
+ func(INTERP, SELF);
+ cont = INTERP->current_cont;
/*
- * If the invocant is a class or there is no invocant
- * shift down arguments.
- * But not if it's a plain NCI function created
- * from dlfunc.
- *
- * NCI flags:
- * private0 ... builtin multi method
- * private1 ... created via dlfunc
- *
+ * If the NCI function was tailcalled, the return result
+ * is already passed back to the caller of this frame
+ * - see Parrot_init_ret_nci(). We therefore invoke the
+ * return continuation here, which gets rid of this frame
+ * and returns the real return address
*/
- func(INTERP, SELF);
+ if (cont && cont != NEED_CONTINUATION &&
+ (PObj_get_FLAGS(cont) & SUB_FLAG_TAILCALL)) {
+ cont = CONTEXT(interpreter->ctx)->current_cont;
+ next = VTABLE_invoke(INTERP, cont, next);
+ }
return next;
}
View
@@ -1315,6 +1315,23 @@ ok 1
ok 2
OUTPUT
+pir_output_is(<<'CODE', <<'OUTPUT', "tailcall to NCI - 2");
+.sub main :main
+ $P0 = eval("print \"Foo!\\n\"")
+ $P0()
+ end
+.end
+
+.sub eval
+ .param string code
+ code = ".sub main :main :anon\n" . code
+ code = code . "\n.end\n"
+ $P0 = compreg "PIR"
+ .return $P0(code)
+.end
+CODE
+Foo!
+OUTPUT
# bug - repeated calls to eval'd sub crashes (pmichaud, 2005.10.27)
pir_output_is(<<'CODE', <<'OUTPUT', "repeated calls to eval'd sub");
@@ -2282,5 +2299,5 @@ CODE
OUTPUT
## remember to change the number of tests :-)
-BEGIN { plan tests => 88 }
+BEGIN { plan tests => 89 }

0 comments on commit 92c390d

Please sign in to comment.