X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pp.c;h=7fa9c06933a7c8d9de35e6d30a017628e00a479f;hb=8b19b778095c65c753c5e9d223cac7401a43bd7f;hp=9af36f06c7f8c99be04af543c2bcfb50e386d755;hpb=57ab3dfef762780a52fccd428b2a630bc33a48f4;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pp.c b/pp.c index 9af36f0..7fa9c06 100644 --- a/pp.c +++ b/pp.c @@ -17,6 +17,8 @@ #include "perl.h" #include "keywords.h" +#include "reentr.h" + /* variations on pp_null */ /* XXX I can't imagine anyone who doesn't have this actually _needs_ @@ -954,6 +956,8 @@ PP(pp_pow) result *= base; /* Only bother to clear the bit if it is set. */ power &= ~bit; + /* Avoid squaring base again if we're done. */ + if (power == 0) break; } } SP--; @@ -3303,12 +3307,12 @@ PP(pp_crypt) # else sv_setpv(TARG, PerlProc_crypt(tmps, SvPV(right, n_a))); # endif + SETs(TARG); + RETURN; #else DIE(aTHX_ "The crypt() function is unimplemented due to excessive paranoia."); #endif - SETs(TARG); - RETURN; } PP(pp_ucfirst) @@ -3823,17 +3827,38 @@ PP(pp_hslice) register HV *hv = (HV*)POPs; register I32 lval = (PL_op->op_flags & OPf_MOD || LVRET); I32 realhv = (SvTYPE(hv) == SVt_PVHV); + bool localizing = PL_op->op_private & OPpLVAL_INTRO ? TRUE : FALSE; + bool other_magic = FALSE; + + if (localizing) { + MAGIC *mg; + HV *stash; - if (!realhv && PL_op->op_private & OPpLVAL_INTRO) + other_magic = mg_find((SV*)hv, PERL_MAGIC_env) || + ((mg = mg_find((SV*)hv, PERL_MAGIC_tied)) + /* Try to preserve the existenceness of a tied hash + * element by using EXISTS and DELETE if possible. + * Fallback to FETCH and STORE otherwise */ + && (stash = SvSTASH(SvRV(SvTIED_obj((SV*)hv, mg)))) + && gv_fetchmethod_autoload(stash, "EXISTS", TRUE) + && gv_fetchmethod_autoload(stash, "DELETE", TRUE)); + } + + if (!realhv && localizing) DIE(aTHX_ "Can't localize pseudo-hash element"); if (realhv || SvTYPE(hv) == SVt_PVAV) { while (++MARK <= SP) { SV *keysv = *MARK; SV **svp; - I32 preeminent = SvRMAGICAL(hv) ? 1 : - realhv ? hv_exists_ent(hv, keysv, 0) - : avhv_exists_ent((AV*)hv, keysv, 0); + bool preeminent = FALSE; + + if (localizing) { + preeminent = SvRMAGICAL(hv) && !other_magic ? 1 : + realhv ? hv_exists_ent(hv, keysv, 0) + : avhv_exists_ent((AV*)hv, keysv, 0); + } + if (realhv) { HE *he = hv_fetch_ent(hv, keysv, lval, 0); svp = he ? &HeVAL(he) : 0; @@ -3846,7 +3871,7 @@ PP(pp_hslice) STRLEN n_a; DIE(aTHX_ PL_no_helem, SvPV(keysv, n_a)); } - if (PL_op->op_private & OPpLVAL_INTRO) { + if (localizing) { if (preeminent) save_helem(hv, keysv, svp); else {