Merge op_pmreplstart and op_pmstash/op_pmstashpv into a union in
Nicholas Clark [Fri, 6 Apr 2007 23:31:14 +0000 (23:31 +0000)]
PMOP, as both pointers never need to be set at the same time.

p4raw-id: //depot/perl@30860

dump.c
ext/B/B.xs
op.c
op.h
pp_ctl.c

diff --git a/dump.c b/dump.c
index e85e5e9..8a6c124 100644 (file)
--- a/dump.c
+++ b/dump.c
@@ -673,13 +673,13 @@ S_sequence(pTHX_ register const OP *o)
            sequence_tail(cLOOPo->op_lastop);
            break;
 
-       case OP_QR:
-       case OP_MATCH:
        case OP_SUBST:
            hv_store(Sequence, key, len, newSVuv(++PL_op_seq), 0);
-           sequence_tail(cPMOPo->op_pmreplstart);
+           sequence_tail(cPMOPo->op_pmstashstartu.op_pmreplstart);
            break;
 
+       case OP_QR:
+       case OP_MATCH:
        case OP_HELEM:
            break;
 
index 9d62ff2..717dbf1 100644 (file)
@@ -513,7 +513,11 @@ oplist(pTHX_ OP *o, SV **SP)
        XPUSHs(opsv);
         switch (o->op_type) {
        case OP_SUBST:
+#if PERL_VERSION >= 9
+            SP = oplist(aTHX_ cPMOPo->op_pmstashstartu.op_pmreplstart, SP);
+#else
             SP = oplist(aTHX_ cPMOPo->op_pmreplstart, SP);
+#endif
             continue;
        case OP_SORT:
            if (o->op_flags & OPf_STACKED && o->op_flags & OPf_SPECIAL) {
@@ -978,14 +982,18 @@ LISTOP_children(o)
         RETVAL
 
 #define PMOP_pmreplroot(o)     o->op_pmreplroot
-#define PMOP_pmreplstart(o)    o->op_pmreplstart
+#if PERL_VERSION >= 9
+#  define PMOP_pmreplstart(o)  o->op_pmstashstartu.op_pmreplstart
+#else
+#  define PMOP_pmreplstart(o)  o->op_pmreplstart
+#endif
 #define PMOP_pmnext(o)         o->op_pmnext
 #define PMOP_pmregexp(o)       PM_GETRE(o)
 #ifdef USE_ITHREADS
 #define PMOP_pmoffset(o)       o->op_pmoffset
-#define PMOP_pmstashpv(o)      o->op_pmstashpv
+#define PMOP_pmstashpv(o)      PmopSTASHPV(o);
 #else
-#define PMOP_pmstash(o)                o->op_pmstash
+#define PMOP_pmstash(o)                PmopSTASH(o);
 #endif
 #define PMOP_pmflags(o)                o->op_pmflags
 
diff --git a/op.c b/op.c
index bb9dc60..9d9494b 100644 (file)
--- a/op.c
+++ b/op.c
@@ -3525,7 +3525,8 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg)
            repl->op_next = (OP*)rcop;
 
            pm->op_pmreplroot = scalar((OP*)rcop);
-           pm->op_pmreplstart = LINKLIST(rcop);
+           assert(!(pm->op_pmflags & PMf_ONCE));
+           pm->op_pmstashstartu.op_pmreplstart = LINKLIST(rcop);
            rcop->op_next = 0;
        }
     }
@@ -8033,10 +8034,12 @@ Perl_peep(pTHX_ register OP *o)
 
        case OP_SUBST:
            o->op_opt = 1;
-           while (cPMOP->op_pmreplstart &&
-                  cPMOP->op_pmreplstart->op_type == OP_NULL)
-               cPMOP->op_pmreplstart = cPMOP->op_pmreplstart->op_next;
-           peep(cPMOP->op_pmreplstart);
+           assert(!(cPMOP->op_pmflags & PMf_ONCE));
+           while (cPMOP->op_pmstashstartu.op_pmreplstart &&
+                  cPMOP->op_pmstashstartu.op_pmreplstart->op_type == OP_NULL)
+               cPMOP->op_pmstashstartu.op_pmreplstart
+                   = cPMOP->op_pmstashstartu.op_pmreplstart->op_next;
+           peep(cPMOP->op_pmstashstartu.op_pmreplstart);
            break;
 
        case OP_EXEC:
@@ -8427,7 +8430,9 @@ Perl_peep(pTHX_ register OP *o)
        
        case OP_QR:
        case OP_MATCH:
-           assert (!cPMOP->op_pmreplstart);
+           if (!(cPMOP->op_pmflags & PMf_ONCE)) {
+               assert (!cPMOP->op_pmstashstartu.op_pmreplstart);
+           }
            /* FALL THROUGH */
        default:
            o->op_opt = 1;
diff --git a/op.h b/op.h
index 36a1687..31bce2f 100644 (file)
--- a/op.h
+++ b/op.h
@@ -319,23 +319,20 @@ struct pmop {
     OP *       op_first;
     OP *       op_last;
     OP *       op_pmreplroot; /* (type is really union {OP*,GV*,PADOFFSET}) */
-    OP *       op_pmreplstart;
 #ifdef USE_ITHREADS
     IV          op_pmoffset;
 #else
     REGEXP *    op_pmregexp;            /* compiled expression */
 #endif
     U32                op_pmflags;
-    /* This field is only needed so that PMOPs can delete themselves from the
-       list held by the stash. In turn, that list is only needed for reset
-       to work correctly, and is now only a list of ops used by ?? matches,
-       which are rare. Hence it would be useful if we could find a way to
-       shave it. */
+    union {
+       OP *    op_pmreplstart; /* Only used in OP_SUBST */
 #ifdef USE_ITHREADS
-    char *     op_pmstashpv;
+       char *  op_pmstashpv;   /* Only used in OP_MATCH, with PMf_ONCE set */
 #else
-    HV *       op_pmstash;
+       HV *    op_pmstash;
 #endif
+    }          op_pmstashstartu;
 };
 
 #ifdef USE_ITHREADS
@@ -357,7 +354,9 @@ struct pmop {
 #define PMf_RETAINT    0x0001          /* taint $1 etc. if target tainted */
 #define PMf_ONCE       0x0002          /* match successfully only once per
                                            reset, with related flag RXf_USED
-                                           in re->extflags holding state */
+                                           in re->extflags holding state.
+                                          This is used only for ?? matches,
+                                          and only on OP_MATCH and OP_QR */
 
 #define PMf_UNUSED     0x0004          /* free for use */
 #define PMf_MAYBE_CONST        0x0008          /* replacement contains variables */
@@ -386,18 +385,35 @@ struct pmop {
 
 #ifdef USE_ITHREADS
 
-#  define PmopSTASHPV(o)       ((o)->op_pmstashpv)
-#  define PmopSTASHPV_set(o,pv)        (PmopSTASHPV(o) = savesharedpv(pv))
+#  define PmopSTASHPV(o)                                               \
+    (((o)->op_pmflags & PMf_ONCE) ? (o)->op_pmstashstartu.op_pmstashpv : NULL)
+#  if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
+#    define PmopSTASHPV_set(o,pv)      ({                              \
+       assert((o)->op_pmflags & PMf_ONCE);                             \
+       ((o)->op_pmstashstartu.op_pmstashpv = savesharedpv(pv));        \
+    })
+#  else
+#    define PmopSTASHPV_set(o,pv)                                      \
+    ((o)->op_pmstashstartu.op_pmstashpv = savesharedpv(pv))
+#  endif
 #  define PmopSTASH(o)         (PmopSTASHPV(o) \
-                                ? gv_stashpv(PmopSTASHPV(o),GV_ADD) : NULL)
+                                ? gv_stashpv((o)->op_pmstashstartu.op_pmstashpv,GV_ADD) : NULL)
 #  define PmopSTASH_set(o,hv)  PmopSTASHPV_set(o, ((hv) ? HvNAME_get(hv) : NULL))
 #  define PmopSTASH_free(o)    PerlMemShared_free(PmopSTASHPV(o))
 
 #else
-#  define PmopSTASH(o)         ((o)->op_pmstash)
-#  define PmopSTASH_set(o,hv)  ((o)->op_pmstash = (hv))
+#  define PmopSTASH(o)                                                 \
+    (((o)->op_pmflags & PMf_ONCE) ? (o)->op_pmstashstartu.op_pmstash : NULL)
+#  if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
+#    define PmopSTASH_set(o,hv)                ({                              \
+       assert((o)->op_pmflags & PMf_ONCE);                             \
+       ((o)->op_pmstashstartu.op_pmstash = (hv));                      \
+    })
+#  else
+#    define PmopSTASH_set(o,hv)        ((o)->op_pmstashstartu.op_pmstash = (hv))
+#  endif
 #  define PmopSTASHPV(o)       (PmopSTASH(o) ? HvNAME_get(PmopSTASH(o)) : NULL)
-   /* op_pmstash is not refcounted */
+   /* op_pmstashstartu.op_pmstash is not refcounted */
 #  define PmopSTASHPV_set(o,pv)        PmopSTASH_set((o), gv_stashpv(pv,GV_ADD))
 #  define PmopSTASH_free(o)    
 #endif
index e01d7e5..63b7039 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -302,7 +302,7 @@ PP(pp_substcont)
        (void)ReREFCNT_inc(rx);
     cx->sb_rxtainted |= RX_MATCH_TAINTED(rx);
     rxres_save(&cx->sb_rxres, rx);
-    RETURNOP(pm->op_pmreplstart);
+    RETURNOP(pm->op_pmstashstartu.op_pmreplstart);
 }
 
 void