This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
add PL_curstackinfo->si_cxsubix field
authorDavid Mitchell <davem@iabyn.com>
Tue, 17 Sep 2019 13:20:40 +0000 (14:20 +0100)
committerDavid Mitchell <davem@iabyn.com>
Thu, 19 Sep 2019 07:42:46 +0000 (08:42 +0100)
This tracks the most recent sub/eval/format context pushed onto the
context stack. Then make dopopto_cursub use it.

The previous value is saved in the cxt struct, and is restored whenever
the context is popped.

This adds a tiny overhead for every sub call, but speeds up other
operations, such as determining the caller context when returning a
value from a sub - this has to be dpne for every sub call where the last
expression is context sensitive, so its often a win.

cop.h
inline.h
pp_ctl.c
scope.c
sv.c

diff --git a/cop.h b/cop.h
index 00396f0..f9bf852 100644 (file)
--- a/cop.h
+++ b/cop.h
@@ -585,6 +585,7 @@ C<*len>.  Upon return, C<*flags> will be set to either C<SVf_UTF8> or 0.
 /* subroutine context */
 struct block_sub {
     OP *       retop;  /* op to execute on exit from sub */
+    I32         old_cxsubix;  /* previous value of si_cxsubix */
     /* Above here is the same for sub, format and eval.  */
     PAD                *prevcomppad; /* the caller's PL_comppad */
     CV *       cv;
@@ -597,6 +598,7 @@ struct block_sub {
 /* format context */
 struct block_format {
     OP *       retop;  /* op to execute on exit from sub */
+    I32         old_cxsubix;  /* previous value of si_cxsubix */
     /* Above here is the same for sub, format and eval.  */
     PAD                *prevcomppad; /* the caller's PL_comppad */
     CV *       cv;
@@ -663,6 +665,7 @@ struct block_format {
 /* eval context */
 struct block_eval {
     OP *       retop;  /* op to execute on exit from eval */
+    I32         old_cxsubix;  /* previous value of si_cxsubix */
     /* Above here is the same for sub, format and eval.  */
     SV *       old_namesv;
     OP *       old_eval_root;
@@ -1026,6 +1029,7 @@ struct stackinfo {
     struct stackinfo * si_next;
     I32                        si_cxix;        /* current context index */
     I32                        si_cxmax;       /* maximum allocated index */
+    I32                        si_cxsubix;     /* topmost sub/eval/format */
     I32                        si_type;        /* type of runlevel */
     I32                        si_markoff;     /* offset where markstack begins for us.
                                         * currently used only with DEBUGGING,
@@ -1072,6 +1076,7 @@ typedef struct stackinfo PERL_SI;
        }                                                               \
        next->si_type = type;                                           \
        next->si_cxix = -1;                                             \
+       next->si_cxsubix = -1;                                          \
         PUSHSTACK_INIT_HWM(next);                                       \
        AvFILLp(next->si_stack) = 0;                                    \
        SWITCHSTACK(PL_curstack,next->si_stack);                        \
index aa4e7b8..84b0bfc 100644 (file)
--- a/inline.h
+++ b/inline.h
@@ -2134,6 +2134,8 @@ Perl_cx_pushsub(pTHX_ PERL_CONTEXT *cx, CV *cv, OP *retop, bool hasargs)
     PERL_ARGS_ASSERT_CX_PUSHSUB;
 
     PERL_DTRACE_PROBE_ENTRY(cv);
+    cx->blk_sub.old_cxsubix     = PL_curstackinfo->si_cxsubix;
+    PL_curstackinfo->si_cxsubix = cx - PL_curstackinfo->si_cxstack;
     cx->blk_sub.cv = cv;
     cx->blk_sub.olddepth = CvDEPTH(cv);
     cx->blk_sub.prevcomppad = PL_comppad;
@@ -2160,6 +2162,7 @@ Perl_cx_popsub_common(pTHX_ PERL_CONTEXT *cx)
     CvDEPTH(cv) = cx->blk_sub.olddepth;
     cx->blk_sub.cv = NULL;
     SvREFCNT_dec(cv);
+    PL_curstackinfo->si_cxsubix = cx->blk_sub.old_cxsubix;
 }
 
 
@@ -2206,6 +2209,8 @@ Perl_cx_pushformat(pTHX_ PERL_CONTEXT *cx, CV *cv, OP *retop, GV *gv)
 {
     PERL_ARGS_ASSERT_CX_PUSHFORMAT;
 
+    cx->blk_format.old_cxsubix = PL_curstackinfo->si_cxsubix;
+    PL_curstackinfo->si_cxsubix= cx - PL_curstackinfo->si_cxstack;
     cx->blk_format.cv          = cv;
     cx->blk_format.retop       = retop;
     cx->blk_format.gv          = gv;
@@ -2239,6 +2244,7 @@ Perl_cx_popformat(pTHX_ PERL_CONTEXT *cx)
     cx->blk_format.cv = NULL;
     --CvDEPTH(cv);
     SvREFCNT_dec_NN(cv);
+    PL_curstackinfo->si_cxsubix = cx->blk_format.old_cxsubix;
 }
 
 
@@ -2247,6 +2253,8 @@ Perl_cx_pusheval(pTHX_ PERL_CONTEXT *cx, OP *retop, SV *namesv)
 {
     PERL_ARGS_ASSERT_CX_PUSHEVAL;
 
+    cx->blk_eval.old_cxsubix   = PL_curstackinfo->si_cxsubix;
+    PL_curstackinfo->si_cxsubix= cx - PL_curstackinfo->si_cxstack;
     cx->blk_eval.retop         = retop;
     cx->blk_eval.old_namesv    = namesv;
     cx->blk_eval.old_eval_root = PL_eval_root;
@@ -2282,6 +2290,7 @@ Perl_cx_popeval(pTHX_ PERL_CONTEXT *cx)
         cx->blk_eval.old_namesv = NULL;
         SvREFCNT_dec_NN(sv);
     }
+    PL_curstackinfo->si_cxsubix = cx->blk_eval.old_cxsubix;
 }
 
 
index 5dee09d..ef1ff8d 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
 #define RUN_PP_CATCHABLY(thispp) \
     STMT_START { if (CATCH_GET) return docatch(thispp); } STMT_END
 
-#define dopopto_cursub()       dopoptosub_at(cxstack, cxstack_ix)
+#define dopopto_cursub() \
+    (PL_curstackinfo->si_cxsubix >= 0        \
+        ? PL_curstackinfo->si_cxsubix        \
+        : dopoptosub_at(cxstack, cxstack_ix))
+
 #define dopoptosub(plop)       dopoptosub_at(cxstack, (plop))
 
 PP(pp_wantarray)
diff --git a/scope.c b/scope.c
index 9b1393c..c661644 100644 (file)
--- a/scope.c
+++ b/scope.c
@@ -82,6 +82,7 @@ Perl_new_stackinfo(pTHX_ I32 stitems, I32 cxitems)
     si->si_next = 0;
     si->si_cxmax = cxitems - 1;
     si->si_cxix = -1;
+    si->si_cxsubix = -1;
     si->si_type = PERLSI_UNDEF;
     Newx(si->si_cxstack, cxitems, PERL_CONTEXT);
     /* Without any kind of initialising CX_PUSHSUBST()
diff --git a/sv.c b/sv.c
index e088e5c..0b878a4 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -14690,6 +14690,7 @@ Perl_si_dup(pTHX_ PERL_SI *si, CLONE_PARAMS* param)
 
     nsi->si_stack      = av_dup_inc(si->si_stack, param);
     nsi->si_cxix       = si->si_cxix;
+    nsi->si_cxsubix    = si->si_cxsubix;
     nsi->si_cxmax      = si->si_cxmax;
     nsi->si_cxstack    = cx_dup(si->si_cxstack, si->si_cxix, si->si_cxmax, param);
     nsi->si_type       = si->si_type;