Hi,

chromatic wrote:
3) PCC argument processing is slow. I've looked over Parrot_pass_args and Parrot_process_args several times in the past few months, and I didn't see any obvious speedups or tricks. However, we do spend a lot of time shuffling data back and forth, and something (instinct, blind desire, lower blood sugar than normal) suggests that we already *know* some of this information already. That is, at the point of a call we know if there are slurpy or named arguments and if the invoked function wants to bind slurpy or named parameters. It seems like we could have a fast path for that common operation... somehow.
I thought that detecting when the signature on the caller and callee side were identical and fast-tracking that might help. I stuck in something to count how many times this happened. It was the case in 23% of calls while compiling Rakudo. So I did the optimisation in the attached patch, which basically just copies arguments from one set of registers to the other about as efficiently as I can see how to do it.

The end result? I can't actually detect enough of a difference to make me think I've really improved anything. Not in the compilation time of Rakudo's actions.pm, nor when I took a Perl 6 Ackerman's function implementation and ran it under Rakudo.

Jonathan
Index: src/inter_call.c
===================================================================
--- src/inter_call.c    (revision 26955)
+++ src/inter_call.c    (working copy)
@@ -1520,12 +1520,45 @@
     Parrot_init_arg_indexes_and_sig_pmc(interp, dest_ctx, dest_indexes,
         dest_signature, &st.dest);
 
-    Parrot_process_args(interp, &st, param_or_result);
+    if (st.src.u.op.signature == st.dest.u.op.signature && 
!PMC_IS_NULL(st.src.u.op.signature)) {
+        /* Identical signatures, so we can fast-track it. */
+        PMC *sig = st.src.u.op.signature;
+        int sig_length = st.src.n;
+        opcode_t *src_idxs = st.src.u.op.pc;
+        opcode_t *dest_idxs = st.dest.u.op.pc;
+        int i;
+        for (i = 0; i < sig_length; i++) {
+            const int constant = PARROT_ARG_CONSTANT_ISSET(SIG_ITEM(sig, i));
+            int src_idx = src_idxs[i];
+            int dest_idx = dest_idxs[i];
+            switch (PARROT_ARG_TYPE_MASK_MASK(SIG_ITEM(sig, i))) {
+                case PARROT_ARG_INTVAL:
+                    CTX_REG_INT(st.dest.ctx, dest_idx) = constant ?
+                        src_idx : CTX_REG_INT(st.src.ctx, src_idx);
+                    break;
+                case PARROT_ARG_STRING:
+                    CTX_REG_STR(st.dest.ctx, dest_idx) = constant ?
+                        st.src.ctx->constants[src_idx]->u.string : 
CTX_REG_STR(st.src.ctx, src_idx);
+                    break;
+                case PARROT_ARG_FLOATVAL:
+                    CTX_REG_NUM(st.dest.ctx, dest_idx) = constant ?
+                        st.src.ctx->constants[src_idx]->u.number : 
CTX_REG_NUM(st.src.ctx, src_idx);
+                    break;
+                case PARROT_ARG_PMC:
+                    CTX_REG_PMC(st.dest.ctx, dest_idx) = constant ?
+                        st.src.ctx->constants[src_idx]->u.key : 
CTX_REG_PMC(st.src.ctx, src_idx);
+                    break;
+            }
+        }
+    }
+    else {
+        Parrot_process_args(interp, &st, param_or_result);
 
-    /* If we created a slurpy, we had to DOD register it so it did not get
-     * collected during arg processing; we'll now unregister it. */
-    if (st.dest.slurp)
-        dod_unregister_pmc(interp, st.dest.slurp);
+        /* If we created a slurpy, we had to DOD register it so it did not get
+         * collected during arg processing; we'll now unregister it. */
+        if (st.dest.slurp)
+            dod_unregister_pmc(interp, st.dest.slurp);
+    }
 }
 
 

Reply via email to