return val;
}
+STATIC void a_map_delete(pTHX_ const OP *o) {
+#define a_map_delete(O) a_map_delete(aTHX_ (O))
+#ifdef USE_ITHREADS
+ MUTEX_LOCK(&a_op_map_mutex);
+#endif
+
+ ptable_map_store(a_op_map, o, NULL);
+
+#ifdef USE_ITHREADS
+ MUTEX_UNLOCK(&a_op_map_mutex);
+#endif
+}
+
STATIC void a_map_set_root(const OP *root, UV flags) {
a_op_info *oi;
const OP *o = root;
dSP;
if (!SvOK(TOPs)) {
+ /* We always need to push an empty array to fool the pp_aelem() that comes
+ * later. */
SV *av;
POPs;
av = sv_2mortal((SV *) newAV());
UV hint;
dSP;
- if (!SvOK(TOPs))
- RETURN;
-
a_map_fetch(PL_op, &oi);
+ if (!SvOK(TOPs)) {
+ if (oi.root->op_flags & OPf_MOD) {
+ SV *hv;
+ POPs;
+ hv = sv_2mortal((SV *) newHV());
+ PUSHs(hv);
+ }
+ RETURN;
+ }
+
return CALL_FPTR(oi.old_pp)(aTHX);
}
U8 old_private;
deref:
- old_private = PL_op->op_private;
- PL_op->op_private &= ~OPpDEREF;
- PL_op->op_private |= OPpLVAL_DEFER;
+ old_private = PL_op->op_private;
+ PL_op->op_private = ((old_private & ~OPpDEREF) | OPpLVAL_DEFER);
o = CALL_FPTR(oi.old_pp)(aTHX);
PL_op->op_private = old_private;
} else if (flags && (PL_op->op_private & OPpDEREF || PL_op == oi.root)) {
oi.flags = flags & A_HINT_NOTIFY;
- if (oi.root->op_flags & OPf_MOD) {
- if (flags & A_HINT_STORE)
+ if ((oi.root->op_flags & (OPf_MOD|OPf_REF)) != (OPf_MOD|OPf_REF)) {
+ if (flags & A_HINT_FETCH)
+ oi.flags |= (A_HINT_FETCH|A_HINT_DEREF);
+ } else if (flags & A_HINT_STORE)
oi.flags |= (A_HINT_STORE|A_HINT_DEREF);
- } else if (flags & A_HINT_FETCH)
- oi.flags |= (A_HINT_FETCH|A_HINT_DEREF);
if (PL_op == oi.root)
oi.flags &= ~A_HINT_DEREF;
a_pp_padsv_save();
a_map_store(o, a_pp_padsv_saved, hint);
} else
- a_map_store(o, 0, 0);
+ a_map_delete(o);
return o;
}
a_map_store(o, o->op_ppaddr, hint);
o->op_ppaddr = a_pp_deref;
} else
- a_map_store(o, 0, 0);
+ a_map_delete(o);
return o;
}
o->op_ppaddr = a_pp_deref;
a_map_set_root(o, hint);
} else
- a_map_store(o, 0, 0);
+ a_map_delete(o);
return o;
}