X-Git-Url: http://git.vpit.fr/?a=blobdiff_plain;f=autovivification.xs;h=9577d87547cbe1170b45919eddd0ae0ea78b8635;hb=fc5a59c6495fe7d4c4607fa2379b5f0084e1dd13;hp=915811487d3c2f814423b4be023121fea3d3365e;hpb=77f5401407e2c26619e5499a1539564c59dc83e2;p=perl%2Fmodules%2Fautovivification.git diff --git a/autovivification.xs b/autovivification.xs index 9158114..9577d87 100644 --- a/autovivification.xs +++ b/autovivification.xs @@ -93,11 +93,11 @@ #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 *); @@ -110,24 +110,24 @@ 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 ------------------------------------------------------------- */ @@ -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) { @@ -869,7 +875,7 @@ static SV *a_do_fake_pp_unop_arg1(pTHX_ U32 type, U32 flags, SV *arg) { 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) { @@ -884,7 +890,7 @@ 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)) @@ -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;