# New Ticket Created by  "Alek Storm" 
# Please include the string:  [perl #42155]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=42155 >


This patch moves args_signature, params_signature, returns_signature,
current_args, current_params, and current_returns from Parrot_Interp
to Parrot_Context.  This makes the interpreter more reentrant, which
is always a good thing.

Since these variables are no longer global, we need to keep track of
who belongs to whom.  In a sub call, current_args and current_results
are set for the caller, while current_params and current_returns are
set for the callee.  The same goes for *_signature, mutatis mutandis
(an excuse to use Latin! yes!).

This patch seems to break some tests in t/dynoplibs, and I have no
idea why.  It also *looks* like it breaks t/examples/shootout.t, but
if the examples are run manually, they work fine.  I am completely
baffled.  If anyone can solve these, they get a hug.

Thanks,
Alek Storm
Index: src/ops/core.ops
===================================================================
--- src/ops/core.ops	(revision 17785)
+++ src/ops/core.ops	(working copy)
@@ -503,7 +503,7 @@
     INTVAL argc;
 
     /* for now just point to the opcode */
-    interp->current_args = this;
+    CONTEXT(interp->ctx)->current_args = this;
     argc = SIG_ELEMS(signature);
     goto OFFSET(argc + 2);
 }
@@ -526,17 +526,16 @@
     INTVAL argc;
     opcode_t *src_indexes, *dst_indexes;
 
-    interp->current_params = this;
     ctx = CONTEXT(interp->ctx);
+    ctx->current_params = this;
     ccont = ctx->current_cont;
 
     caller_ctx = ctx->caller_ctx;
 
-    src_indexes = interp->current_args;
-    dst_indexes = interp->current_params;
-    /* the args and params are now 'used.' */
-    interp->current_args = NULL;
-    interp->current_params = NULL;
+    src_indexes = caller_ctx->current_args;
+    dst_indexes = ctx->current_params;
+    caller_ctx->current_args = NULL;
+    ctx->current_params = NULL;
 
     parrot_pass_args(interp, caller_ctx, ctx, src_indexes, dst_indexes, PARROT_PASS_PARAMS);
     if (PObj_get_FLAGS(ccont) & SUB_FLAG_TAILCALL) {
@@ -546,7 +545,6 @@
         /* ordinarily, this will free the context immediately, but not if the
            sub created a closure (or continuation, or . . .).  */
         Parrot_free_context(interp, caller_ctx, 0);
-        interp->current_args = NULL;
     }
     argc = SIG_ELEMS(signature);
     goto OFFSET(argc + 2);
@@ -560,8 +558,8 @@
     INTVAL argc;
     opcode_t *src_indexes, *dest_indexes;
 
-    interp->current_returns = this;
     ctx = CONTEXT(interp->ctx);
+    ctx->current_returns = this;
     ccont = ctx->current_cont;
 
     if (PMC_cont(ccont)->address) {
@@ -573,11 +571,10 @@
             internal_exception(1, "No caller_ctx for continuation %p.", ccont);
         }
 
-        src_indexes = interp->current_returns;
+        src_indexes = ctx->current_returns;
         dest_indexes = caller_ctx->current_results;
-        interp->current_returns = NULL;
-        /* does this need to be here */
-        interp->current_args = NULL;
+        ctx->current_returns = NULL;
+        caller_ctx->current_results = NULL;
 
         parrot_pass_args(interp, ctx, caller_ctx, src_indexes, dest_indexes, PARROT_PASS_RESULTS);
     }
Index: src/ops/experimental.ops
===================================================================
--- src/ops/experimental.ops	(revision 17785)
+++ src/ops/experimental.ops	(working copy)
@@ -394,13 +394,14 @@
   opcode_t* arg_op;
   PMC *sig, *class;
   int typ;
+  parrot_context_t *ctx = CONTEXT(interp->ctx);
 
-  arg_op = interp->current_args;
+  arg_op = ctx->current_args;
   if (!arg_op) {
         real_exception(interp, NULL, NULL_REG_ACCESS,
             "No set_args with instantiate");
   }
-  sig = CONTEXT(interp->ctx)->constants[arg_op[1]]->u.key;
+  sig = ctx->constants[arg_op[1]]->u.key;
   ASSERT_SIG_PMC(sig);
   if (!SIG_ELEMS(sig)) {
         real_exception(interp, NULL, E_ValueError,
@@ -425,7 +426,7 @@
           break;
   }
   $1 = VTABLE_instantiate(interp, class, sig);
-  interp->current_args = NULL;
+  ctx->current_args = NULL;
   goto NEXT();
 }
 
Index: src/ops/pic.ops
===================================================================
--- src/ops/pic.ops	(revision 17785)
+++ src/ops/pic.ops	(working copy)
@@ -147,7 +147,7 @@
      * - yes, confusing but faster
      */
     ctx = CONTEXT(interp->ctx);
-    src_pc = interp->current_args;
+    src_pc = ctx->current_args;
     mic = (Parrot_MIC *) cur_opcode[1];
     caller_ctx = ctx->caller_ctx;
     if (src_pc) {
@@ -173,7 +173,7 @@
             --ctx->recursion_depth;
             ctx->caller_ctx = caller_ctx->caller_ctx;
             Parrot_free_context(interp, caller_ctx, 0);
-            interp->current_args = NULL;
+            ctx->current_args = NULL;
         }
 
         goto OFFSET(n);
@@ -200,12 +200,12 @@
     ccont = ctx->current_cont;
     cc = PMC_cont(ccont);
     if (!cc->address) {
-        interp->current_returns = CUR_OPCODE;
+        ctx->current_returns = CUR_OPCODE;
         n = PMC_int_val(mic->m.sig);
         goto OFFSET(n + 2);
     }
     caller_ctx = cc->to_ctx;
-    interp->current_args = NULL;
+    ctx->current_args = NULL;
     dest_pc = caller_ctx->current_results;
     if (dest_pc) {
         dest_pred = (void**) dest_pc - caller_ctx->pred_offset;
Index: src/gc/register.c
===================================================================
--- src/gc/register.c	(revision 17785)
+++ src/gc/register.c	(working copy)
@@ -230,27 +230,33 @@
 static void
 init_context(Interp *interp, parrot_context_t *ctx, parrot_context_t *old)
 {
-    ctx->ref_count = 0;                 /* TODO 1 - Exceptions !!! */
-    ctx->current_results = NULL;
+    ctx->ref_count         = 0;         /* TODO 1 - Exceptions !!! */
+    ctx->current_results   = NULL;
+    ctx->current_args      = NULL;
+    ctx->current_params    = NULL;
+    ctx->current_returns   = NULL;
     ctx->results_signature = NULL;
-    ctx->lex_pad = PMCNULL;
-    ctx->outer_ctx = NULL;
-    ctx->current_cont = NULL;
-    ctx->current_object = NULL; /* XXX who clears it?  */
+    ctx->args_signature    = NULL;
+    ctx->params_signature  = NULL;
+    ctx->returns_signature = NULL;
+    ctx->lex_pad           = PMCNULL;
+    ctx->outer_ctx         = NULL;
+    ctx->current_cont      = NULL;
+    ctx->current_object    = NULL; /* XXX who clears it?  */
     ctx->current_HLL = 0;
     if (old) {
         /* some items should better be COW copied */
-        ctx->constants = old->constants;
-        ctx->reg_stack = old->reg_stack;     /* XXX move into interpreter? */
-        ctx->user_stack = old->user_stack;   /* XXX move into interpreter? */
-        ctx->warns = old->warns;
-        ctx->errors = old->errors;
-        ctx->trace_flags = old->trace_flags;
-        ctx->pred_offset = old->pred_offset;
-        ctx->current_HLL = old->current_HLL;
+        ctx->constants         = old->constants;
+        ctx->reg_stack         = old->reg_stack;  /* XXX move into interpreter? */
+        ctx->user_stack        = old->user_stack; /* XXX move into interpreter? */
+        ctx->warns             = old->warns;
+        ctx->errors            = old->errors;
+        ctx->trace_flags       = old->trace_flags;
+        ctx->pred_offset       = old->pred_offset;
+        ctx->current_HLL       = old->current_HLL;
         ctx->current_namespace = old->current_namespace;
         /* end COW */
-        ctx->recursion_depth = old->recursion_depth;
+        ctx->recursion_depth   = old->recursion_depth;
     }
     /* other stuff is set inside Sub.invoke */
     clear_regs(interp, ctx);
Index: src/pic.c
===================================================================
--- src/pic.c	(revision 17785)
+++ src/pic.c	(working copy)
@@ -436,7 +436,7 @@
     }
     else {
         caller_ctx = ctx->caller_ctx;
-        args = interp->current_args;
+        args = ctx->current_args;
     }
     if (args) {
         const_nr = args[1];
@@ -510,7 +510,7 @@
     sig_args = (PMC*)(pc[1]);
     ASSERT_SIG_PMC(sig_args);
     n = SIG_ELEMS(sig_args);
-    interp->current_args = (opcode_t*)pc + ctx->pred_offset;
+    ctx->current_args = (opcode_t*)pc + ctx->pred_offset;
     pc += 2 + n;
     op = (opcode_t*)pc + ctx->pred_offset;
     if (*op != PARROT_OP_set_p_pc)
Index: src/inter_call.c
===================================================================
--- src/inter_call.c	(revision 17785)
+++ src/inter_call.c	(working copy)
@@ -59,8 +59,9 @@
 int
 Parrot_init_arg_nci(Interp *interp, struct call_state *st, const char *sig)
 {
-    Parrot_init_arg_op(interp, CONTEXT(interp->ctx), interp->current_args, &st->src);
-    Parrot_init_arg_sig(interp, CONTEXT(interp->ctx), sig, NULL, &st->dest);
+    parrot_context_t *ctx = CONTEXT(interp->ctx);
+    Parrot_init_arg_op(interp, ctx, ctx->current_args, &st->src);
+    Parrot_init_arg_sig(interp, ctx, sig, NULL, &st->dest);
     return 1;
 }
 
@@ -1072,15 +1073,15 @@
     PMC* dest_signature;
 
     if (param_or_result == PARROT_PASS_PARAMS) {
-        src_signature = interp->args_signature;
-        dest_signature = interp->params_signature;
-        interp->args_signature = NULL;
-        interp->params_signature = NULL;
+        src_signature = src_ctx->args_signature;
+        dest_signature = dest_ctx->params_signature;
+        src_ctx->args_signature = NULL;
+        dest_ctx->params_signature = NULL;
     }
     else /* (param_or_result == PARROT_PASS_RESULTS) */ {
-        src_signature = interp->returns_signature;
+        src_signature = src_ctx->returns_signature;
         dest_signature = dest_ctx->results_signature;
-        interp->returns_signature = NULL;
+        src_ctx->returns_signature = NULL;
         dest_ctx->results_signature = NULL;
     }
 
@@ -1119,13 +1120,11 @@
 int
 set_retval_util(Parrot_Interp interp, const char *sig, parrot_context_t *ctx, struct call_state *st)
 {
-    opcode_t *src_pc = interp->current_returns;
+    opcode_t *src_pc = ctx->current_returns;
     int todo = Parrot_init_arg_op(interp, ctx, src_pc, &st->src);
 
-    interp->current_returns = NULL;
-
     if (todo) {
-        todo = Parrot_init_arg_sig(interp, CONTEXT(interp->ctx), sig, NULL, &st->dest);
+        todo = Parrot_init_arg_sig(interp, ctx, sig, NULL, &st->dest);
         if (todo) {
             Parrot_fetch_arg(interp, st);
             Parrot_convert_arg(interp, st);
@@ -1448,13 +1447,13 @@
     }
 
     /* code from PCCINVOKE impl in PCCMETHOD.pm */
-    save_current_args = interp->current_args;
-    save_args_signature = interp->args_signature;
+    save_current_args   = ctx->current_args;
+    save_args_signature = ctx->args_signature;
     save_current_object = interp->current_object;
 
-    interp->current_args = arg_indexes;
-    interp->args_signature = args_sig;
-    ctx->current_results = result_indexes;
+    ctx->current_args      = arg_indexes;
+    ctx->args_signature    = args_sig;
+    ctx->current_results   = result_indexes;
     ctx->results_signature = results_sig;
 
 
@@ -1508,8 +1507,8 @@
     PObj_live_CLEAR(args_sig);
     PObj_live_CLEAR(results_sig);
     Parrot_pop_context(interp);
-    interp->current_args = save_current_args;
-    interp->args_signature = save_args_signature;
+    CONTEXT(interp->ctx)->current_args = save_current_args;
+    ctx->args_signature = save_args_signature;
     interp->current_object = save_current_object;
 }
 
Index: src/inter_run.c
===================================================================
--- src/inter_run.c	(revision 17785)
+++ src/inter_run.c	(working copy)
@@ -163,7 +163,7 @@
     const char *sig_p;
 
     old_ctx = CONTEXT(interp->ctx);
-    interp->current_cont  = new_ret_continuation_pmc(interp, NULL);
+    interp->current_cont   = new_ret_continuation_pmc(interp, NULL);
     interp->current_object = obj;
     dest = VTABLE_invoke(interp, sub, NULL);
     if (!dest)
@@ -319,9 +319,6 @@
      * running code from event handlers isn't fully reentrant due to
      * these interpreter variables - mainly related to calls
      */
-    cargs   = interp->current_args;
-    params  = interp->current_params;
-    returns = interp->current_returns;
     cont    = interp->current_cont;
     /* what else ? */
 
@@ -330,9 +327,6 @@
     va_end(args);
     retval = set_retval(interp, *sig, ctx);
 
-    interp->current_args     = cargs;
-    interp->current_params   = params;
-    interp->current_returns  = returns;
     interp->current_cont     = cont;
     return retval;
 }
Index: src/pmc/continuation.pmc
===================================================================
--- src/pmc/continuation.pmc	(revision 17785)
+++ src/pmc/continuation.pmc	(working copy)
@@ -356,7 +356,7 @@
             /* where caller wants result */
             to_ctx->current_results = cc->current_results;
         }
-        if (to_ctx->current_results && INTERP->current_args) {
+        if (to_ctx->current_results && from_ctx->current_args) {
             opcode_t *src_indexes, *dest_indexes;
             /*
              * the register pointer is already switched back
@@ -365,9 +365,10 @@
              * inside argument passing a DOD run is triggered
              * therefore we have to block DOD
              */
-            src_indexes = interp->current_args;
-            interp->current_args = NULL;
+            src_indexes = from_ctx->current_args;
             dest_indexes = to_ctx->current_results;
+            from_ctx->current_args = NULL;
+            to_ctx->current_results = NULL;
 
             Parrot_block_DOD(INTERP);
             parrot_pass_args(INTERP, from_ctx, to_ctx, src_indexes, dest_indexes,
@@ -376,7 +377,7 @@
         }
 
         /* switch segment */
-        INTERP->current_args = NULL;
+        from_ctx->current_args = NULL;
         if (INTERP->code != cc->seg) {
             Parrot_switch_to_cs(INTERP, cc->seg, 1);
         }
Index: src/pmc/integer.pmc
===================================================================
--- src/pmc/integer.pmc	(revision 17785)
+++ src/pmc/integer.pmc	(working copy)
@@ -90,7 +90,7 @@
         INTVAL init = 0;
 
         ret->vtable = INTERP->vtables[SELF->vtable->base_type];
-        arg_op = interp->current_args;
+        arg_op = CONTEXT(INTERP->ctx)->current_args;
         if (SIG_ELEMS(sig) == 2) {
             switch (SIG_ITEM(sig, 1)) {
                 case PARROT_ARG_I:
Index: src/jit/i386/core.jit
===================================================================
--- src/jit/i386/core.jit	(revision 17785)
+++ src/jit/i386/core.jit	(working copy)
@@ -1427,7 +1427,7 @@
     if (jit_info->code_type == JIT_CODE_FILE) {
         Parrot_jit_emit_get_INTERP(jit_info->native_ptr, emit_EAX);
         emitm_movl_i_m(NATIVECODE, jit_info->cur_op, emit_EAX, emit_None, 1,
-                offsetof(Interp, current_args));
+                offsetof(parrot_context_t, current_args));
     }
     else  {
         jit_set_args_pc(jit_info, interp,
Index: src/mmd.c
===================================================================
--- src/mmd.c	(revision 17785)
+++ src/mmd.c	(working copy)
@@ -988,7 +988,7 @@
      */
 
     arg_tuple = pmc_new(interp, enum_class_ResizableIntegerArray);
-    args_op = interp->current_args;
+    args_op = CONTEXT(interp->ctx)->current_args;
     if (!args_op)
         return arg_tuple;
     assert(*args_op == PARROT_OP_set_args_pc);
Index: lib/Parrot/Pmc2c/PCCMETHOD.pm
===================================================================
--- lib/Parrot/Pmc2c/PCCMETHOD.pm	(revision 17785)
+++ lib/Parrot/Pmc2c/PCCMETHOD.pm	(working copy)
@@ -381,12 +381,12 @@
 
     ctx->current_cont = ret_cont;
 
-    current_args = interp->current_args;
-    interp->current_args = NULL;
+    current_args = caller_ctx->current_args;
+    caller_ctx->current_args = NULL;
 
 $named_names
 
-    interp->params_signature = param_sig;
+    ctx->params_signature = param_sig;
     parrot_pass_args(interp, caller_ctx, ctx, current_args, param_indexes, PARROT_PASS_PARAMS);
 
     if (PObj_get_FLAGS(ccont) & SUB_FLAG_TAILCALL) {
@@ -394,7 +394,6 @@
         --ctx->recursion_depth;
         ctx->caller_ctx = caller_ctx->caller_ctx;
         Parrot_free_context(interp, caller_ctx, 0);
-        interp->current_args = NULL;
     }
     /* BEGIN PARMS SCOPE */
     {
@@ -422,7 +421,7 @@
             internal_exception(1, "No caller_ctx for continuation \%p.", ccont);
         }
 
-        interp->returns_signature = return_sig;
+        ctx->returns_signature = return_sig;
         parrot_pass_args(interp, ctx, caller_ctx, return_indexes, caller_ctx->current_results, PARROT_PASS_RESULTS);
     }
 
@@ -502,12 +501,12 @@
       parrot_context_t *ctx = Parrot_push_context(interp, n_regs_used);
       PMC* pccinvoke_meth;
 
-      opcode_t* save_current_args = interp->current_args;
-      PMC* save_args_signature = interp->args_signature;
+      opcode_t* save_current_args = ctx->current_args;
+      PMC* save_args_signature = ctx->args_signature;
       PMC* save_current_object = interp->current_object;
 
-      interp->current_args = arg_indexes;
-      interp->args_signature = args_sig;
+      ctx->current_args = arg_indexes;
+      ctx->args_signature = args_sig;
       ctx->current_results = result_indexes;
       ctx->results_signature = results_sig;
 
@@ -532,8 +531,8 @@
       PObj_live_CLEAR(args_sig);
       PObj_live_CLEAR(results_sig);
       Parrot_pop_context(interp);
-      interp->current_args = save_current_args;
-      interp->args_signature = save_args_signature;
+      CONTEXT(interp->ctx)->current_args = save_current_args;
+      ctx->args_signature = save_args_signature;
       interp->current_object = save_current_object;
     }
     /*END PCCONVOKE $method_name */
Index: include/parrot/interpreter.h
===================================================================
--- include/parrot/interpreter.h	(revision 17785)
+++ include/parrot/interpreter.h	(working copy)
@@ -225,8 +225,14 @@
     opcode_t *current_pc;       /* program counter of Sub invocation */
     PMC *current_namespace;     /* The namespace we're currently in */
     INTVAL current_HLL;         /* see also src/hll.c */
+    opcode_t *current_args;     /* ptr into code with set_args opcode */
+    opcode_t *current_params;   /* ptr into code with get_params opcode */
     opcode_t *current_results;  /* ptr into code with get_results opcode */
+    opcode_t *current_returns;  /* ptr into code with set_returns opcode */
     PMC *results_signature;     /* results signature pmc if it is non-const */
+    PMC *args_signature;        /* args signature pmc if it is non-const */
+    PMC *params_signature;      /* params signature pmc if it is non-const */
+    PMC *returns_signature;     /* returns signature pmc if it is non-const */
     /* deref the constants - we need it all the time */
     struct PackFile_Constant ** constants;
     /* code->prederefed.code - code->base.data in opcodes
@@ -391,12 +397,6 @@
 
     UINTVAL gc_generation;                    /* GC generation number */
 
-    opcode_t *current_args;                   /* ptr into code with set_args opcode */
-    opcode_t *current_params;                 /* ptr into code with get_params opcode */
-    opcode_t *current_returns;                /* ptr into code with get_returns opcode */
-    PMC *args_signature;                      /* args signature pmc if it is non-const */
-    PMC *params_signature;                    /* params signature pmc if it is non-const */
-    PMC *returns_signature;                   /* returns signature pmc if it is non-const */
     /* during a call sequencer the caller fills these objects
      * inside the invoke these get moved to the context structure
      */

Reply via email to