#endif
#if defined(OP_CHECK_MUTEX_LOCK) && defined(OP_CHECK_MUTEX_UNLOCK)
-# define A_CHECK_MUTEX_LOCK OP_CHECK_MUTEX_LOCK
-# define A_CHECK_MUTEX_UNLOCK OP_CHECK_MUTEX_UNLOCK
+# define A_CHECK_LOCK OP_CHECK_MUTEX_LOCK
+# define A_CHECK_UNLOCK OP_CHECK_MUTEX_UNLOCK
#else
-# define A_CHECK_MUTEX_LOCK OP_REFCNT_LOCK
-# define A_CHECK_MUTEX_UNLOCK OP_REFCNT_UNLOCK
+# define A_CHECK_LOCK OP_REFCNT_LOCK
+# define A_CHECK_UNLOCK OP_REFCNT_UNLOCK
#endif
typedef OP *(*a_ck_t)(pTHX_ OP *);
static void a_ck_replace(pTHX_ OPCODE type, a_ck_t new_ck, a_ck_t *old_ck_p) {
#define a_ck_replace(T, NC, OCP) a_ck_replace(aTHX_ (T), (NC), (OCP))
- A_CHECK_MUTEX_LOCK;
+ A_CHECK_LOCK;
if (!*old_ck_p) {
*old_ck_p = PL_check[type];
PL_check[type] = new_ck;
}
- A_CHECK_MUTEX_UNLOCK;
+ A_CHECK_UNLOCK;
}
#endif
static void a_ck_restore(pTHX_ OPCODE type, a_ck_t *old_ck_p) {
#define a_ck_restore(T, OCP) a_ck_restore(aTHX_ (T), (OCP))
- A_CHECK_MUTEX_LOCK;
+ A_CHECK_LOCK;
if (*old_ck_p) {
PL_check[type] = *old_ck_p;
*old_ck_p = 0;
}
- A_CHECK_MUTEX_UNLOCK;
+ A_CHECK_UNLOCK;
}
/* --- Helpers ------------------------------------------------------------- */
/* ... 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) {
PUSHs(arg);
PUTBACK;
- return a_do_fake_pp(&unop);
+ return a_do_fake_pp((OP *) &unop);
}
static SV *a_do_fake_pp_unop_arg2(pTHX_ U32 type, U32 flags, SV *arg1, SV *arg2) {
PUSHs(arg2);
PUTBACK;
- return a_do_fake_pp(&unop);
+ return a_do_fake_pp((OP *) &unop);
}
#define a_do_pp_rv2av(R) a_do_fake_pp_unop_arg1(OP_RV2AV, OPf_REF, (R))
UNOP_AUX_item *items;
UV actions;
UV flags = 0;
- UV deref = 0;
SV *sv = NULL;
dSP;
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);
}
}
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;
}
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;
}
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;