X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/ed3b9b3c212f717939207379cdb328156dd4a01e..0f2dddf9d5446ead8d477e583a8d2c0191df31e1:/pp_hot.c diff --git a/pp_hot.c b/pp_hot.c index edc4854..34542c2 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; @@ -122,7 +123,7 @@ PP(pp_sassign) if (PL_op->op_private & OPpASSIGN_CV_TO_GV) { SV * const cv = SvRV(left); const U32 cv_type = SvTYPE(cv); - const U32 gv_type = SvTYPE(right); + const bool is_gv = isGV_with_GP(right); const bool got_coderef = cv_type == SVt_PVCV || cv_type == SVt_PVFM; if (!got_coderef) { @@ -132,7 +133,7 @@ PP(pp_sassign) /* Can do the optimisation if right (LVALUE) is not a typeglob, left (RVALUE) is a reference to something, and we're in void context. */ - if (!got_coderef && gv_type != SVt_PVGV && GIMME_V == G_VOID) { + if (!got_coderef && !is_gv && GIMME_V == G_VOID) { /* Is the target symbol table currently empty? */ GV * const gv = gv_fetchsv(right, GV_NOINIT, SVt_PVGV); if (SvTYPE(gv) != SVt_PVGV && !SvOK(gv)) { @@ -150,7 +151,7 @@ PP(pp_sassign) } /* Need to fix things up. */ - if (gv_type != SVt_PVGV) { + if (!is_gv) { /* Need to fix GV. */ right = MUTABLE_SV(gv_fetchsv(right, GV_ADD, SVt_PVGV)); } @@ -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( isGV_with_GP(right) && 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)) @@ -820,8 +828,9 @@ PP(pp_rv2av) const bool is_pp_rv2av = PL_op->op_type == OP_RV2AV; const svtype type = is_pp_rv2av ? SVt_PVAV : SVt_PVHV; + if (!(PL_op->op_private & OPpDEREFed)) + SvGETMAGIC(sv); if (SvROK(sv)) { - wasref: tryAMAGICunDEREF_var(is_pp_rv2av ? to_av_amg : to_hv_amg); sv = SvRV(sv); @@ -858,11 +867,6 @@ PP(pp_rv2av) GV *gv; if (!isGV_with_GP(sv)) { - if (SvGMAGICAL(sv)) { - mg_get(sv); - if (SvROK(sv)) - goto wasref; - } gv = Perl_softref2xv(aTHX_ sv, is_pp_rv2av ? an_array : a_hash, type, &sp); if (!gv) @@ -1045,24 +1049,19 @@ PP(pp_aassign) *(relem++) = sv; didstore = av_store(ary,i++,sv); if (magic) { - if (SvSMAGICAL(sv)) { - /* More magic can happen in the mg_set callback, so we - * backup the delaymagic for now. */ - U16 dmbak = PL_delaymagic; - PL_delaymagic = 0; + if (SvSMAGICAL(sv)) mg_set(sv); - PL_delaymagic = dmbak; - } if (!didstore) sv_2mortal(sv); } TAINT_NOT; } - if (PL_delaymagic & DM_ARRAY) + if (PL_delaymagic & DM_ARRAY_ISA) SvSETMAGIC(MUTABLE_SV(ary)); break; case SVt_PVHV: { /* normal hash */ SV *tmpstr; + SV** topelem = relem; hash = MUTABLE_HV(sv); magic = SvMAGICAL(hash) != 0; @@ -1076,18 +1075,23 @@ 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)) { - U16 dmbak = PL_delaymagic; - PL_delaymagic = 0; + if (SvSMAGICAL(tmpstr)) mg_set(tmpstr); - PL_delaymagic = dmbak; - } if (!didstore) sv_2mortal(tmpstr); } @@ -1111,13 +1115,7 @@ PP(pp_aassign) } else sv_setsv(sv, &PL_sv_undef); - - if (SvSMAGICAL(sv)) { - U16 dmbak = PL_delaymagic; - PL_delaymagic = 0; - mg_set(sv); - PL_delaymagic = dmbak; - } + SvSETMAGIC(sv); break; } } @@ -1202,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; } @@ -1239,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); } @@ -1347,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; @@ -1660,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)) { @@ -2110,6 +2121,11 @@ PP(pp_subst) EXTEND(SP,1); } + /* In non-destructive replacement mode, duplicate target scalar so it + * remains unchanged. */ + if (rpm->op_pmflags & PMf_NONDESTRUCT) + TARG = newSVsv(TARG); + #ifdef PERL_OLD_COPY_ON_WRITE /* Awooga. Awooga. "bool" types that are actually char are dangerous, because they make integers such as 256 "false". */ @@ -2126,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: @@ -2233,7 +2249,10 @@ PP(pp_subst) if (!matched) { SPAGAIN; - PUSHs(&PL_sv_no); + if (rpm->op_pmflags & PMf_NONDESTRUCT) + PUSHs(TARG); + else + PUSHs(&PL_sv_no); LEAVE_SCOPE(oldsave); RETURN; } @@ -2287,7 +2306,10 @@ PP(pp_subst) } TAINT_IF(rxtainted & 1); SPAGAIN; - PUSHs(&PL_sv_yes); + if (rpm->op_pmflags & PMf_NONDESTRUCT) + PUSHs(TARG); + else + PUSHs(&PL_sv_yes); } else { do { @@ -2316,7 +2338,10 @@ PP(pp_subst) } TAINT_IF(rxtainted & 1); SPAGAIN; - mPUSHi((I32)iters); + if (rpm->op_pmflags & PMf_NONDESTRUCT) + PUSHs(TARG); + else + mPUSHi((I32)iters); } (void)SvPOK_only_UTF8(TARG); TAINT_IF(rxtainted); @@ -2402,7 +2427,10 @@ PP(pp_subst) TAINT_IF(rxtainted & 1); SPAGAIN; - mPUSHi((I32)iters); + if (rpm->op_pmflags & PMf_NONDESTRUCT) + PUSHs(TARG); + else + mPUSHi((I32)iters); (void)SvPOK_only(TARG); if (doutf8) @@ -2418,7 +2446,10 @@ PP(pp_subst) nope: ret_no: SPAGAIN; - PUSHs(&PL_sv_no); + if (rpm->op_pmflags & PMf_NONDESTRUCT) + PUSHs(TARG); + else + PUSHs(&PL_sv_no); LEAVE_SCOPE(oldsave); RETURN; } @@ -2430,6 +2461,7 @@ PP(pp_grepwhile) if (SvTRUEx(POPs)) PL_stack_base[PL_markstack_ptr[-1]++] = PL_stack_base[*PL_markstack_ptr]; ++*PL_markstack_ptr; + FREETMPS; LEAVE_with_name("grep_item"); /* exit inner scope */ /* All done yet? */ @@ -2598,10 +2630,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); @@ -2715,6 +2750,7 @@ PP(pp_entersub) case SVt_PVGV: if (!isGV_with_GP(sv)) DIE(aTHX_ "Not a CODE reference"); + we_have_a_glob: if (!(cv = GvCVu((const GV *)sv))) { HV *stash; cv = sv_2cv(sv, &stash, &gv, 0); @@ -2725,30 +2761,24 @@ PP(pp_entersub) goto try_autoload; } break; + case SVt_PVLV: + if(isGV_with_GP(sv)) goto we_have_a_glob; + /*FALLTHROUGH*/ 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 +2786,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 +2949,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 +3066,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: