]> git.vpit.fr Git - perl/modules/autovivification.git/blobdiff - autovivification.xs
This is 0.08
[perl/modules/autovivification.git] / autovivification.xs
index 98140687672dd2512a136a8f79186ea472d2b87a..d07fd07f076645328255602c9ac4cf766fe3b82a 100644 (file)
 
 #define A_HAS_PERL(R, V, S) (PERL_REVISION > (R) || (PERL_REVISION == (R) && (PERL_VERSION > (V) || (PERL_VERSION == (V) && (PERL_SUBVERSION >= (S))))))
 
-#define A_HAS_PERL_EXACT(R, V, S) ((PERL_REVISION == (R)) && (PERL_VERSION == (V)) && (PERL_SUBVERSION == (S)))
-
-#undef ENTERn
-#if defined(ENTER_with_name) && !A_HAS_PERL(5, 11, 4)
-# define ENTERn(N) ENTER_with_name(N)
-#else
-# define ENTERn(N) ENTER
-#endif
-
-#undef LEAVEn
-#if defined(LEAVE_with_name) && !A_HAS_PERL(5, 11, 4)
-# define LEAVEn(N) LEAVE_with_name(N)
-#else
-# define LEAVEn(N) LEAVE
-#endif
-
 #ifndef A_WORKAROUND_REQUIRE_PROPAGATION
 # define A_WORKAROUND_REQUIRE_PROPAGATION !A_HAS_PERL(5, 10, 1)
 #endif
@@ -130,6 +114,11 @@ typedef struct {
 
 #include "ptable.h"
 
+/* PerlMemShared_free() needs the [ap]PTBLMS_? default values */
+#define ptable_seen_store(T, K, V) ptable_seen_store(aPTBLMS_ (T), (K), (V))
+#define ptable_seen_clear(T)       ptable_seen_clear(aPTBLMS_ (T))
+#define ptable_seen_free(T)        ptable_seen_free(aPTBLMS_ (T))
+
 #endif /* !A_HAS_RPEEP */
 
 #define A_NEED_CXT ((A_THREADSAFE && A_WORKAROUND_REQUIRE_PROPAGATION) || !A_HAS_RPEEP)
@@ -309,7 +298,7 @@ STATIC UV a_detag(pTHX_ const SV *hint) {
      ? SvUVX(H)    \
      : (SvPOK(H)   \
         ? sv_2uv(SvLEN(H) ? (H) : sv_mortalcopy(H)) \
-       : 0        \
+        : 0        \
        )           \
      )             \
   : 0)
@@ -368,6 +357,7 @@ typedef struct {
 
 /* PerlMemShared_free() needs the [ap]PTBLMS_? default values */
 #define ptable_map_store(T, K, V) ptable_map_store(aPTBLMS_ (T), (K), (V))
+#define ptable_map_delete(T, K)   ptable_map_delete(aPTBLMS_ (T), (K))
 
 STATIC ptable *a_op_map = NULL;
 
@@ -615,8 +605,6 @@ STATIC OP *a_pp_rv2av(pTHX) {
    PUSHs(av);
    RETURN;
   }
- } else {
-  PL_op->op_ppaddr = oi->old_pp;
  }
 
  return oi->old_pp(aTHX);
@@ -634,8 +622,6 @@ STATIC OP *a_pp_rv2hv_simple(pTHX) {
  if (oi->flags & A_HINT_DEREF) {
   if (a_undef(TOPs))
    RETURN;
- } else {
-  PL_op->op_ppaddr = oi->old_pp;
  }
 
  return oi->old_pp(aTHX);
@@ -656,8 +642,6 @@ STATIC OP *a_pp_rv2hv(pTHX) {
    PUSHs(hv);
    RETURN;
   }
- } else {
-  PL_op->op_ppaddr = oi->old_pp;
  }
 
  return oi->old_pp(aTHX);
@@ -672,17 +656,12 @@ STATIC OP *a_pp_deref(pTHX) {
  dSP;
 
  oi = a_map_fetch(PL_op);
- flags = oi->flags;
 
+ flags = oi->flags;
  if (flags & A_HINT_DEREF) {
   OP *o;
-  U8 old_private;
 
-deref:
-  old_private       = PL_op->op_private;
-  PL_op->op_private = ((old_private & ~OPpDEREF) | OPpLVAL_DEFER);
   o = oi->old_pp(aTHX);
-  PL_op->op_private = old_private;
 
   if (flags & (A_HINT_NOTIFY|A_HINT_STORE)) {
    SPAGAIN;
@@ -697,21 +676,8 @@ deref:
   }
 
   return o;
- } else if ((flags & ~A_HINT_ROOT)
-                    && (PL_op->op_private & OPpDEREF || flags & A_HINT_ROOT)) {
-  /* Decide if the expression must autovivify or not.
-   * This branch should be called only once by expression. */
-  flags = a_map_resolve(PL_op, oi);
-
-  /* We need the updated flags value in the deref branch. */
-  if (flags & A_HINT_DEREF)
-   goto deref;
  }
 
- /* This op doesn't need to skip autovivification, so restore the original
-  * state. */
- PL_op->op_ppaddr = oi->old_pp;
-
  return oi->old_pp(aTHX);
 }
 
@@ -995,7 +961,6 @@ A_PEEP_REC_PROTO {
 # define a_peep_rec(O) a_peep_rec(aTHX_ (O))
 #endif /* A_HAS_RPEEP */
  dA_MAP_THX;
- const a_op_info *oi;
 
 #if !A_HAS_RPEEP
  if (ptable_fetch(seen, o))
@@ -1003,6 +968,9 @@ A_PEEP_REC_PROTO {
 #endif
 
  for (; o; o = o->op_next) {
+  const a_op_info *oi = NULL;
+  UV flags = 0;
+
 #if !A_HAS_RPEEP
   ptable_seen_store(seen, o, o);
 #endif
@@ -1015,6 +983,39 @@ A_PEEP_REC_PROTO {
       o->op_ppaddr = a_pp_deref;
      }
     }
+    /* FALLTHROUGH */
+   case OP_AELEM:
+   case OP_AELEMFAST:
+   case OP_HELEM:
+   case OP_RV2SV:
+    if (o->op_ppaddr != a_pp_deref)
+     break;
+    oi = a_map_fetch(o);
+    if (!oi)
+     break;
+    flags = oi->flags;
+    if (!(flags & A_HINT_DEREF)
+        && (flags & A_HINT_DO)
+        && (o->op_private & OPpDEREF || flags & A_HINT_ROOT)) {
+     /* Decide if the expression must autovivify or not. */
+     flags = a_map_resolve(o, oi);
+    }
+    if (flags & A_HINT_DEREF)
+     o->op_private = ((o->op_private & ~OPpDEREF) | OPpLVAL_DEFER);
+    else
+     o->op_ppaddr  = oi->old_pp;
+    break;
+   case OP_RV2AV:
+   case OP_RV2HV:
+    if (   o->op_ppaddr != a_pp_rv2av
+        && o->op_ppaddr != a_pp_rv2hv
+        && o->op_ppaddr != a_pp_rv2hv_simple)
+     break;
+    oi = a_map_fetch(o);
+    if (!oi)
+     break;
+    if (!(oi->flags & A_HINT_DEREF))
+     o->op_ppaddr  = oi->old_pp;
     break;
 #if !A_HAS_RPEEP
    case OP_MAPWHILE:
@@ -1064,15 +1065,8 @@ STATIC void a_peep(pTHX_ OP *o) {
  ptable_seen_clear(seen);
 #endif /* !A_HAS_RPEEP */
 
-#if A_HAS_PERL_EXACT(5, 8, 2)
- /* 5.8.2's peephole optimizer has a naughty bug with stub ops coming from
-  * sub { }. */
- a_peep_rec(o);
- a_old_peep(aTHX_ o);
-#else
  a_old_peep(aTHX_ o);
  a_peep_rec(o);
-#endif
 }
 
 /* --- Interpreter setup/teardown ------------------------------------------ */