X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/354b0578ec63c058cd73f018f484808b22cc8631..60666776a83addda0a7fcb957c6b5007b8e030f3:/pp_hot.c diff --git a/pp_hot.c b/pp_hot.c index 1a7c13f..4f043fb 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -112,6 +112,7 @@ PP(pp_and) PP(pp_sassign) { dVAR; dSP; dPOPTOPssrl; + U32 wasfake = 0; if (PL_op->op_private & OPpASSIGN_BACKWARDS) { SV * const temp = left; @@ -197,7 +198,14 @@ PP(pp_sassign) } } + /* Allow glob assignments like *$x = ..., which, when the glob has a + SVf_FAKE flag, cannot be distinguished from $x = ... without looking + at the op tree. */ + if( SvTYPE(right) == SVt_PVGV && cBINOP->op_last->op_type == OP_RV2GV + && (wasfake = SvFLAGS(right) & SVf_FAKE) ) + SvFLAGS(right) &= ~SVf_FAKE; SvSetMagicSV(right, left); + if(wasfake) SvFLAGS(right) |= SVf_FAKE; SETs(right); RETURN; } @@ -244,7 +252,7 @@ PP(pp_concat) rcopied = TRUE; } - if (TARG != left) { + if (TARG != left) { /* not $l .= $r */ STRLEN llen; const char* const lpv = SvPV_nomg_const(left, llen); lbyte = !DO_UTF8(left); @@ -254,22 +262,21 @@ PP(pp_concat) else SvUTF8_off(TARG); } - else { /* TARG == left */ - STRLEN llen; + else { /* $l .= $r */ if (!SvOK(TARG)) { - if (left == right && ckWARN(WARN_UNINITIALIZED)) + if (left == right && ckWARN(WARN_UNINITIALIZED)) /* $l .= $l */ report_uninit(right); sv_setpvs(left, ""); } - (void)SvPV_nomg_const(left, llen); /* Needed to set UTF8 flag */ - lbyte = !DO_UTF8(left); + lbyte = (SvROK(left) && SvTYPE(SvRV(left)) == SVt_REGEXP) + ? !DO_UTF8(SvRV(left)) : !DO_UTF8(left); if (IN_BYTES) SvUTF8_off(TARG); } if (!rcopied) { if (left == right) - /* $a.$a: do magic twice: tied might return different 2nd time */ + /* $r.$r: do magic twice: tied might return different 2nd time */ SvGETMAGIC(right); rpv = SvPV_nomg_const(right, rlen); rbyte = !DO_UTF8(right); @@ -311,6 +318,7 @@ PP(pp_padsv) PP(pp_readline) { dVAR; + dSP; SvGETMAGIC(TOPs); tryAMAGICunTARGET(iter, 0); PL_last_in_gv = MUTABLE_GV(*PL_stack_sp--); if (!isGV_with_GP(PL_last_in_gv)) { @@ -405,7 +413,7 @@ PP(pp_preinc) { dVAR; dSP; if (SvTYPE(TOPs) >= SVt_PVAV || isGV_with_GP(TOPs)) - DIE(aTHX_ "%s", PL_no_modify); + Perl_croak_no_modify(aTHX); if (!SvREADONLY(TOPs) && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) && SvIVX(TOPs) != IV_MAX) { @@ -743,7 +751,7 @@ PP(pp_print) RETURN; } if (!(io = GvIO(gv))) { - if ((GvEGVx(gv)) && (io = GvIO(GvEGV(gv))) + if ( gv && GvEGVx(gv) && (io = GvIO(GvEGV(gv))) && (mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar))) goto had_magic; if (ckWARN2(WARN_UNOPENED,WARN_CLOSED)) @@ -1053,6 +1061,7 @@ PP(pp_aassign) break; case SVt_PVHV: { /* normal hash */ SV *tmpstr; + SV** topelem = relem; hash = MUTABLE_HV(sv); magic = SvMAGICAL(hash) != 0; @@ -1066,10 +1075,19 @@ PP(pp_aassign) tmpstr = newSV(0); if (*relem) sv_setsv(tmpstr,*relem); /* value */ - *(relem++) = tmpstr; - if (gimme != G_VOID && hv_exists_ent(hash, sv, 0)) - /* key overwrites an existing entry */ - duplicates += 2; + relem++; + if (gimme != G_VOID) { + if (hv_exists_ent(hash, sv, 0)) + /* key overwrites an existing entry */ + duplicates += 2; + else + if (gimme == G_ARRAY) { + /* copy element back: possibly to an earlier + * stack location if we encountered dups earlier */ + *topelem++ = sv; + *topelem++ = tmpstr; + } + } didstore = hv_store_ent(hash,sv,tmpstr,0); if (magic) { if (SvSMAGICAL(tmpstr)) @@ -1182,11 +1200,20 @@ PP(pp_aassign) SP = lastrelem; else if (hash) { if (duplicates) { - /* Removes from the stack the entries which ended up as - * duplicated keys in the hash (fix for [perl #24380]) */ - Move(firsthashrelem + duplicates, - firsthashrelem, duplicates, SV**); + /* at this point we have removed the duplicate key/value + * pairs from the stack, but the remaining values may be + * wrong; i.e. with (a 1 a 2 b 3) on the stack we've removed + * the (a 2), but the stack now probably contains + * (a b 3), because { hv_save(a,1); hv_save(a,2) } + * obliterates the earlier key. So refresh all values. */ lastrelem -= duplicates; + relem = firsthashrelem; + while (relem < lastrelem) { + HE *he; + sv = *relem++; + he = hv_fetch_ent(hash, sv, 0, 0); + *relem++ = (he ? HeVAL(he) : &PL_sv_undef); + } } SP = lastrelem; } @@ -1219,7 +1246,7 @@ PP(pp_qr) SvROK_on(rv); if (pkg) { - HV* const stash = gv_stashpv(SvPV_nolen(pkg), GV_ADD); + HV *const stash = gv_stashsv(pkg, GV_ADD); SvREFCNT_dec(pkg); (void)sv_bless(rv, stash); } @@ -1327,9 +1354,9 @@ PP(pp_match) /g matches against large strings. So far a solution to this problem appears to be quite tricky. Test for the unsafe vars are TODO for now. */ - if (( !global && RX_NPARENS(rx)) - || SvTEMP(TARG) || PL_sawampersand || - (RX_EXTFLAGS(rx) & (RXf_EVAL_SEEN|RXf_PMf_KEEPCOPY))) + if ( (!global && RX_NPARENS(rx)) + || SvTEMP(TARG) || SvAMAGIC(TARG) || PL_sawampersand + || (RX_EXTFLAGS(rx) & (RXf_EVAL_SEEN|RXf_PMf_KEEPCOPY))) r_flags |= REXEC_COPY_STR; if (SvSCREAM(TARG)) r_flags |= REXEC_SCREAM; @@ -1640,8 +1667,12 @@ Perl_do_readline(pTHX) } SvUPGRADE(sv, SVt_PV); tmplen = SvLEN(sv); /* remember if already alloced */ - if (!tmplen && !SvREADONLY(sv)) - Sv_Grow(sv, 80); /* try short-buffering it */ + if (!tmplen && !SvREADONLY(sv)) { + /* try short-buffering it. Please update t/op/readline.t + * if you change the growth length. + */ + Sv_Grow(sv, 80); + } offset = 0; if (type == OP_RCATLINE && SvOK(sv)) { if (!SvPOK(sv)) { @@ -2111,7 +2142,7 @@ PP(pp_subst) || ( ((SvTYPE(TARG) == SVt_PVGV && isGV_with_GP(TARG)) || SvTYPE(TARG) > SVt_PVLV) && !(SvTYPE(TARG) == SVt_PVGV && SvFAKE(TARG))))) - DIE(aTHX_ "%s", PL_no_modify); + Perl_croak_no_modify(aTHX); PUTBACK; setup_match: @@ -2598,10 +2629,13 @@ PP(pp_leavesublv) MARK = newsp + 1; EXTEND_MORTAL(1); if (MARK == SP) { - /* Temporaries are bad unless they happen to be elements - * of a tied hash or array */ - if (SvFLAGS(TOPs) & (SVs_TEMP | SVs_PADTMP | SVf_READONLY) && - !(SvRMAGICAL(TOPs) && mg_find(TOPs, PERL_MAGIC_tiedelem))) { + /* Temporaries are bad unless they happen to have set magic + * attached, such as the elements of a tied hash or array */ + if ((SvFLAGS(TOPs) & (SVs_TEMP | SVs_PADTMP) || + (SvFLAGS(TOPs) & (SVf_READONLY | SVf_FAKE)) + == SVf_READONLY + ) && + !SvSMAGICAL(TOPs)) { LEAVE; cxstack_ix--; POPSUB(cx,sv); @@ -2726,29 +2760,20 @@ PP(pp_entersub) } break; default: - if (!SvROK(sv)) { + if (sv == &PL_sv_yes) { /* unfound import, ignore */ + if (hasargs) + SP = PL_stack_base + POPMARK; + RETURN; + } + SvGETMAGIC(sv); + if (SvROK(sv)) { + SV * const * sp = &sv; /* Used in tryAMAGICunDEREF macro. */ + tryAMAGICunDEREF(to_cv); + } + else { const char *sym; STRLEN len; - if (sv == &PL_sv_yes) { /* unfound import, ignore */ - if (hasargs) - SP = PL_stack_base + POPMARK; - RETURN; - } - if (SvGMAGICAL(sv)) { - mg_get(sv); - if (SvROK(sv)) - goto got_rv; - if (SvPOKp(sv)) { - sym = SvPVX_const(sv); - len = SvCUR(sv); - } else { - sym = NULL; - len = 0; - } - } - else { - sym = SvPV_const(sv, len); - } + sym = SvPV_nomg_const(sv, len); if (!sym) DIE(aTHX_ PL_no_usym, "a subroutine"); if (PL_op->op_private & HINT_STRICT_REFS) @@ -2756,11 +2781,6 @@ PP(pp_entersub) cv = get_cvn_flags(sym, len, GV_ADD|SvUTF8(sv)); break; } - got_rv: - { - SV * const * sp = &sv; /* Used in tryAMAGICunDEREF macro. */ - tryAMAGICunDEREF(to_cv); - } cv = MUTABLE_CV(SvRV(sv)); if (SvTYPE(cv) == SVt_PVCV) break; @@ -2924,7 +2944,7 @@ try_autoload: /* CvXSUB(cv) must not be NULL because newXS() refuses NULL xsub address */ assert(CvXSUB(cv)); - CALL_FPTR(CvXSUB(cv))(aTHX_ cv); + CvXSUB(cv)(aTHX_ cv); /* Enforce some sanity in scalar context. */ if (gimme == G_SCALAR && ++markix != PL_stack_sp - PL_stack_base ) { @@ -3041,7 +3061,7 @@ Perl_vivify_ref(pTHX_ SV *sv, U32 to_what) SvGETMAGIC(sv); if (!SvOK(sv)) { if (SvREADONLY(sv)) - Perl_croak(aTHX_ "%s", PL_no_modify); + Perl_croak_no_modify(aTHX); prepare_SV_for_RV(sv); switch (to_what) { case OPpDEREF_SV: