X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pp_hot.c;h=1054d1df104f0b99f423ddc945d72bd8a2f28d17;hb=e77e2f143f073d08d6764e30771960b2bccde0db;hp=24d26d7703d54a6522fc5d41b4f368d232ad789c;hpb=35c1215df9ec9cb54402afdda4ed360fdbf58539;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pp_hot.c b/pp_hot.c index 24d26d7..1054d1d 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -1,6 +1,7 @@ /* pp_hot.c * - * Copyright (c) 1991-2002, Larry Wall + * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + * 2000, 2001, 2002, 2003, 2004, by Larry Wall and others * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. @@ -15,6 +16,19 @@ * Fire, Foes! Awake! */ +/* This file contains 'hot' pp ("push/pop") functions that + * execute the opcodes that make up a perl program. A typical pp function + * expects to find its arguments on the stack, and usually pushes its + * results onto the stack, hence the 'pp' terminology. Each OP structure + * contains a pointer to the relevant pp_foo() function. + * + * By 'hot', we mean common ops whose execution speed is critical. + * By gathering them together into a single file, we encourage + * CPU cache hits on hot code. Also it could be taken as a warning not to + * change any code in this file unless you're sure it won't affect + * performance. + */ + #include "EXTERN.h" #define PERL_IN_PP_HOT_C #include "perl.h" @@ -136,16 +150,17 @@ PP(pp_concat) bool lbyte; STRLEN rlen; char* rpv = SvPV(right, rlen); /* mg_get(right) happens here */ - bool rbyte = !SvUTF8(right); + bool rbyte = !DO_UTF8(right), rcopied = FALSE; if (TARG == right && right != left) { right = sv_2mortal(newSVpvn(rpv, rlen)); - rpv = SvPV(right, rlen); /* no point setting UTF8 here */ + rpv = SvPV(right, rlen); /* no point setting UTF-8 here */ + rcopied = TRUE; } if (TARG != left) { lpv = SvPV(left, llen); /* mg_get(left) may happen here */ - lbyte = !SvUTF8(left); + lbyte = !DO_UTF8(left); sv_setpvn(TARG, lpv, llen); if (!lbyte) SvUTF8_on(TARG); @@ -158,7 +173,9 @@ PP(pp_concat) if (!SvOK(TARG)) sv_setpv(left, ""); lpv = SvPV_nomg(left, llen); - lbyte = !SvUTF8(left); + lbyte = !DO_UTF8(left); + if (IN_BYTES) + SvUTF8_off(TARG); } #if defined(PERL_Y2KWARN) @@ -176,6 +193,8 @@ PP(pp_concat) if (lbyte) sv_utf8_upgrade_nomg(TARG); else { + if (!rcopied) + right = sv_2mortal(newSVpvn(rpv, rlen)); sv_utf8_upgrade_nomg(right); rpv = SvPV(right, rlen); } @@ -194,7 +213,7 @@ PP(pp_padsv) if (PL_op->op_flags & OPf_MOD) { if (PL_op->op_private & OPpLVAL_INTRO) SAVECLEARSV(PAD_SVl(PL_op->op_targ)); - else if (PL_op->op_private & OPpDEREF) { + if (PL_op->op_private & OPpDEREF) { PUTBACK; vivify_ref(PAD_SVl(PL_op->op_targ), PL_op->op_private & OPpDEREF); SPAGAIN; @@ -225,7 +244,7 @@ PP(pp_eq) { dSP; tryAMAGICbinSET(eq,0); #ifndef NV_PRESERVES_UV - if (SvROK(TOPs) && SvROK(TOPm1s)) { + if (SvROK(TOPs) && !SvAMAGIC(TOPs) && SvROK(TOPm1s) && !SvAMAGIC(TOPm1s)) { SP--; SETs(boolSV(SvRV(TOPs) == SvRV(TOPp1s))); RETURN; @@ -291,7 +310,7 @@ PP(pp_eq) PP(pp_preinc) { dSP; - if (SvTYPE(TOPs) > SVt_PVLV) + if (SvTYPE(TOPs) >= SVt_PVGV && SvTYPE(TOPs) != SVt_PVLV) DIE(aTHX_ PL_no_modify); if (!SvREADONLY(TOPs) && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) && SvIVX(TOPs) != IV_MAX) @@ -517,7 +536,8 @@ PP(pp_add) PP(pp_aelemfast) { dSP; - AV *av = GvAV(cGVOP_gv); + AV *av = PL_op->op_flags & OPf_SPECIAL ? + (AV*)PAD_SV(PL_op->op_targ) : GvAV(cGVOP_gv); U32 lval = PL_op->op_flags & OPf_MOD; SV** svp = av_fetch(av, PL_op->op_private, lval); SV *sv = (svp ? *svp : &PL_sv_undef); @@ -682,6 +702,9 @@ PP(pp_rv2av) SETs((SV*)av); RETURN; } + else if (PL_op->op_flags & OPf_MOD + && PL_op->op_private & OPpLVAL_INTRO) + Perl_croak(aTHX_ PL_no_localize_ref); } else { if (SvTYPE(sv) == SVt_PVAV) { @@ -715,7 +738,7 @@ PP(pp_rv2av) PL_op->op_private & HINT_STRICT_REFS) DIE(aTHX_ PL_no_usym, "an ARRAY"); if (ckWARN(WARN_UNINITIALIZED)) - report_uninit(); + report_uninit(sv); if (GIMME == G_ARRAY) { (void)POPs; RETURN; @@ -768,7 +791,10 @@ PP(pp_rv2av) U32 i; for (i=0; i < (U32)maxarg; i++) { SV **svp = av_fetch(av, i, FALSE); - SP[i+1] = (svp) ? *svp : &PL_sv_undef; + /* See note in pp_helem, and bug id #27839 */ + SP[i+1] = svp + ? SvGMAGICAL(*svp) ? sv_mortalcopy(*svp) : *svp + : &PL_sv_undef; } } else { @@ -788,6 +814,7 @@ PP(pp_rv2hv) { dSP; dTOPss; HV *hv; + I32 gimme = GIMME_V; if (SvROK(sv)) { wasref: @@ -801,11 +828,14 @@ PP(pp_rv2hv) RETURN; } else if (LVRET) { - if (GIMME == G_SCALAR) + if (gimme != G_ARRAY) Perl_croak(aTHX_ "Can't return hash to lvalue scalar context"); SETs((SV*)hv); RETURN; } + else if (PL_op->op_flags & OPf_MOD + && PL_op->op_private & OPpLVAL_INTRO) + Perl_croak(aTHX_ PL_no_localize_ref); } else { if (SvTYPE(sv) == SVt_PVHV) { @@ -815,7 +845,7 @@ PP(pp_rv2hv) RETURN; } else if (LVRET) { - if (GIMME == G_SCALAR) + if (gimme != G_ARRAY) Perl_croak(aTHX_ "Can't return hash to lvalue" " scalar context"); SETs((SV*)hv); @@ -839,8 +869,8 @@ PP(pp_rv2hv) PL_op->op_private & HINT_STRICT_REFS) DIE(aTHX_ PL_no_usym, "a HASH"); if (ckWARN(WARN_UNINITIALIZED)) - report_uninit(); - if (GIMME == G_ARRAY) { + report_uninit(sv); + if (gimme == G_ARRAY) { SP--; RETURN; } @@ -875,7 +905,7 @@ PP(pp_rv2hv) RETURN; } else if (LVRET) { - if (GIMME == G_SCALAR) + if (gimme != G_ARRAY) Perl_croak(aTHX_ "Can't return hash to lvalue" " scalar context"); SETs((SV*)hv); @@ -884,21 +914,16 @@ PP(pp_rv2hv) } } - if (GIMME == G_ARRAY) { /* array wanted */ + if (gimme == G_ARRAY) { /* array wanted */ *PL_stack_sp = (SV*)hv; return do_kv(); } - else { + else if (gimme == G_SCALAR) { dTARGET; - if (HvFILL(hv)) - Perl_sv_setpvf(aTHX_ TARG, "%"IVdf"/%"IVdf, - (IV)HvFILL(hv), (IV)HvMAX(hv) + 1); - else - sv_setiv(TARG, 0); - + TARG = Perl_hv_scalar(aTHX_ hv); SETTARG; - RETURN; } + RETURN; } STATIC void @@ -952,8 +977,12 @@ PP(pp_aassign) HV *hash; I32 i; int magic; + int duplicates = 0; + SV **firsthashrelem = 0; /* "= 0" keeps gcc 2.95 quiet */ + PL_delaymagic = DM_DELAY; /* catch simultaneous items */ + gimme = GIMME_V; /* If there's a common identifier on both sides we have to take * special care that assigning the identifier on the left doesn't @@ -1007,6 +1036,7 @@ PP(pp_aassign) hash = (HV*)sv; magic = SvMAGICAL(hash) != 0; hv_clear(hash); + firsthashrelem = relem; while (relem < lastrelem) { /* gobble up all the rest */ HE *didstore; @@ -1018,6 +1048,9 @@ PP(pp_aassign) 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; didstore = hv_store_ent(hash,sv,tmpstr,0); if (magic) { if (SvSMAGICAL(tmpstr)) @@ -1052,10 +1085,13 @@ PP(pp_aassign) if (PL_delaymagic & ~DM_DELAY) { if (PL_delaymagic & DM_UID) { #ifdef HAS_SETRESUID - (void)setresuid(PL_uid,PL_euid,(Uid_t)-1); + (void)setresuid((PL_delaymagic & DM_RUID) ? PL_uid : (Uid_t)-1, + (PL_delaymagic & DM_EUID) ? PL_euid : (Uid_t)-1, + (Uid_t)-1); #else # ifdef HAS_SETREUID - (void)setreuid(PL_uid,PL_euid); + (void)setreuid((PL_delaymagic & DM_RUID) ? PL_uid : (Uid_t)-1, + (PL_delaymagic & DM_EUID) ? PL_euid : (Uid_t)-1); # else # ifdef HAS_SETRUID if ((PL_delaymagic & DM_UID) == DM_RUID) { @@ -1065,7 +1101,7 @@ PP(pp_aassign) # endif /* HAS_SETRUID */ # ifdef HAS_SETEUID if ((PL_delaymagic & DM_UID) == DM_EUID) { - (void)seteuid(PL_uid); + (void)seteuid(PL_euid); PL_delaymagic &= ~DM_EUID; } # endif /* HAS_SETEUID */ @@ -1081,10 +1117,13 @@ PP(pp_aassign) } if (PL_delaymagic & DM_GID) { #ifdef HAS_SETRESGID - (void)setresgid(PL_gid,PL_egid,(Gid_t)-1); + (void)setresgid((PL_delaymagic & DM_RGID) ? PL_gid : (Gid_t)-1, + (PL_delaymagic & DM_EGID) ? PL_egid : (Gid_t)-1, + (Gid_t)-1); #else # ifdef HAS_SETREGID - (void)setregid(PL_gid,PL_egid); + (void)setregid((PL_delaymagic & DM_RGID) ? PL_gid : (Gid_t)-1, + (PL_delaymagic & DM_EGID) ? PL_egid : (Gid_t)-1); # else # ifdef HAS_SETRGID if ((PL_delaymagic & DM_GID) == DM_RGID) { @@ -1094,7 +1133,7 @@ PP(pp_aassign) # endif /* HAS_SETRGID */ # ifdef HAS_SETEGID if ((PL_delaymagic & DM_GID) == DM_EGID) { - (void)setegid(PL_gid); + (void)setegid(PL_egid); PL_delaymagic &= ~DM_EGID; } # endif /* HAS_SETEGID */ @@ -1112,17 +1151,26 @@ PP(pp_aassign) } PL_delaymagic = 0; - gimme = GIMME_V; if (gimme == G_VOID) SP = firstrelem - 1; else if (gimme == G_SCALAR) { dTARGET; SP = firstrelem; - SETi(lastrelem - firstrelem + 1); + SETi(lastrelem - firstrelem + 1 - duplicates); } else { - if (ary || hash) + if (ary) 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**); + lastrelem -= duplicates; + } + SP = lastrelem; + } else SP = firstrelem + (lastlelem - firstlelem); lelem = firstlelem + (relem - firstrelem); @@ -1166,6 +1214,8 @@ PP(pp_match) if (PL_op->op_flags & OPf_STACKED) TARG = POPs; + else if (PL_op->op_private & OPpTARGET_MY) + GETTARGET; else { TARG = DEFSV; EXTEND(SP,1); @@ -1180,7 +1230,7 @@ PP(pp_match) (PL_tainted && (pm->op_pmflags & PMf_RETAINT))); TAINT_NOT; - PL_reg_match_utf8 = DO_UTF8(TARG); + RX_MATCH_UTF8_set(rx, DO_UTF8(TARG)); /* PMdf_USED is set after a ?? matches once */ if (pm->op_pmdynflags & PMdf_USED) { @@ -1224,7 +1274,7 @@ PP(pp_match) if (SvSCREAM(TARG)) r_flags |= REXEC_SCREAM; - if (pm->op_pmflags & (PMf_MULTILINE|PMf_SINGLELINE)) { + if ((int)(pm->op_pmflags & PMf_MULTILINE) != PL_multiline) { SAVEINT(PL_multiline); PL_multiline = pm->op_pmflags & PMf_MULTILINE; } @@ -1283,10 +1333,10 @@ play_it_again: /*SUPPRESS 560*/ if ((rx->startp[i] != -1) && rx->endp[i] != -1 ) { len = rx->endp[i] - rx->startp[i]; + s = rx->startp[i] + truebase; if (rx->endp[i] < 0 || rx->startp[i] < 0 || len < 0 || len > strend - s) DIE(aTHX_ "panic: pp_match start/end pointers"); - s = rx->startp[i] + truebase; sv_setpvn(*SP, s, len); if (DO_UTF8(TARG) && is_utf8_string((U8*)s, len)) SvUTF8_on(*SP); @@ -1355,7 +1405,7 @@ yup: /* Confirmed by INTUIT */ if (global) { rx->subbeg = truebase; rx->startp[0] = s - truebase; - if (PL_reg_match_utf8) { + if (RX_MATCH_UTF8(rx)) { char *t = (char*)utf8_hop((U8*)s, rx->minlen); rx->endp[0] = t - truebase; } @@ -1367,8 +1417,26 @@ yup: /* Confirmed by INTUIT */ } if (PL_sawampersand) { I32 off; +#ifdef PERL_COPY_ON_WRITE + if (SvIsCOW(TARG) || (SvFLAGS(TARG) & CAN_COW_MASK) == CAN_COW_FLAGS) { + if (DEBUG_C_TEST) { + PerlIO_printf(Perl_debug_log, + "Copy on write: pp_match $& capture, type %d, truebase=%p, t=%p, difference %d\n", + (int) SvTYPE(TARG), truebase, t, + (int)(t-truebase)); + } + rx->saved_copy = sv_setsv_cow(rx->saved_copy, TARG); + rx->subbeg = SvPVX(rx->saved_copy) + (t - truebase); + assert (SvPOKp(rx->saved_copy)); + } else +#endif + { - rx->subbeg = savepvn(t, strend - t); + rx->subbeg = savepvn(t, strend - t); +#ifdef PERL_COPY_ON_WRITE + rx->saved_copy = Nullsv; +#endif + } rx->sublen = strend - t; RX_MATCH_COPIED_on(rx); off = rx->startp[0] = s - t; @@ -1378,7 +1446,7 @@ yup: /* Confirmed by INTUIT */ rx->startp[0] = s - truebase; rx->endp[0] = s - truebase + rx->minlen; } - rx->nparens = rx->lastparen = 0; /* used by @- and @+ */ + rx->nparens = rx->lastparen = rx->lastcloseparen = 0; /* used by @-, @+, and $^N */ LEAVE_SCOPE(oldsave); RETPUSHYES; @@ -1466,7 +1534,11 @@ Perl_do_readline(pTHX) report_evil_fh(PL_last_in_gv, io, PL_op->op_type); } if (gimme == G_SCALAR) { - (void)SvOK_off(TARG); + /* undef TARG, and push that undefined value */ + if (type != OP_RCATLINE) { + SV_CHECK_THINKFIRST_COW_DROP(TARG); + SvOK_off(TARG); + } PUSHTARG; } RETURN; @@ -1478,7 +1550,7 @@ Perl_do_readline(pTHX) sv_unref(sv); (void)SvUPGRADE(sv, SVt_PV); tmplen = SvLEN(sv); /* remember if already alloced */ - if (!tmplen) + if (!tmplen && !SvREADONLY(sv)) Sv_Grow(sv, 80); /* try short-buffering it */ offset = 0; if (type == OP_RCATLINE && SvOK(sv)) { @@ -1509,7 +1581,9 @@ Perl_do_readline(pTHX) for (;;) { PUTBACK; if (!sv_gets(sv, fp, offset) - && (type == OP_GLOB || SNARF_EOF(gimme, PL_rs, io, sv))) + && (type == OP_GLOB + || SNARF_EOF(gimme, PL_rs, io, sv) + || PerlIO_error(fp))) { PerlIO_clearerr(fp); if (IoFLAGS(io) & IOf_ARGV) { @@ -1527,7 +1601,10 @@ Perl_do_readline(pTHX) } } if (gimme == G_SCALAR) { - (void)SvOK_off(TARG); + if (type != OP_RCATLINE) { + SV_CHECK_THINKFIRST_COW_DROP(TARG); + SvOK_off(TARG); + } SPAGAIN; PUSHTARG; } @@ -1558,6 +1635,17 @@ Perl_do_readline(pTHX) (void)POPs; /* Unmatched wildcard? Chuck it... */ continue; } + } else if (SvUTF8(sv)) { /* OP_READLINE, OP_RCATLINE */ + U8 *s = (U8*)SvPVX(sv) + offset; + STRLEN len = SvCUR(sv) - offset; + U8 *f; + + if (ckWARN(WARN_UTF8) && + !Perl_is_utf8_string_loc(aTHX_ s, len, &f)) + /* Emulate :encoding(utf8) warning in the same case. */ + Perl_warner(aTHX_ packWARN(WARN_UTF8), + "utf8 \"\\x%02X\" does not map to Unicode", + f < (U8*)SvEND(sv) ? *f : 0); } if (gimme == G_ARRAY) { if (SvLEN(sv) - SvCUR(sv) > 20) { @@ -1749,7 +1837,7 @@ PP(pp_iter) { dSP; register PERL_CONTEXT *cx; - SV* sv; + SV *sv, *oldsv; AV* av; SV **itersvp; @@ -1765,8 +1853,8 @@ PP(pp_iter) if (cx->blk_loop.iterlval) { /* string increment */ register SV* cur = cx->blk_loop.iterlval; - STRLEN maxlen; - char *max = SvPV((SV*)av, maxlen); + STRLEN maxlen = 0; + char *max = SvOK((SV*)av) ? SvPV((SV*)av, maxlen) : ""; if (!SvNIOK(cur) && SvCUR(cur) <= maxlen) { if (SvREFCNT(*itersvp) == 1 && !SvMAGICAL(*itersvp)) { /* safe to reuse old SV */ @@ -1777,8 +1865,9 @@ PP(pp_iter) /* we need a fresh SV every time so that loop body sees a * completely new SV for closures/references to work as * they used to */ - SvREFCNT_dec(*itersvp); + oldsv = *itersvp; *itersvp = newSVsv(cur); + SvREFCNT_dec(oldsv); } if (strEQ(SvPVX(cur), max)) sv_setiv(cur, 0); /* terminate next time */ @@ -1802,28 +1891,52 @@ PP(pp_iter) /* we need a fresh SV every time so that loop body sees a * completely new SV for closures/references to work as they * used to */ - SvREFCNT_dec(*itersvp); + oldsv = *itersvp; *itersvp = newSViv(cx->blk_loop.iterix++); + SvREFCNT_dec(oldsv); } RETPUSHYES; } /* iterate array */ - if (cx->blk_loop.iterix >= (av == PL_curstack ? cx->blk_oldsp : AvFILL(av))) - RETPUSHNO; - - SvREFCNT_dec(*itersvp); + if (PL_op->op_private & OPpITER_REVERSED) { + /* In reverse, use itermax as the min :-) */ + if (cx->blk_loop.iterix <= cx->blk_loop.itermax) + RETPUSHNO; - if (SvMAGICAL(av) || AvREIFY(av)) { - SV **svp = av_fetch(av, ++cx->blk_loop.iterix, FALSE); - if (svp) - sv = *svp; - else - sv = Nullsv; + if (SvMAGICAL(av) || AvREIFY(av)) { + SV **svp = av_fetch(av, cx->blk_loop.iterix--, FALSE); + if (svp) + sv = *svp; + else + sv = Nullsv; + } + else { + sv = AvARRAY(av)[cx->blk_loop.iterix--]; + } } else { - sv = AvARRAY(av)[++cx->blk_loop.iterix]; + if (cx->blk_loop.iterix >= (av == PL_curstack ? cx->blk_oldsp : + AvFILL(av))) + RETPUSHNO; + + if (SvMAGICAL(av) || AvREIFY(av)) { + SV **svp = av_fetch(av, ++cx->blk_loop.iterix, FALSE); + if (svp) + sv = *svp; + else + sv = Nullsv; + } + else { + sv = AvARRAY(av)[++cx->blk_loop.iterix]; + } } + + if (sv && SvREFCNT(sv) == 0) { + *itersvp = Nullsv; + Perl_croak(aTHX_ "Use of freed value in iteration"); + } + if (sv) SvTEMP_off(sv); else @@ -1848,7 +1961,10 @@ PP(pp_iter) sv = (SV*)lv; } + oldsv = *itersvp; *itersvp = SvREFCNT_inc(sv); + SvREFCNT_dec(oldsv); + RETPUSHYES; } @@ -1877,21 +1993,37 @@ PP(pp_subst) I32 oldsave = PL_savestack_ix; STRLEN slen; bool doutf8 = FALSE; +#ifdef PERL_COPY_ON_WRITE + bool is_cow; +#endif + SV *nsv = Nullsv; /* known replacement string? */ dstr = (pm->op_pmflags & PMf_CONST) ? POPs : Nullsv; if (PL_op->op_flags & OPf_STACKED) TARG = POPs; + else if (PL_op->op_private & OPpTARGET_MY) + GETTARGET; else { TARG = DEFSV; EXTEND(SP,1); } +#ifdef PERL_COPY_ON_WRITE + /* Awooga. Awooga. "bool" types that are actually char are dangerous, + because they make integers such as 256 "false". */ + is_cow = SvIsCOW(TARG) ? TRUE : FALSE; +#else if (SvIsCOW(TARG)) sv_force_normal_flags(TARG,0); - if (SvREADONLY(TARG) - || (SvTYPE(TARG) > SVt_PVLV - && !(SvTYPE(TARG) == SVt_PVGV && SvFAKE(TARG)))) +#endif + if ( +#ifdef PERL_COPY_ON_WRITE + !is_cow && +#endif + (SvREADONLY(TARG) + || ( (SvTYPE(TARG) == SVt_PVGV || SvTYPE(TARG) > SVt_PVLV) + && !(SvTYPE(TARG) == SVt_PVGV && SvFAKE(TARG))))) DIE(aTHX_ PL_no_modify); PUTBACK; @@ -1904,14 +2036,14 @@ PP(pp_subst) rxtainted |= 2; TAINT_NOT; - PL_reg_match_utf8 = DO_UTF8(TARG); + RX_MATCH_UTF8_set(rx, DO_UTF8(TARG)); force_it: if (!pm || !s) DIE(aTHX_ "panic: pp_subst"); strend = s + len; - slen = PL_reg_match_utf8 ? utf8_length((U8*)s, (U8*)strend) : len; + slen = RX_MATCH_UTF8(rx) ? utf8_length((U8*)s, (U8*)strend) : len; maxiters = 2 * slen + 10; /* We can match twice at each position, once with zero-length, second time with non-zero. */ @@ -1921,10 +2053,10 @@ PP(pp_subst) rx = PM_GETRE(pm); } r_flags = (rx->nparens || SvTEMP(TARG) || PL_sawampersand) - ? REXEC_COPY_STR : 0; + ? REXEC_COPY_STR : 0; if (SvSCREAM(TARG)) r_flags |= REXEC_SCREAM; - if (pm->op_pmflags & (PMf_MULTILINE|PMf_SINGLELINE)) { + if ((int)(pm->op_pmflags & PMf_MULTILINE) != PL_multiline) { SAVEINT(PL_multiline); PL_multiline = pm->op_pmflags & PMf_MULTILINE; } @@ -1952,7 +2084,7 @@ PP(pp_subst) if (dstr) { /* replacement needing upgrading? */ if (DO_UTF8(TARG) && !doutf8) { - SV *nsv = sv_newmortal(); + nsv = sv_newmortal(); SvSetSV(nsv, dstr); if (PL_encoding) sv_recode_to_utf8(nsv, PL_encoding); @@ -1972,8 +2104,13 @@ PP(pp_subst) } /* can do inplace substitution? */ - if (c && (I32)clen <= rx->minlen && (once || !(r_flags & REXEC_COPY_STR)) - && !(rx->reganch & ROPT_LOOKBEHIND_SEEN)) { + if (c +#ifdef PERL_COPY_ON_WRITE + && !is_cow +#endif + && (I32)clen <= rx->minlen && (once || !(r_flags & REXEC_COPY_STR)) + && !(rx->reganch & ROPT_LOOKBEHIND_SEEN) + && (!doutf8 || SvUTF8(TARG))) { if (!CALLREGEXEC(aTHX_ rx, s, strend, orig, 0, TARG, NULL, r_flags | REXEC_CHECKED)) { @@ -1982,6 +2119,12 @@ PP(pp_subst) LEAVE_SCOPE(oldsave); RETURN; } +#ifdef PERL_COPY_ON_WRITE + if (SvIsCOW(TARG)) { + assert (!force_on_match); + goto have_a_cow; + } +#endif if (force_on_match) { force_on_match = 0; s = SvPV_force(TARG, len); @@ -2083,6 +2226,9 @@ PP(pp_subst) s = SvPV_force(TARG, len); goto force_it; } +#ifdef PERL_COPY_ON_WRITE + have_a_cow: +#endif rxtainted |= RX_MATCH_TAINTED(rx); dstr = NEWSV(25, len); sv_setpvn(dstr, m, s-m); @@ -2092,6 +2238,7 @@ PP(pp_subst) if (!c) { register PERL_CONTEXT *cx; SPAGAIN; + ReREFCNT_inc(rx); PUSHSUBST(cx); RETURNOP(cPMOP->op_pmreplroot); } @@ -2108,7 +2255,10 @@ PP(pp_subst) strend = s + (strend - m); } m = rx->startp[0] + orig; - sv_catpvn(dstr, s, m-s); + if (doutf8 && !SvUTF8(dstr)) + sv_catpvn_utf8_upgrade(dstr, s, m - s, nsv); + else + sv_catpvn(dstr, s, m-s); s = rx->endp[0] + orig; if (clen) sv_catpvn(dstr, c, clen); @@ -2116,17 +2266,26 @@ PP(pp_subst) break; } while (CALLREGEXEC(aTHX_ rx, s, strend, orig, s == m, TARG, NULL, r_flags)); - if (doutf8 && !DO_UTF8(dstr)) { - SV* nsv = sv_2mortal(newSVpvn(s, strend - s)); - - sv_utf8_upgrade(nsv); - sv_catpvn(dstr, SvPVX(nsv), SvCUR(nsv)); - } + if (doutf8 && !DO_UTF8(TARG)) + sv_catpvn_utf8_upgrade(dstr, s, strend - s, nsv); else sv_catpvn(dstr, s, strend - s); - (void)SvOOK_off(TARG); - Safefree(SvPVX(TARG)); +#ifdef PERL_COPY_ON_WRITE + /* The match may make the string COW. If so, brilliant, because that's + just saved us one malloc, copy and free - the regexp has donated + the old buffer, and we malloc an entirely new one, rather than the + regexp malloc()ing a buffer and copying our original, only for + us to throw it away here during the substitution. */ + if (SvIsCOW(TARG)) { + sv_force_normal_flags(TARG, SV_COW_DROP_PV); + } else +#endif + { + SvOOK_off(TARG); + if (SvLEN(TARG)) + Safefree(SvPVX(TARG)); + } SvPVX(TARG) = SvPVX(dstr); SvCUR_set(TARG, SvCUR(dstr)); SvLEN_set(TARG, SvLEN(dstr)); @@ -2177,8 +2336,15 @@ PP(pp_grepwhile) (void)POPMARK; /* pop dst */ SP = PL_stack_base + POPMARK; /* pop original mark */ if (gimme == G_SCALAR) { - dTARGET; - XPUSHi(items); + if (PL_op->op_private & OPpGREP_LEX) { + SV* sv = sv_newmortal(); + sv_setiv(sv, items); + PUSHs(sv); + } + else { + dTARGET; + XPUSHi(items); + } } else if (gimme == G_ARRAY) SP += items; @@ -2192,7 +2358,10 @@ PP(pp_grepwhile) src = PL_stack_base[*PL_markstack_ptr]; SvTEMP_off(src); - DEFSV = src; + if (PL_op->op_private & OPpGREP_LEX) + PAD_SVl(PL_op->op_targ) = src; + else + DEFSV = src; RETURNOP(cLOGOP->op_other); } @@ -2209,6 +2378,7 @@ PP(pp_leavesub) SV *sv; POPBLOCK(cx,newpm); + cxstack_ix++; /* temporarily protect top context */ TAINT_NOT; if (gimme == G_SCALAR) { @@ -2246,12 +2416,13 @@ PP(pp_leavesub) } PUTBACK; + LEAVE; + cxstack_ix--; POPSUB(cx,sv); /* Stack values are safe: release CV and @_ ... */ PL_curpm = newpm; /* ... and pop $1 et al */ - LEAVE; LEAVESUB(sv); - return pop_return(); + return cx->blk_sub.retop; } /* This duplicates the above code because the above code must not @@ -2267,6 +2438,7 @@ PP(pp_leavesublv) SV *sv; POPBLOCK(cx,newpm); + cxstack_ix++; /* temporarily protect top context */ TAINT_NOT; @@ -2302,9 +2474,10 @@ PP(pp_leavesublv) * the refcounts so the caller gets a live guy. Cannot set * TEMP, so sv_2mortal is out of question. */ if (!CvLVALUE(cx->blk_sub.cv)) { + LEAVE; + cxstack_ix--; POPSUB(cx,sv); PL_curpm = newpm; - LEAVE; LEAVESUB(sv); DIE(aTHX_ "Can't modify non-lvalue subroutine call"); } @@ -2313,9 +2486,10 @@ PP(pp_leavesublv) EXTEND_MORTAL(1); if (MARK == SP) { if (SvFLAGS(TOPs) & (SVs_TEMP | SVs_PADTMP | SVf_READONLY)) { + LEAVE; + cxstack_ix--; POPSUB(cx,sv); PL_curpm = newpm; - LEAVE; LEAVESUB(sv); DIE(aTHX_ "Can't return %s from lvalue subroutine", SvREADONLY(TOPs) ? (TOPs == &PL_sv_undef) ? "undef" @@ -2328,9 +2502,10 @@ PP(pp_leavesublv) } } else { /* Should not happen? */ + LEAVE; + cxstack_ix--; POPSUB(cx,sv); PL_curpm = newpm; - LEAVE; LEAVESUB(sv); DIE(aTHX_ "%s returned from lvalue subroutine in scalar context", (MARK > SP ? "Empty array" : "Array")); @@ -2344,9 +2519,10 @@ PP(pp_leavesublv) && SvFLAGS(*mark) & (SVs_TEMP | SVs_PADTMP | SVf_READONLY)) { /* Might be flattened array after $#array = */ PUTBACK; + LEAVE; + cxstack_ix--; POPSUB(cx,sv); PL_curpm = newpm; - LEAVE; LEAVESUB(sv); DIE(aTHX_ "Can't return a %s from lvalue subroutine", SvREADONLY(TOPs) ? "readonly value" : "temporary"); @@ -2398,12 +2574,13 @@ PP(pp_leavesublv) } PUTBACK; + LEAVE; + cxstack_ix--; POPSUB(cx,sv); /* Stack values are safe: release CV and @_ ... */ PL_curpm = newpm; /* ... and pop $1 et al */ - LEAVE; LEAVESUB(sv); - return pop_return(); + return cx->blk_sub.retop; } @@ -2520,6 +2697,9 @@ PP(pp_entersub) gimme = GIMME_V; if ((PL_op->op_private & OPpENTERSUB_DB) && GvCV(PL_DBsub) && !CvNODEBUG(cv)) { + if (CvASSERTION(cv) && PL_DBassertion) + sv_setiv(PL_DBassertion, 1); + cv = get_db_sub(&sv, cv); if (!cv) DIE(aTHX_ "No DBsub routine"); @@ -2530,18 +2710,16 @@ PP(pp_entersub) dMARK; register I32 items = SP - MARK; AV* padlist = CvPADLIST(cv); - push_return(PL_op->op_next); PUSHBLOCK(cx, CXt_SUB, MARK); PUSHSUB(cx); + cx->blk_sub.retop = PL_op->op_next; CvDEPTH(cv)++; /* XXX This would be a natural place to set C so * that eval'' ops within this sub know the correct lexical space. * Owing the speed considerations, we choose instead to search for * the cv using find_runcv() when calling doeval(). */ - if (CvDEPTH(cv) < 2) - (void)SvREFCNT_inc(cv); - else { + if (CvDEPTH(cv) >= 2) { PERL_STACK_OVERFLOW_CHECK(); pad_push(padlist, CvDEPTH(cv), 1); } @@ -2737,6 +2915,18 @@ PP(pp_aelem) RETPUSHUNDEF; svp = av_fetch(av, elem, lval && !defer); if (lval) { +#ifdef PERL_MALLOC_WRAP + static const char oom_array_extend[] = + "Out of memory during array extend"; /* Duplicated in av.c */ + if (SvUOK(elemsv)) { + UV uv = SvUV(elemsv); + elem = uv > IV_MAX ? IV_MAX : uv; + } + else if (SvNOK(elemsv)) + elem = (IV)SvNV(elemsv); + if (elem > 0) + MEM_WRAP_CHECK_1(elem,SV*,oom_array_extend); +#endif if (!svp || *svp == &PL_sv_undef) { SV* lv; if (!defer) @@ -2774,7 +2964,7 @@ Perl_vivify_ref(pTHX_ SV *sv, U32 to_what) if (SvTYPE(sv) < SVt_RV) sv_upgrade(sv, SVt_RV); else if (SvTYPE(sv) >= SVt_PV) { - (void)SvOOK_off(sv); + SvOOK_off(sv); Safefree(SvPVX(sv)); SvLEN(sv) = SvCUR(sv) = 0; } @@ -2814,7 +3004,7 @@ PP(pp_method) PP(pp_method_named) { dSP; - SV* sv = cSVOP->op_sv; + SV* sv = cSVOP_sv; U32 hash = SvUVX(sv); XPUSHs(method_common(sv, &hash)); @@ -2849,8 +3039,18 @@ S_method_common(pTHX_ SV* meth, U32* hashp) /* this isn't a reference */ packname = Nullch; + + if(SvOK(sv) && (packname = SvPV(sv, packlen))) { + HE* he; + he = hv_fetch_ent(PL_stashcache, sv, 0, 0); + if (he) { + stash = INT2PTR(HV*,SvIV(HeVAL(he))); + goto fetch; + } + } + if (!SvOK(sv) || - !(packname = SvPV(sv, packlen)) || + !(packname) || !(iogv = gv_fetchpv(packname, FALSE, SVt_PVIO)) || !(ob=(SV*)GvIO(iogv))) { @@ -2869,6 +3069,10 @@ S_method_common(pTHX_ SV* meth, U32* hashp) stash = gv_stashpvn(packname, packlen, FALSE); if (!stash) packsv = sv; + else { + SV* ref = newSViv(PTR2IV(stash)); + hv_store(PL_stashcache, packname, packlen, ref, 0); + } goto fetch; } /* it _is_ a filehandle name -- replace with a reference */ @@ -2925,7 +3129,11 @@ S_method_common(pTHX_ SV* meth, U32* hashp) /* the method name is unqualified or starts with SUPER:: */ packname = sep ? CopSTASHPV(PL_curcop) : stash ? HvNAME(stash) : packname; - packlen = strlen(packname); + if (!packname) + Perl_croak(aTHX_ + "Can't use anonymous symbol table for method lookup"); + else + packlen = strlen(packname); } else { /* the method name is qualified */