X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/8daf8916b49984fc91791e8265cd7e1ca36b836c..3cd96634230fc4a063f58b18b2aa85cae3ffb1b2:/op.c diff --git a/op.c b/op.c index aedf54f..23eeaaa 100644 --- a/op.c +++ b/op.c @@ -165,11 +165,23 @@ Perl_Slab_Alloc(pTHX_ size_t sz) OP *o; size_t opsz, space; + /* We only allocate ops from the slab during subroutine compilation. + We find the slab via PL_compcv, hence that must be non-NULL. It could + also be pointing to a subroutine which is now fully set up (CvROOT() + pointing to the top of the optree for that sub), or a subroutine + which isn't using the slab allocator. If our sanity checks aren't met, + don't use a slab, but allocate the OP directly from the heap. */ if (!PL_compcv || CvROOT(PL_compcv) || (CvSTART(PL_compcv) && !CvSLABBED(PL_compcv))) return PerlMemShared_calloc(1, sz); - if (!CvSTART(PL_compcv)) { /* sneak it in here */ + /* While the subroutine is under construction, the slabs are accessed via + CvSTART(), to avoid needing to expand PVCV by one pointer for something + unneeded at runtime. Once a subroutine is constructed, the slabs are + accessed via CvROOT(). So if CvSTART() is NULL, no slab has been + allocated yet. See the commit message for 8be227ab5eaa23f2 for more + details. */ + if (!CvSTART(PL_compcv)) { CvSTART(PL_compcv) = (OP *)(slab = S_new_slab(aTHX_ PERL_SLAB_SIZE)); CvSLABBED_on(PL_compcv); @@ -180,6 +192,9 @@ Perl_Slab_Alloc(pTHX_ size_t sz) opsz = SIZE_TO_PSIZE(sz); sz = opsz + OPSLOT_HEADER_P; + /* The slabs maintain a free list of OPs. In particular, constant folding + will free up OPs, so it makes sense to re-use them where possible. A + freed up slot is used in preference to a new allocation. */ if (slab->opslab_freed) { OP **too = &slab->opslab_freed; o = *too; @@ -283,7 +298,7 @@ Perl_Slab_to_rw(pTHX_ OPSLAB *const slab) } #else -# define Slab_to_rw(op) +# define Slab_to_rw(op) NOOP #endif /* This cannot possibly be right, but it was copied from the old slab @@ -520,9 +535,10 @@ S_bad_type_pv(pTHX_ I32 n, const char *t, const char *name, U32 flags, const OP } STATIC void -S_bad_type_sv(pTHX_ I32 n, const char *t, SV *namesv, U32 flags, const OP *kid) +S_bad_type_gv(pTHX_ I32 n, const char *t, GV *gv, U32 flags, const OP *kid) { - PERL_ARGS_ASSERT_BAD_TYPE_SV; + SV * const namesv = gv_ename(gv); + PERL_ARGS_ASSERT_BAD_TYPE_GV; yyerror_pv(Perl_form(aTHX_ "Type of arg %d to %"SVf" must be %s (not %s)", (int)n, SVfARG(namesv), t, OP_DESC(kid)), SvUTF8(namesv) | flags); @@ -578,6 +594,13 @@ Perl_allocmy(pTHX_ const char *const name, const STRLEN len, const U32 flags) PL_parser->in_my == KEY_state ? "state" : "my"), flags & SVf_UTF8); } } + else if (len == 2 && name[1] == '_' && !is_our) + /* diag_listed_as: Use of my $_ is experimental */ + Perl_ck_warner_d(aTHX_ packWARN(WARN_EXPERIMENTAL__LEXICAL_TOPIC), + "Use of %s $_ is experimental", + PL_parser->in_my == KEY_state + ? "state" + : "my"); /* allocate a spare slot and store the name in that slot */ @@ -647,12 +670,6 @@ S_op_destroy(pTHX_ OP *o) FreeOp(o); } -#ifdef USE_ITHREADS -# define forget_pmop(a,b) S_forget_pmop(aTHX_ a,b) -#else -# define forget_pmop(a,b) S_forget_pmop(aTHX_ a) -#endif - /* Destructor */ void @@ -711,9 +728,8 @@ Perl_op_free(pTHX_ OP *o) if (type == OP_NULL) type = (OPCODE)o->op_targ; - if (o->op_slabbed) { - Slab_to_rw(OpSLAB(o)); - } + if (o->op_slabbed) + Slab_to_rw(OpSLAB(o)); /* COP* is not cleared by op_clear() so that we may track line * numbers etc even after null() */ @@ -799,7 +815,7 @@ Perl_op_clear(pTHX_ OP *o) #endif if (still_valid) { int try_downgrade = SvREFCNT(gv) == 2; - SvREFCNT_dec(gv); + SvREFCNT_dec_NN(gv); if (try_downgrade) gv_try_downgrade(gv); } @@ -870,7 +886,7 @@ clear_pmop: if (!(cPMOPo->op_pmflags & PMf_CODELIST_PRIVATE)) op_free(cPMOPo->op_code_list); cPMOPo->op_code_list = NULL; - forget_pmop(cPMOPo, 1); + forget_pmop(cPMOPo); cPMOPo->op_pmreplrootu.op_pmreplroot = NULL; /* we use the same protection as the "SAFE" version of the PM_ macros * here since sv_clean_all might release some PMOPs @@ -909,13 +925,12 @@ S_cop_free(pTHX_ COP* cop) if (! specialWARN(cop->cop_warnings)) PerlMemShared_free(cop->cop_warnings); cophh_free(CopHINTHASH_get(cop)); + if (PL_curcop == cop) + PL_curcop = NULL; } STATIC void S_forget_pmop(pTHX_ PMOP *const o -#ifdef USE_ITHREADS - , U32 flags -#endif ) { HV * const pmstash = PmopSTASH(o); @@ -948,10 +963,6 @@ S_forget_pmop(pTHX_ PMOP *const o } if (PL_curpm == o) PL_curpm = NULL; -#ifdef USE_ITHREADS - if (flags) - PmopSTASH_free(o); -#endif } STATIC void @@ -967,7 +978,7 @@ S_find_and_forget_pmops(pTHX_ OP *o) case OP_PUSHRE: case OP_MATCH: case OP_QR: - forget_pmop((PMOP*)kid, 0); + forget_pmop((PMOP*)kid); } find_and_forget_pmops(kid); kid = kid->op_sibling; @@ -1372,29 +1383,16 @@ Perl_scalarvoid(pTHX_ OP *o) else if (SvNIOK(sv) && (SvNV(sv) == 0.0 || SvNV(sv) == 1.0)) useless = NULL; else if (SvPOK(sv)) { - /* perl4's way of mixing documentation and code - (before the invention of POD) was based on a - trick to mix nroff and perl code. The trick was - built upon these three nroff macros being used in - void context. The pink camel has the details in - the script wrapman near page 319. */ - const char * const maybe_macro = SvPVX_const(sv); - if (strnEQ(maybe_macro, "di", 2) || - strnEQ(maybe_macro, "ds", 2) || - strnEQ(maybe_macro, "ig", 2)) - useless = NULL; - else { - SV * const dsv = newSVpvs(""); - useless_sv - = Perl_newSVpvf(aTHX_ - "a constant (%s)", - pv_pretty(dsv, maybe_macro, - SvCUR(sv), 32, NULL, NULL, - PERL_PV_PRETTY_DUMP - | PERL_PV_ESCAPE_NOCLEAR - | PERL_PV_ESCAPE_UNI_DETECT)); - SvREFCNT_dec(dsv); - } + SV * const dsv = newSVpvs(""); + useless_sv + = Perl_newSVpvf(aTHX_ + "a constant (%s)", + pv_pretty(dsv, SvPVX_const(sv), + SvCUR(sv), 32, NULL, NULL, + PERL_PV_PRETTY_DUMP + | PERL_PV_ESCAPE_NOCLEAR + | PERL_PV_ESCAPE_UNI_DETECT)); + SvREFCNT_dec_NN(dsv); } else if (SvOK(sv)) { useless_sv = Perl_newSVpvf(aTHX_ "a constant (%"SVf")", sv); @@ -1713,7 +1711,7 @@ S_finalize_op(pTHX_ OP* o) case OP_EXEC: if ( o->op_sibling && (o->op_sibling->op_type == OP_NEXTSTATE || o->op_sibling->op_type == OP_DBSTATE) - && ckWARN(WARN_SYNTAX)) + && ckWARN(WARN_EXEC)) { if (o->op_sibling->op_sibling) { const OPCODE type = o->op_sibling->op_sibling->op_type; @@ -1755,17 +1753,8 @@ S_finalize_op(pTHX_ OP* o) * Despite being a "constant", the SV is written to, * for reference counts, sv_upgrade() etc. */ if (cSVOPo->op_sv) { - const PADOFFSET ix = pad_alloc(OP_CONST, SVs_PADTMP); - if (o->op_type != OP_METHOD_NAMED && - (SvPADTMP(cSVOPo->op_sv) || SvPADMY(cSVOPo->op_sv))) - { - /* If op_sv is already a PADTMP/MY then it is being used by - * some pad, so make a copy. */ - sv_setsv(PAD_SVl(ix),cSVOPo->op_sv); - if (!SvIsCOW(PAD_SVl(ix))) SvREADONLY_on(PAD_SVl(ix)); - SvREFCNT_dec(cSVOPo->op_sv); - } - else if (o->op_type != OP_METHOD_NAMED + const PADOFFSET ix = pad_alloc(OP_CONST, SVf_READONLY); + if (o->op_type != OP_METHOD_NAMED && cSVOPo->op_sv == &PL_sv_undef) { /* PL_sv_undef is hack - it's unsafe to store it in the AV that is the pad, because av_fetch treats values of @@ -1779,7 +1768,6 @@ S_finalize_op(pTHX_ OP* o) } else { SvREFCNT_dec(PAD_SVl(ix)); - SvPADTMP_on(cSVOPo->op_sv); PAD_SETSV(ix, cSVOPo->op_sv); /* XXX I don't know how this isn't readonly already. */ if (!SvIsCOW(PAD_SVl(ix))) SvREADONLY_on(PAD_SVl(ix)); @@ -1803,13 +1791,13 @@ S_finalize_op(pTHX_ OP* o) /* Make the CONST have a shared SV */ svp = cSVOPx_svp(((BINOP*)o)->op_last); - if ((!SvIsCOW(sv = *svp)) - && SvTYPE(sv) < SVt_PVMG && !SvROK(sv)) { + if ((!SvIsCOW_shared_hash(sv = *svp)) + && SvTYPE(sv) < SVt_PVMG && SvOK(sv) && !SvROK(sv)) { key = SvPV_const(sv, keylen); lexname = newSVpvn_share(key, SvUTF8(sv) ? -(I32)keylen : (I32)keylen, 0); - SvREFCNT_dec(sv); + SvREFCNT_dec_NN(sv); *svp = lexname; } @@ -2077,11 +2065,12 @@ Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags) /* FALL THROUGH */ case OP_ASLICE: case OP_HSLICE: - if (type == OP_LEAVESUBLV) - o->op_private |= OPpMAYBE_LVSUB; localize = 1; /* FALL THROUGH */ case OP_AASSIGN: + if (type == OP_LEAVESUBLV) + o->op_private |= OPpMAYBE_LVSUB; + /* FALL THROUGH */ case OP_NEXTSTATE: case OP_DBSTATE: PL_modcount = RETURN_UNLIMITED_NUMBER; @@ -2146,9 +2135,6 @@ Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags) lvalue_func: if (type == OP_LEAVESUBLV) o->op_private |= OPpMAYBE_LVSUB; - pad_free(o->op_targ); - o->op_targ = pad_alloc(o->op_type, SVs_PADMY); - assert(SvTYPE(PAD_SV(o->op_targ)) == SVt_NULL); if (o->op_flags & OPf_KIDS) op_lvalue(cBINOPo->op_first->op_sibling, type); break; @@ -2898,7 +2884,6 @@ Perl_block_end(pTHX_ I32 floor, OP *seq) CALL_BLOCK_HOOKS(bhk_pre_end, &retval); LEAVE_SCOPE(floor); - CopHINTS_set(&PL_compiling, PL_hints); if (needblockscope) PL_hints |= HINT_BLOCK_SCOPE; /* propagate out */ o = pad_leavemy(); @@ -3126,10 +3111,10 @@ Perl_localize(pTHX_ OP *o, I32 lex) while (1) { if (*s && strchr("@$%*", *s) && *++s - && (isALNUM(*s) || UTF8_IS_CONTINUED(*s))) { + && (isWORDCHAR(*s) || UTF8_IS_CONTINUED(*s))) { s++; sigil = TRUE; - while (*s && (isALNUM(*s) || UTF8_IS_CONTINUED(*s))) + while (*s && (isWORDCHAR(*s) || UTF8_IS_CONTINUED(*s))) s++; while (*s && (strchr(", \t\n", *s))) s++; @@ -3209,7 +3194,7 @@ S_op_integerize(pTHX_ OP *o) } static OP * -S_fold_constants(pTHX_ register OP *o) +S_fold_constants(pTHX_ OP *o) { dVAR; OP * VOL curop; @@ -3234,6 +3219,7 @@ S_fold_constants(pTHX_ register OP *o) case OP_LCFIRST: case OP_UC: case OP_LC: + case OP_FC: case OP_SLT: case OP_SGT: case OP_SLE: @@ -3316,6 +3302,7 @@ S_fold_constants(pTHX_ register OP *o) SvREFCNT_inc_simple_void(sv); SvTEMP_off(sv); } + else { assert(SvIMMORTAL(sv)); } break; case 3: /* Something tried to die. Abandon constant folding. */ @@ -3347,10 +3334,15 @@ S_fold_constants(pTHX_ register OP *o) op_free(o); #endif assert(sv); + if (type == OP_STRINGIFY) SvPADTMP_off(sv); + else if (!SvIMMORTAL(sv)) SvPADTMP_on(sv); if (type == OP_RV2GV) newop = newGVOP(OP_GV, 0, MUTABLE_GV(sv)); else + { newop = newSVOP(OP_CONST, OPpCONST_FOLDED<<8, MUTABLE_SV(sv)); + newop->op_folded = 1; + } op_getmad(o,newop,'f'); return newop; @@ -3359,11 +3351,13 @@ S_fold_constants(pTHX_ register OP *o) } static OP * -S_gen_constant_list(pTHX_ register OP *o) +S_gen_constant_list(pTHX_ OP *o) { dVAR; OP *curop; - const I32 oldtmps_floor = PL_tmps_floor; + const SSize_t oldtmps_floor = PL_tmps_floor; + SV **svp; + AV *av; list(o); if (PL_parser && PL_parser->error_count) @@ -3386,7 +3380,11 @@ S_gen_constant_list(pTHX_ register OP *o) o->op_flags |= OPf_PARENS; /* and flatten \(1..2,3) */ o->op_opt = 0; /* needs to be revisited in rpeep() */ curop = ((UNOP*)o)->op_first; - ((UNOP*)o)->op_first = newSVOP(OP_CONST, 0, SvREFCNT_inc_NN(*PL_stack_sp--)); + av = (AV *)SvREFCNT_inc_NN(*PL_stack_sp--); + ((UNOP*)o)->op_first = newSVOP(OP_CONST, 0, (SV *)av); + if (AvFILLp(av) != -1) + for (svp = AvARRAY(av) + AvFILLp(av); svp >= AvARRAY(av); --svp) + SvPADTMP_on(*svp); #ifdef PERL_MAD op_getmad(curop,o,'O'); #else @@ -4119,11 +4117,9 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) rend = r + len; } -/* There are several snags with this code on EBCDIC: - 1. 0xFF is a legal UTF-EBCDIC byte (there are no illegal bytes). - 2. scan_const() in toke.c has encoded chars in native encoding which makes - ranges at least in EBCDIC 0..255 range the bottom odd. -*/ +/* There is a snag with this code on EBCDIC: scan_const() in toke.c has + * encoded chars in native encoding which makes ranges in the EBCDIC 0..255 + * odd. */ if (complement) { U8 tmpbuf[UTF8_MAXBYTES+1]; @@ -4133,11 +4129,11 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) i = 0; transv = newSVpvs(""); while (t < tend) { - cp[2*i] = utf8n_to_uvuni(t, tend-t, &ulen, flags); + cp[2*i] = utf8n_to_uvchr(t, tend-t, &ulen, flags); t += ulen; - if (t < tend && NATIVE_TO_UTF(*t) == 0xff) { + if (t < tend && *t == ILLEGAL_UTF8_BYTE) { t++; - cp[2*i+1] = utf8n_to_uvuni(t, tend-t, &ulen, flags); + cp[2*i+1] = utf8n_to_uvchr(t, tend-t, &ulen, flags); t += ulen; } else { @@ -4150,11 +4146,11 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) UV val = cp[2*j]; diff = val - nextmin; if (diff > 0) { - t = uvuni_to_utf8(tmpbuf,nextmin); + t = uvchr_to_utf8(tmpbuf,nextmin); sv_catpvn(transv, (char*)tmpbuf, t - tmpbuf); if (diff > 1) { - U8 range_mark = UTF_TO_NATIVE(0xff); - t = uvuni_to_utf8(tmpbuf, val - 1); + U8 range_mark = ILLEGAL_UTF8_BYTE; + t = uvchr_to_utf8(tmpbuf, val - 1); sv_catpvn(transv, (char *)&range_mark, 1); sv_catpvn(transv, (char*)tmpbuf, t - tmpbuf); } @@ -4163,13 +4159,13 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) if (val >= nextmin) nextmin = val + 1; } - t = uvuni_to_utf8(tmpbuf,nextmin); + t = uvchr_to_utf8(tmpbuf,nextmin); sv_catpvn(transv, (char*)tmpbuf, t - tmpbuf); { - U8 range_mark = UTF_TO_NATIVE(0xff); + U8 range_mark = ILLEGAL_UTF8_BYTE; sv_catpvn(transv, (char *)&range_mark, 1); } - t = uvuni_to_utf8(tmpbuf, 0x7fffffff); + t = uvchr_to_utf8(tmpbuf, 0x7fffffff); sv_catpvn(transv, (char*)tmpbuf, t - tmpbuf); t = (const U8*)SvPVX_const(transv); tlen = SvCUR(transv); @@ -4190,11 +4186,11 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) while (t < tend || tfirst <= tlast) { /* see if we need more "t" chars */ if (tfirst > tlast) { - tfirst = (I32)utf8n_to_uvuni(t, tend - t, &ulen, flags); + tfirst = (I32)utf8n_to_uvchr(t, tend - t, &ulen, flags); t += ulen; - if (t < tend && NATIVE_TO_UTF(*t) == 0xff) { /* illegal utf8 val indicates range */ + if (t < tend && *t == ILLEGAL_UTF8_BYTE) { /* illegal utf8 val indicates range */ t++; - tlast = (I32)utf8n_to_uvuni(t, tend - t, &ulen, flags); + tlast = (I32)utf8n_to_uvchr(t, tend - t, &ulen, flags); t += ulen; } else @@ -4204,11 +4200,11 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) /* now see if we need more "r" chars */ if (rfirst > rlast) { if (r < rend) { - rfirst = (I32)utf8n_to_uvuni(r, rend - r, &ulen, flags); + rfirst = (I32)utf8n_to_uvchr(r, rend - r, &ulen, flags); r += ulen; - if (r < rend && NATIVE_TO_UTF(*r) == 0xff) { /* illegal utf8 val indicates range */ + if (r < rend && *r == ILLEGAL_UTF8_BYTE) { /* illegal utf8 val indicates range */ r++; - rlast = (I32)utf8n_to_uvuni(r, rend - r, &ulen, flags); + rlast = (I32)utf8n_to_uvchr(r, rend - r, &ulen, flags); r += ulen; } else @@ -4270,7 +4266,7 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) swash = MUTABLE_SV(swash_init("utf8", "", listsv, bits, none)); #ifdef USE_ITHREADS - cPADOPo->op_padix = pad_alloc(OP_TRANS, SVs_PADTMP); + cPADOPo->op_padix = pad_alloc(OP_TRANS, SVf_READONLY); SvREFCNT_dec(PAD_SVl(cPADOPo->op_padix)); PAD_SETSV(cPADOPo->op_padix, swash); SvPADTMP_on(swash); @@ -4376,7 +4372,7 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) if(del && rlen == tlen) { Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "Useless use of /d modifier in transliteration operator"); - } else if(rlen > tlen) { + } else if(rlen > tlen && !complement) { Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "Replacement list is longer than search list"); } @@ -4550,27 +4546,37 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg, I32 floor) LINKLIST(expr); - /* fix up DO blocks; treat each one as a separate little sub */ + /* fix up DO blocks; treat each one as a separate little sub; + * also, mark any arrays as LIST/REF */ if (expr->op_type == OP_LIST) { OP *o; for (o = cLISTOPx(expr)->op_first; o; o = o->op_sibling) { + + if (o->op_type == OP_PADAV || o->op_type == OP_RV2AV) { + assert( !(o->op_flags & OPf_WANT)); + /* push the array rather than its contents. The regex + * engine will retrieve and join the elements later */ + o->op_flags |= (OPf_WANT_LIST | OPf_REF); + continue; + } + if (!(o->op_type == OP_NULL && (o->op_flags & OPf_SPECIAL))) continue; o->op_next = NULL; /* undo temporary hack from above */ scalar(o); LINKLIST(o); if (cLISTOPo->op_first->op_type == OP_LEAVE) { - LISTOP *leave = cLISTOPx(cLISTOPo->op_first); + LISTOP *leaveop = cLISTOPx(cLISTOPo->op_first); /* skip ENTER */ - assert(leave->op_first->op_type == OP_ENTER); - assert(leave->op_first->op_sibling); - o->op_next = leave->op_first->op_sibling; - /* skip LEAVE */ - assert(leave->op_flags & OPf_KIDS); - assert(leave->op_last->op_next = (OP*)leave); - leave->op_next = NULL; /* stop on last op */ - op_null((OP*)leave); + assert(leaveop->op_first->op_type == OP_ENTER); + assert(leaveop->op_first->op_sibling); + o->op_next = leaveop->op_first->op_sibling; + /* skip leave */ + assert(leaveop->op_flags & OPf_KIDS); + assert(leaveop->op_last->op_next == (OP*)leaveop); + leaveop->op_next = NULL; /* stop on last op */ + op_null((OP*)leaveop); } else { /* skip SCOPE */ @@ -4588,6 +4594,12 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg, I32 floor) finalize_optree(o); } } + else if (expr->op_type == OP_PADAV || expr->op_type == OP_RV2AV) { + assert( !(expr->op_flags & OPf_WANT)); + /* push the array rather than its contents. The regex + * engine will retrieve and join the elements later */ + expr->op_flags |= (OPf_WANT_LIST | OPf_REF); + } PL_hints |= HINT_BLOCK_SCOPE; pm = (PMOP*)o; @@ -4597,6 +4609,9 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg, I32 floor) U32 rx_flags = pm->op_pmflags & RXf_PMf_COMPILETIME; regexp_engine const *eng = current_re_engine(); + if (o->op_flags & OPf_SPECIAL) + rx_flags |= RXf_SPLIT; + if (!has_code || !eng->op_comp) { /* compile-time simple constant pattern */ @@ -4673,6 +4688,9 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg, I32 floor) pm->op_pmflags |= PMf_CODELIST_PRIVATE; } + if (o->op_flags & OPf_SPECIAL) + pm->op_pmflags |= PMf_SPLIT; + /* the OP_REGCMAYBE is a placeholder in the non-threaded case * to allow its op_next to be pointed past the regcomp and * preceding stacking ops; @@ -4901,7 +4919,7 @@ Perl_newPADOP(pTHX_ I32 type, I32 flags, SV *sv) return CHECKOP(type, padop); } -#endif /* !USE_ITHREADS */ +#endif /* USE_ITHREADS */ /* =for apidoc Am|OP *|newGVOP|I32 type|I32 flags|GV *gv @@ -4936,7 +4954,7 @@ Perl_newGVOP(pTHX_ I32 type, I32 flags, GV *gv) Constructs, checks, and returns an op of any type that involves an embedded C-level pointer (PV). I is the opcode. I gives the eight bits of C. I supplies the C-level pointer, which -must have been allocated using L; the memory will +must have been allocated using C; the memory will be freed when the op is destroyed. =cut @@ -5318,7 +5336,7 @@ Perl_newSLICEOP(pTHX_ I32 flags, OP *subscript, OP *listval) } STATIC I32 -S_is_list_assignment(pTHX_ register const OP *o) +S_is_list_assignment(pTHX_ const OP *o) { unsigned type; U8 flags; @@ -5400,24 +5418,20 @@ S_aassign_common_vars(pTHX_ OP* o) return TRUE; } else if (curop->op_type == OP_PUSHRE) { + GV *const gv = #ifdef USE_ITHREADS - if (((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff) { - GV *const gv = MUTABLE_GV(PAD_SVl(((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff)); - if (gv == PL_defgv - || (int)GvASSIGN_GENERATION(gv) == PL_generation) - return TRUE; - GvASSIGN_GENERATION_set(gv, PL_generation); - } + ((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff + ? MUTABLE_GV(PAD_SVl(((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff)) + : NULL; #else - GV *const gv - = ((PMOP*)curop)->op_pmreplrootu.op_pmtargetgv; + ((PMOP*)curop)->op_pmreplrootu.op_pmtargetgv; +#endif if (gv) { if (gv == PL_defgv || (int)GvASSIGN_GENERATION(gv) == PL_generation) return TRUE; GvASSIGN_GENERATION_set(gv, PL_generation); } -#endif } else return TRUE; @@ -5589,7 +5603,6 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) = MUTABLE_GV(cSVOPx(tmpop)->op_sv); cSVOPx(tmpop)->op_sv = NULL; /* steal it */ #endif - pm->op_pmflags |= PMf_ONCE; tmpop = cUNOPo->op_first; /* to list (nulled) */ tmpop = ((UNOP*)tmpop)->op_first; /* to pushmark */ tmpop->op_sibling = NULL; /* don't free split */ @@ -5604,9 +5617,22 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) if (PL_modcount < RETURN_UNLIMITED_NUMBER && ((LISTOP*)right)->op_last->op_type == OP_CONST) { - SV *sv = ((SVOP*)((LISTOP*)right)->op_last)->op_sv; + SV ** const svp = + &((SVOP*)((LISTOP*)right)->op_last)->op_sv; + SV * const sv = *svp; if (SvIOK(sv) && SvIVX(sv) == 0) + { + if (right->op_private & OPpSPLIT_IMPLIM) { + /* our own SV, created in ck_split */ + SvREADONLY_off(sv); sv_setiv(sv, PL_modcount+1); + } + else { + /* SV may belong to someone else */ + SvREFCNT_dec(sv); + *svp = newSViv(PL_modcount+1); + } + } } } } @@ -5632,7 +5658,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) Constructs a state op (COP). The state op is normally a C op, but will be a C op if debugging is enabled for currently-compiled -code. The state op is populated from L (or L). +code. The state op is populated from C (or C). If I