]> git.vpit.fr Git - perl/modules/autovivification.git/blobdiff - autovivification.xs
Document that the multideref implementation is only used for exists/delete
[perl/modules/autovivification.git] / autovivification.xs
index 0a7330ee3af30d89278b60b8404e0c810300ac71..46422c4002ce3cc80e2aae522e84e076b8672fd9 100644 (file)
@@ -800,32 +800,38 @@ static OP *a_pp_root_binop(pTHX) {
 
 /* ... pp_multideref ....................................................... */
 
+/* This pp replacement is actually only called for topmost exists/delete ops,
+ * because we hijack the [ah]elem check functions and this disables the
+ * optimization for lvalue and rvalue dereferencing. In particular, the
+ * OPf_MOD branches should never be covered. In the future, the multideref
+ * optimization might also be disabled for custom exists/delete check functions,
+ * which will make this section unnecessary. However, the code tries to be as
+ * general as possible in case I think of a way to reenable the multideref
+ * optimization even when this module is in use. */
+
 static UV a_do_multideref(const OP *o, UV flags) {
- UV isexdel;
+ UV isexdel, other_flags;
 
  assert(o->op_type == OP_MULTIDEREF);
 
isexdel = o->op_private & (OPpMULTIDEREF_EXISTS|OPpMULTIDEREF_DELETE);
other_flags = flags & ~A_HINT_DO;
 
+ isexdel = o->op_private & (OPpMULTIDEREF_EXISTS|OPpMULTIDEREF_DELETE);
  if (isexdel) {
   if (isexdel & OPpMULTIDEREF_EXISTS) {
-   if (flags & A_HINT_EXISTS)
-    return A_HINT_EXISTS;
+   flags &= A_HINT_EXISTS;
   } else {
-   if (flags & A_HINT_DELETE)
-    return A_HINT_DELETE;
+   flags &= A_HINT_DELETE;
   }
  } else {
   if (o->op_flags & OPf_MOD) {
-   if (flags & A_HINT_STORE)
-    return A_HINT_STORE;
+   flags &= A_HINT_STORE;
   } else {
-   if (flags & A_HINT_FETCH)
-    return A_HINT_FETCH;
+   flags &= A_HINT_FETCH;
   }
  }
 
- return 0;
+ return flags ? (flags | other_flags) : 0;
 }
 
 static SV *a_do_fake_pp(pTHX_ OP *op) {
@@ -903,7 +909,6 @@ static OP *a_pp_multideref(pTHX) {
  UNOP_AUX_item *items;
  UV  actions;
  UV  flags = 0;
- UV  deref = 0;
  SV *sv    = NULL;
  dSP;
 
@@ -911,9 +916,8 @@ static OP *a_pp_multideref(pTHX) {
   dA_MAP_THX;
   const a_op_info *oi = a_map_fetch(PL_op);
   assert(oi);
-  flags = oi->flags;
-  deref = a_do_multideref(PL_op, flags);
-  if (!deref)
+  flags = a_do_multideref(PL_op, oi->flags);
+  if (!flags)
    return oi->old_pp(aTHX);
  }
 
@@ -987,7 +991,7 @@ check_elem:
      }
      PL_multideref_pc = items;
      if (actions & MDEREF_FLAG_last) {
-      switch (deref) {
+      switch (flags & A_HINT_DO) {
        case A_HINT_FETCH:
         sv = a_do_pp_afetch(sv, esv);
         break;
@@ -1061,7 +1065,7 @@ do_HV_helem:
      }
      PL_multideref_pc = items;
      if (actions & MDEREF_FLAG_last) {
-      switch (deref) {
+      switch (flags & A_HINT_DO) {
        case A_HINT_FETCH:
         sv = a_do_pp_hfetch(sv, key);
         break;
@@ -1088,9 +1092,9 @@ do_HV_helem:
  }
 
 ret_undef:
- if ((flags & A_HINT_NOTIFY) || (deref == A_HINT_STORE))
+ if (flags & (A_HINT_NOTIFY|A_HINT_STORE))
   a_cannot_vivify(flags);
- if (deref == A_HINT_EXISTS)
+ if (flags & A_HINT_EXISTS)
   sv = &PL_sv_no;
  else
   sv = &PL_sv_undef;