X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/27fcb6ee0bb7765fc92447e27763fa4ab7ae9baa..3097ec408171fa0c7fc407cae0375c8689b8a222:/op.c diff --git a/op.c b/op.c index e917d43..d2cb4f0 100644 --- a/op.c +++ b/op.c @@ -365,7 +365,7 @@ S_bad_type(pTHX_ I32 n, const char *t, const char *name, const OP *kid) } STATIC void -S_no_bareword_allowed(pTHX_ const OP *o) +S_no_bareword_allowed(pTHX_ OP *o) { PERL_ARGS_ASSERT_NO_BAREWORD_ALLOWED; @@ -374,6 +374,7 @@ S_no_bareword_allowed(pTHX_ const OP *o) qerror(Perl_mess(aTHX_ "Bareword \"%"SVf"\" not allowed while \"strict subs\" in use", SVfARG(cSVOPo_sv))); + o->op_private &= ~OPpCONST_STRICT; /* prevent warning twice about the same OP */ } /* "register" allocation */ @@ -387,7 +388,7 @@ Perl_allocmy(pTHX_ const char *const name, const STRLEN len, const U32 flags) PERL_ARGS_ASSERT_ALLOCMY; - if (flags) + if (flags & ~SVf_UTF8) Perl_croak(aTHX_ "panic: allocmy illegal flag bits 0x%" UVxf, (UV)flags); @@ -399,7 +400,7 @@ Perl_allocmy(pTHX_ const char *const name, const STRLEN len, const U32 flags) if (len && !(is_our || isALPHA(name[1]) || - (USE_UTF8_IN_NAMES && UTF8_IS_START(name[1])) || + ((flags & SVf_UTF8) && UTF8_IS_START(name[1])) || (name[1] == '_' && (*name == '$' || len > 2)))) { /* name[2] is true if strlen(name) > 2 */ @@ -415,9 +416,10 @@ Perl_allocmy(pTHX_ const char *const name, const STRLEN len, const U32 flags) /* allocate a spare slot and store the name in that slot */ - off = pad_add_name(name, len, - is_our ? padadd_OUR : - PL_parser->in_my == KEY_state ? padadd_STATE : 0, + off = pad_add_name_pvn(name, len, + (is_our ? padadd_OUR : + PL_parser->in_my == KEY_state ? padadd_STATE : 0) + | ( flags & SVf_UTF8 ? SVf_UTF8 : 0 ), PL_parser->in_my_stash, (is_our /* $_ is always in main::, even with our */ @@ -547,18 +549,8 @@ Perl_op_clear(pTHX_ OP *o) PERL_ARGS_ASSERT_OP_CLEAR; #ifdef PERL_MAD - /* if (o->op_madprop && o->op_madprop->mad_next) - abort(); */ - /* FIXME for MAD - if I uncomment these two lines t/op/pack.t fails with - "modification of a read only value" for a reason I can't fathom why. - It's the "" stringification of $_, where $_ was set to '' in a foreach - loop, but it defies simplification into a small test case. - However, commenting them out has caused ext/List/Util/t/weak.t to fail - the last test. */ - /* - mad_free(o->op_madprop); - o->op_madprop = 0; - */ + mad_free(o->op_madprop); + o->op_madprop = 0; #endif retry: @@ -581,8 +573,7 @@ Perl_op_clear(pTHX_ OP *o) case OP_GVSV: case OP_GV: case OP_AELEMFAST: - if (! (o->op_type == OP_AELEMFAST && o->op_flags & OPf_SPECIAL)) { - /* not an OP_PADAV replacement */ + { GV *gv = (o->op_type == OP_GV || o->op_type == OP_GVSV) #ifdef USE_ITHREADS && PL_curpad @@ -970,14 +961,9 @@ Perl_scalar(pTHX_ OP *o) do_kids: while (kid) { OP *sib = kid->op_sibling; - if (sib && kid->op_type != OP_LEAVEWHEN) { - if (sib->op_type == OP_BREAK && sib->op_flags & OPf_SPECIAL) { - scalar(kid); - scalarvoid(sib); - break; - } else - scalarvoid(kid); - } else + if (sib && kid->op_type != OP_LEAVEWHEN) + scalarvoid(kid); + else scalar(kid); kid = sib; } @@ -1079,6 +1065,7 @@ Perl_scalarvoid(pTHX_ OP *o) case OP_SPRINTF: case OP_AELEM: case OP_AELEMFAST: + case OP_AELEMFAST_LEX: case OP_ASLICE: case OP_HELEM: case OP_HSLICE: @@ -1183,8 +1170,6 @@ Perl_scalarvoid(pTHX_ OP *o) } else useless = "a constant (undef)"; - if (o->op_private & OPpCONST_ARYBASE) - useless = NULL; /* don't warn on optimised away booleans, eg * use constant Foo, 5; Foo || print; */ if (cSVOPo->op_private & OPpCONST_SHORTCIRCUIT) @@ -1232,6 +1217,52 @@ Perl_scalarvoid(pTHX_ OP *o) o->op_ppaddr = PL_ppaddr[OP_I_PREDEC]; break; + case OP_SASSIGN: { + OP *rv2gv; + UNOP *refgen, *rv2cv; + LISTOP *exlist; + + if ((o->op_private & ~OPpASSIGN_BACKWARDS) != 2) + break; + + rv2gv = ((BINOP *)o)->op_last; + if (!rv2gv || rv2gv->op_type != OP_RV2GV) + break; + + refgen = (UNOP *)((BINOP *)o)->op_first; + + if (!refgen || refgen->op_type != OP_REFGEN) + break; + + exlist = (LISTOP *)refgen->op_first; + if (!exlist || exlist->op_type != OP_NULL + || exlist->op_targ != OP_LIST) + break; + + if (exlist->op_first->op_type != OP_PUSHMARK) + break; + + rv2cv = (UNOP*)exlist->op_last; + + if (rv2cv->op_type != OP_RV2CV) + break; + + assert ((rv2gv->op_private & OPpDONT_INIT_GV) == 0); + assert ((o->op_private & OPpASSIGN_CV_TO_GV) == 0); + assert ((rv2cv->op_private & OPpMAY_RETURN_CONSTANT) == 0); + + o->op_private |= OPpASSIGN_CV_TO_GV; + rv2gv->op_private |= OPpDONT_INIT_GV; + rv2cv->op_private |= OPpMAY_RETURN_CONSTANT; + + break; + } + + case OP_AASSIGN: { + inplace_aassign(o); + break; + } + case OP_OR: case OP_AND: kid = cLOGOPo->op_first; @@ -1355,14 +1386,9 @@ Perl_list(pTHX_ OP *o) do_kids: while (kid) { OP *sib = kid->op_sibling; - if (sib && kid->op_type != OP_LEAVEWHEN) { - if (sib->op_type == OP_BREAK && sib->op_flags & OPf_SPECIAL) { - list(kid); - scalarvoid(sib); - break; - } else - scalarvoid(kid); - } else + if (sib && kid->op_type != OP_LEAVEWHEN) + scalarvoid(kid); + else list(kid); kid = sib; } @@ -1415,6 +1441,253 @@ S_modkids(pTHX_ OP *o, I32 type) } /* +=for apidoc finalize_optree + +This function finalizes the optree. Should be called directly after +the complete optree is built. It does some additional +checking which can't be done in the normal ck_xxx functions and makes +the tree thread-safe. + +=cut +*/ +void +Perl_finalize_optree(pTHX_ OP* o) +{ + PERL_ARGS_ASSERT_FINALIZE_OPTREE; + + ENTER; + SAVEVPTR(PL_curcop); + + finalize_op(o); + + LEAVE; +} + +void +S_finalize_op(pTHX_ OP* o) +{ + PERL_ARGS_ASSERT_FINALIZE_OP; + +#if defined(PERL_MAD) && defined(USE_ITHREADS) + { + /* Make sure mad ops are also thread-safe */ + MADPROP *mp = o->op_madprop; + while (mp) { + if (mp->mad_type == MAD_OP && mp->mad_vlen) { + OP *prop_op = (OP *) mp->mad_val; + /* We only need "Relocate sv to the pad for thread safety.", but this + easiest way to make sure it traverses everything */ + if (prop_op->op_type == OP_CONST) + cSVOPx(prop_op)->op_private &= ~OPpCONST_STRICT; + finalize_op(prop_op); + } + mp = mp->mad_next; + } + } +#endif + + switch (o->op_type) { + case OP_NEXTSTATE: + case OP_DBSTATE: + PL_curcop = ((COP*)o); /* for warnings */ + break; + case OP_EXEC: + if ( o->op_sibling + && (o->op_sibling->op_type == OP_NEXTSTATE || o->op_sibling->op_type == OP_DBSTATE) + && ckWARN(WARN_SYNTAX)) + { + if (o->op_sibling->op_sibling) { + const OPCODE type = o->op_sibling->op_sibling->op_type; + if (type != OP_EXIT && type != OP_WARN && type != OP_DIE) { + const line_t oldline = CopLINE(PL_curcop); + CopLINE_set(PL_curcop, CopLINE((COP*)o->op_sibling)); + Perl_warner(aTHX_ packWARN(WARN_EXEC), + "Statement unlikely to be reached"); + Perl_warner(aTHX_ packWARN(WARN_EXEC), + "\t(Maybe you meant system() when you said exec()?)\n"); + CopLINE_set(PL_curcop, oldline); + } + } + } + break; + + case OP_GV: + if ((o->op_private & OPpEARLY_CV) && ckWARN(WARN_PROTOTYPE)) { + GV * const gv = cGVOPo_gv; + if (SvTYPE(gv) == SVt_PVGV && GvCV(gv) && SvPVX_const(GvCV(gv))) { + /* XXX could check prototype here instead of just carping */ + SV * const sv = sv_newmortal(); + gv_efullname3(sv, gv, NULL); + Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), + "%"SVf"() called too early to check prototype", + SVfARG(sv)); + } + } + break; + + case OP_CONST: + if (cSVOPo->op_private & OPpCONST_STRICT) + no_bareword_allowed(o); + /* FALLTHROUGH */ +#ifdef USE_ITHREADS + case OP_HINTSEVAL: + case OP_METHOD_NAMED: + /* Relocate sv to the pad for thread safety. + * 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); + SvREADONLY_on(PAD_SVl(ix)); + SvREFCNT_dec(cSVOPo->op_sv); + } + else 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 + PL_sv_undef as a "free" AV entry and will merrily + replace them with a new SV, causing pad_alloc to think + that this pad slot is free. (When, clearly, it is not) + */ + SvOK_off(PAD_SVl(ix)); + SvPADTMP_on(PAD_SVl(ix)); + SvREADONLY_on(PAD_SVl(ix)); + } + 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. */ + SvREADONLY_on(PAD_SVl(ix)); + } + cSVOPo->op_sv = NULL; + o->op_targ = ix; + } +#endif + break; + + case OP_HELEM: { + UNOP *rop; + SV *lexname; + GV **fields; + SV **svp, *sv; + const char *key = NULL; + STRLEN keylen; + + if (((BINOP*)o)->op_last->op_type != OP_CONST) + break; + + /* Make the CONST have a shared SV */ + svp = cSVOPx_svp(((BINOP*)o)->op_last); + if ((!SvFAKE(sv = *svp) || !SvREADONLY(sv)) + && SvTYPE(sv) < SVt_PVMG && !SvROK(sv)) { + key = SvPV_const(sv, keylen); + lexname = newSVpvn_share(key, + SvUTF8(sv) ? -(I32)keylen : (I32)keylen, + 0); + SvREFCNT_dec(sv); + *svp = lexname; + } + + if ((o->op_private & (OPpLVAL_INTRO))) + break; + + rop = (UNOP*)((BINOP*)o)->op_first; + if (rop->op_type != OP_RV2HV || rop->op_first->op_type != OP_PADSV) + break; + lexname = *av_fetch(PL_comppad_name, rop->op_first->op_targ, TRUE); + if (!SvPAD_TYPED(lexname)) + break; + fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE); + if (!fields || !GvHV(*fields)) + break; + key = SvPV_const(*svp, keylen); + if (!hv_fetch(GvHV(*fields), key, + SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE)) { + Perl_croak(aTHX_ "No such class field \"%s\" " + "in variable %s of type %s", + key, SvPV_nolen_const(lexname), HvNAME_get(SvSTASH(lexname))); + } + break; + } + + case OP_HSLICE: { + UNOP *rop; + SV *lexname; + GV **fields; + SV **svp; + const char *key; + STRLEN keylen; + SVOP *first_key_op, *key_op; + + if ((o->op_private & (OPpLVAL_INTRO)) + /* I bet there's always a pushmark... */ + || ((LISTOP*)o)->op_first->op_sibling->op_type != OP_LIST) + /* hmmm, no optimization if list contains only one key. */ + break; + rop = (UNOP*)((LISTOP*)o)->op_last; + if (rop->op_type != OP_RV2HV) + break; + if (rop->op_first->op_type == OP_PADSV) + /* @$hash{qw(keys here)} */ + rop = (UNOP*)rop->op_first; + else { + /* @{$hash}{qw(keys here)} */ + if (rop->op_first->op_type == OP_SCOPE + && cLISTOPx(rop->op_first)->op_last->op_type == OP_PADSV) + { + rop = (UNOP*)cLISTOPx(rop->op_first)->op_last; + } + else + break; + } + + lexname = *av_fetch(PL_comppad_name, rop->op_targ, TRUE); + if (!SvPAD_TYPED(lexname)) + break; + fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE); + if (!fields || !GvHV(*fields)) + break; + /* Again guessing that the pushmark can be jumped over.... */ + first_key_op = (SVOP*)((LISTOP*)((LISTOP*)o)->op_first->op_sibling) + ->op_first->op_sibling; + for (key_op = first_key_op; key_op; + key_op = (SVOP*)key_op->op_sibling) { + if (key_op->op_type != OP_CONST) + continue; + svp = cSVOPx_svp(key_op); + key = SvPV_const(*svp, keylen); + if (!hv_fetch(GvHV(*fields), key, + SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE)) { + Perl_croak(aTHX_ "No such class field \"%s\" " + "in variable %s of type %s", + key, SvPV_nolen(lexname), HvNAME_get(SvSTASH(lexname))); + } + } + break; + } + case OP_SUBST: { + if (cPMOPo->op_pmreplrootu.op_pmreplroot) + finalize_op(cPMOPo->op_pmreplrootu.op_pmreplroot); + break; + } + default: + break; + } + + if (o->op_flags & OPf_KIDS) { + OP *kid; + for (kid = cUNOPo->op_first; kid; kid = kid->op_sibling) + finalize_op(kid); + } +} + +/* =for apidoc Amx|OP *|op_lvalue|OP *o|I32 type Propagate lvalue ("modifiable") context to an op and its children. @@ -1434,7 +1707,7 @@ such as C<$$x = 5> which might have to vivify a reference in C<$x>. */ OP * -Perl_op_lvalue(pTHX_ OP *o, I32 type) +Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags) { dVAR; OP *kid; @@ -1450,50 +1723,32 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type) return o; } + assert( (o->op_flags & OPf_WANT) != OPf_WANT_VOID ); + switch (o->op_type) { case OP_UNDEF: localize = 0; PL_modcount++; return o; - case OP_CONST: - if (!(o->op_private & OPpCONST_ARYBASE)) - goto nomod; - localize = 0; - if (PL_eval_start && PL_eval_start->op_type == OP_CONST) { - CopARYBASE_set(&PL_compiling, - (I32)SvIV(cSVOPx(PL_eval_start)->op_sv)); - PL_eval_start = 0; - } - else if (!type) { - SAVECOPARYBASE(&PL_compiling); - CopARYBASE_set(&PL_compiling, 0); - } - else if (type == OP_REFGEN) - goto nomod; - else - Perl_croak(aTHX_ "That use of $[ is unsupported"); - break; case OP_STUB: if ((o->op_flags & OPf_PARENS) || PL_madskills) break; goto nomod; case OP_ENTERSUB: - if ((type == OP_UNDEF || type == OP_REFGEN) && + if ((type == OP_UNDEF || type == OP_REFGEN || type == OP_LOCK) && !(o->op_flags & OPf_STACKED)) { o->op_type = OP_RV2CV; /* entersub => rv2cv */ - /* The default is to set op_private to the number of children, - which for a UNOP such as RV2CV is always 1. And w're using - the bit for a flag in RV2CV, so we need it clear. */ + /* Both ENTERSUB and RV2CV use this bit, but for different pur- + poses, so we need it clear. */ o->op_private &= ~1; o->op_ppaddr = PL_ppaddr[OP_RV2CV]; assert(cUNOPo->op_first->op_type == OP_NULL); op_null(((LISTOP*)cUNOPo->op_first)->op_first);/* disable pushmark */ break; } - else if (o->op_private & OPpENTERSUB_NOMOD) - return o; else { /* lvalue subroutine call */ - o->op_private |= OPpLVAL_INTRO; + o->op_private |= OPpLVAL_INTRO + |(OPpENTERSUB_INARGS * (type == OP_LEAVESUBLV)); PL_modcount = RETURN_UNLIMITED_NUMBER; if (type == OP_GREPSTART || type == OP_ENTERSUB || type == OP_REFGEN) { /* Backward compatibility mode: */ @@ -1578,8 +1833,10 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type) /* FALL THROUGH */ default: nomod: + if (flags & OP_LVALUE_NO_CROAK) return NULL; /* grep, foreach, subcalls, refgen */ - if (type == OP_GREPSTART || type == OP_ENTERSUB || type == OP_REFGEN) + if (type == OP_GREPSTART || type == OP_ENTERSUB + || type == OP_REFGEN || type == OP_LEAVESUBLV) break; yyerror(Perl_form(aTHX_ "Can't modify %s in %s", (o->op_type == OP_NULL && (o->op_flags & OPf_SPECIAL) @@ -1664,6 +1921,7 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type) break; case OP_AELEMFAST: + case OP_AELEMFAST_LEX: localize = -1; PL_modcount++; break; @@ -1681,8 +1939,8 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type) case OP_PADSV: PL_modcount++; if (!type) /* local() */ - Perl_croak(aTHX_ "Can't localize lexical variable %s", - PAD_COMPNAME_PV(o->op_targ)); + Perl_croak(aTHX_ "Can't localize lexical variable %"SVf, + PAD_COMPNAME_SV(o->op_targ)); break; case OP_PUSHMARK: @@ -1690,7 +1948,8 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type) break; case OP_KEYS: - if (type != OP_SASSIGN) + case OP_RKEYS: + if (type != OP_SASSIGN && type != OP_LEAVESUBLV) goto nomod; goto lvalue_func; case OP_SUBSTR: @@ -1699,9 +1958,9 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type) /* FALL THROUGH */ case OP_POS: case OP_VEC: + lvalue_func: if (type == OP_LEAVESUBLV) o->op_private |= OPpMAYBE_LVSUB; - lvalue_func: pad_free(o->op_targ); o->op_targ = pad_alloc(o->op_type, SVs_PADMY); assert(SvTYPE(PAD_SV(o->op_targ)) == SVt_NULL); @@ -1744,7 +2003,10 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type) case OP_LIST: localize = 0; for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) - op_lvalue(kid, type); + /* elements might be in void context because the list is + in scalar context or because they are attribute sub calls */ + if ( (kid->op_flags & OPf_WANT) != OPf_WANT_VOID ) + op_lvalue(kid, type); break; case OP_RETURN: @@ -1785,18 +2047,10 @@ Perl_op_lvalue(pTHX_ OP *o, I32 type) return o; } -/* Do not use this. It will be removed after 5.14. */ -OP * -Perl_mod(pTHX_ OP *o, I32 type) -{ - return op_lvalue(o,type); -} - - STATIC bool S_scalar_mod_type(const OP *o, I32 type) { - PERL_ARGS_ASSERT_SCALAR_MOD_TYPE; + assert(o || type != OP_SASSIGN); switch (type) { case OP_SASSIGN: @@ -1893,7 +2147,7 @@ Perl_doref(pTHX_ OP *o, I32 type, bool set_op_ref) switch (o->op_type) { case OP_ENTERSUB: - if ((type == OP_EXISTS || type == OP_DEFINED || type == OP_LOCK) && + if ((type == OP_EXISTS || type == OP_DEFINED) && !(o->op_flags & OPf_STACKED)) { o->op_type = OP_RV2CV; /* entersub => rv2cv */ o->op_ppaddr = PL_ppaddr[OP_RV2CV]; @@ -1902,6 +2156,13 @@ Perl_doref(pTHX_ OP *o, I32 type, bool set_op_ref) o->op_flags |= OPf_SPECIAL; o->op_private &= ~1; } + else if (type == OP_RV2SV || type == OP_RV2AV || type == OP_RV2HV){ + o->op_private |= (type == OP_RV2AV ? OPpDEREF_AV + : type == OP_RV2HV ? OPpDEREF_HV + : OPpDEREF_SV); + o->op_flags |= OPf_MOD; + } + break; case OP_COND_EXPR: @@ -2082,7 +2343,6 @@ S_apply_attrs_my(pTHX_ HV *stash, OP *target, OP *attrs, OP **imopsp) op_append_elem(OP_LIST, op_prepend_elem(OP_LIST, pack, list(arg)), newSVOP(OP_METHOD_NAMED, 0, meth))); - imop->op_private |= OPpENTERSUB_NOMOD; /* Combine the ops. */ *imopsp = op_append_elem(OP_LIST, *imopsp, imop); @@ -2247,8 +2507,19 @@ Perl_my_attrs(pTHX_ OP *o, OP *attrs) o = scalar(op_append_list(OP_LIST, rops, o)); o->op_private |= OPpLVAL_INTRO; } - else + else { + /* The listop in rops might have a pushmark at the beginning, + which will mess up list assignment. */ + LISTOP * const lrops = (LISTOP *)rops; /* for brevity */ + if (rops->op_type == OP_LIST && + lrops->op_first && lrops->op_first->op_type == OP_PUSHMARK) + { + OP * const pushmark = lrops->op_first; + lrops->op_first = pushmark->op_sibling; + op_free(pushmark); + } o = op_append_list(OP_LIST, o, rops); + } } PL_parser->in_my = FALSE; PL_parser->in_my_stash = NULL; @@ -2450,7 +2721,7 @@ STATIC OP * S_newDEFSVOP(pTHX) { dVAR; - const PADOFFSET offset = Perl_pad_findmy(aTHX_ STR_WITH_LEN("$_"), 0); + const PADOFFSET offset = pad_findmy_pvs("$_", 0); if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS_isOUR(offset)) { return newSVREF(newGVOP(OP_GV, 0, PL_defgv)); } @@ -2469,11 +2740,23 @@ Perl_newPROG(pTHX_ OP *o) PERL_ARGS_ASSERT_NEWPROG; if (PL_in_eval) { + PERL_CONTEXT *cx; if (PL_eval_root) return; PL_eval_root = newUNOP(OP_LEAVEEVAL, ((PL_in_eval & EVAL_KEEPERR) ? OPf_SPECIAL : 0), o); + + cx = &cxstack[cxstack_ix]; + assert(CxTYPE(cx) == CXt_EVAL); + + if ((cx->blk_gimme & G_WANT) == G_VOID) + scalarvoid(PL_eval_root); + else if ((cx->blk_gimme & G_WANT) == G_ARRAY) + list(PL_eval_root); + else + scalar(PL_eval_root); + /* don't use LINKLIST, since PL_eval_root might indirect through * a rather expensive function call and LINKLIST evaluates its * argument more than once */ @@ -2482,6 +2765,8 @@ Perl_newPROG(pTHX_ OP *o) OpREFCNT_set(PL_eval_root, 1); PL_eval_root->op_next = 0; CALL_PEEP(PL_eval_start); + finalize_optree(PL_eval_root); + } else { if (o->op_type == OP_STUB) { @@ -2497,6 +2782,7 @@ Perl_newPROG(pTHX_ OP *o) OpREFCNT_set(PL_main_root, 1); PL_main_root->op_next = 0; CALL_PEEP(PL_main_start); + finalize_optree(PL_main_root); PL_compcv = 0; /* Register with debugger */ @@ -2588,6 +2874,45 @@ Perl_jmaybe(pTHX_ OP *o) return o; } +PERL_STATIC_INLINE OP * +S_op_std_init(pTHX_ OP *o) +{ + I32 type = o->op_type; + + PERL_ARGS_ASSERT_OP_STD_INIT; + + if (PL_opargs[type] & OA_RETSCALAR) + scalar(o); + if (PL_opargs[type] & OA_TARGET && !o->op_targ) + o->op_targ = pad_alloc(type, SVs_PADTMP); + + return o; +} + +PERL_STATIC_INLINE OP * +S_op_integerize(pTHX_ OP *o) +{ + I32 type = o->op_type; + + PERL_ARGS_ASSERT_OP_INTEGERIZE; + + /* integerize op, unless it happens to be C<-foo>. + * XXX should pp_i_negate() do magic string negation instead? */ + if ((PL_opargs[type] & OA_OTHERINT) && (PL_hints & HINT_INTEGER) + && !(type == OP_NEGATE && cUNOPo->op_first->op_type == OP_CONST + && (cUNOPo->op_first->op_private & OPpCONST_BARE))) + { + dVAR; + o->op_ppaddr = PL_ppaddr[type = ++(o->op_type)]; + } + + if (type == OP_NEGATE) + /* XXX might want a ck_negate() for this */ + cUNOPo->op_first->op_private &= ~OPpCONST_STRICT; + + return o; +} + static OP * S_fold_constants(pTHX_ register OP *o) { @@ -2606,28 +2931,10 @@ S_fold_constants(pTHX_ register OP *o) PERL_ARGS_ASSERT_FOLD_CONSTANTS; - if (PL_opargs[type] & OA_RETSCALAR) - scalar(o); - if (PL_opargs[type] & OA_TARGET && !o->op_targ) - o->op_targ = pad_alloc(type, SVs_PADTMP); - - /* integerize op, unless it happens to be C<-foo>. - * XXX should pp_i_negate() do magic string negation instead? */ - if ((PL_opargs[type] & OA_OTHERINT) && (PL_hints & HINT_INTEGER) - && !(type == OP_NEGATE && cUNOPo->op_first->op_type == OP_CONST - && (cUNOPo->op_first->op_private & OPpCONST_BARE))) - { - o->op_ppaddr = PL_ppaddr[type = ++(o->op_type)]; - } - if (!(PL_opargs[type] & OA_FOLDCONST)) goto nope; switch (type) { - case OP_NEGATE: - /* XXX might want a ck_negate() for this */ - cUNOPo->op_first->op_private &= ~OPpCONST_STRICT; - break; case OP_UCFIRST: case OP_LCFIRST: case OP_UC: @@ -2682,8 +2989,16 @@ S_fold_constants(pTHX_ register OP *o) case 0: CALLRUNOPS(aTHX); sv = *(PL_stack_sp--); - if (o->op_targ && sv == PAD_SV(o->op_targ)) /* grab pad temp? */ + if (o->op_targ && sv == PAD_SV(o->op_targ)) { /* grab pad temp? */ +#ifdef PERL_MAD + /* Can't simply swipe the SV from the pad, because that relies on + the op being freed "real soon now". Under MAD, this doesn't + happen (see the #ifdef below). */ + sv = newSVsv(sv); +#else pad_swipe(o->op_targ, FALSE); +#endif + } else if (SvTEMP(sv)) { /* grab mortal temp? */ SvREFCNT_inc_simple_void(sv); SvTEMP_off(sv); @@ -2779,6 +3094,13 @@ Perl_convert(pTHX_ I32 type, I32 flags, OP *o) if (!(PL_opargs[type] & OA_MARK)) op_null(cLISTOPo->op_first); + else { + OP * const kid2 = cLISTOPo->op_first->op_sibling; + if (kid2 && kid2->op_type == OP_COREARGS) { + op_null(cLISTOPo->op_first); + kid2->op_private |= OPpCOREARGS_PUSHMARK; + } + } o->op_type = (OPCODE)type; o->op_ppaddr = PL_ppaddr[type]; @@ -2788,7 +3110,7 @@ Perl_convert(pTHX_ I32 type, I32 flags, OP *o) if (o->op_type != (unsigned)type) return o; - return fold_constants(o); + return fold_constants(op_integerize(op_std_init(o))); } /* @@ -3138,8 +3460,7 @@ Perl_newMADsv(pTHX_ char key, SV* sv) MADPROP * Perl_newMADPROP(pTHX_ char key, char type, void* val, I32 vlen) { - MADPROP *mp; - Newxz(mp, 1, MADPROP); + MADPROP *const mp = (MADPROP *) PerlMemShared_malloc(sizeof(MADPROP)); mp->mad_next = 0; mp->mad_key = key; mp->mad_vlen = vlen; @@ -3176,7 +3497,7 @@ Perl_mad_free(pTHX_ MADPROP* mp) PerlIO_printf(PerlIO_stderr(), "Unrecognized mad\n"); break; } - Safefree(mp); + PerlMemShared_free(mp); } #endif @@ -3337,7 +3658,7 @@ Perl_newUNOP(pTHX_ I32 type, I32 flags, OP *first) if (unop->op_next) return (OP*)unop; - return fold_constants((OP *) unop); + return fold_constants(op_integerize(op_std_init((OP *) unop))); } /* @@ -3387,7 +3708,7 @@ Perl_newBINOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) binop->op_last = binop->op_first->op_sibling; - return fold_constants((OP *)binop); + return fold_constants(op_integerize(op_std_init((OP *)binop))); } static int uvcompare(const void *a, const void *b) @@ -4557,6 +4878,76 @@ S_is_list_assignment(pTHX_ register const OP *o) } /* + Helper function for newASSIGNOP to detection commonality between the + lhs and the rhs. Marks all variables with PL_generation. If it + returns TRUE the assignment must be able to handle common variables. +*/ +PERL_STATIC_INLINE bool +S_aassign_common_vars(pTHX_ OP* o) +{ + OP *curop; + for (curop = cUNOPo->op_first; curop; curop=curop->op_sibling) { + if (PL_opargs[curop->op_type] & OA_DANGEROUS) { + if (curop->op_type == OP_GV) { + GV *gv = cGVOPx_gv(curop); + if (gv == PL_defgv + || (int)GvASSIGN_GENERATION(gv) == PL_generation) + return TRUE; + GvASSIGN_GENERATION_set(gv, PL_generation); + } + else if (curop->op_type == OP_PADSV || + curop->op_type == OP_PADAV || + curop->op_type == OP_PADHV || + curop->op_type == OP_PADANY) + { + if (PAD_COMPNAME_GEN(curop->op_targ) + == (STRLEN)PL_generation) + return TRUE; + PAD_COMPNAME_GEN_set(curop->op_targ, PL_generation); + + } + else if (curop->op_type == OP_RV2CV) + return TRUE; + else if (curop->op_type == OP_RV2SV || + curop->op_type == OP_RV2AV || + curop->op_type == OP_RV2HV || + curop->op_type == OP_RV2GV) { + if (cUNOPx(curop)->op_first->op_type != OP_GV) /* funny deref? */ + return TRUE; + } + else if (curop->op_type == OP_PUSHRE) { +#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); + } +#else + GV *const gv + = ((PMOP*)curop)->op_pmreplrootu.op_pmtargetgv; + if (gv) { + if (gv == PL_defgv + || (int)GvASSIGN_GENERATION(gv) == PL_generation) + return TRUE; + GvASSIGN_GENERATION_set(gv, PL_generation); + } +#endif + } + else + return TRUE; + } + + if (curop->op_flags & OPf_KIDS) { + if (aassign_common_vars(curop)) + return TRUE; + } + } + return FALSE; +} + +/* =for apidoc Am|OP *|newASSIGNOP|I32 flags|OP *left|I32 optype|OP *right Constructs, checks, and returns an assignment op. I and I @@ -4604,18 +4995,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) bool maybe_common_vars = TRUE; PL_modcount = 0; - /* Grandfathering $[ assignment here. Bletch.*/ - /* Only simple assignments like C<< ($[) = 1 >> are allowed */ - PL_eval_start = (left->op_type == OP_CONST) ? right : NULL; left = op_lvalue(left, OP_AASSIGN); - if (PL_eval_start) - PL_eval_start = 0; - else if (left->op_type == OP_CONST) { - deprecate("assignment to $["); - /* FIXME for MAD */ - /* Result of assignment is always 1 (or we'd be dead already) */ - return newSVOP(OP_CONST, 0, newSViv(1)); - } curop = list(force_list(left)); o = newBINOP(OP_AASSIGN, flags, list(force_list(right)), curop); o->op_private = (U8)(0 | (flags >> 8)); @@ -4694,64 +5074,10 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) */ if (maybe_common_vars) { - OP *lastop = o; PL_generation++; - for (curop = LINKLIST(o); curop != o; curop = LINKLIST(curop)) { - if (PL_opargs[curop->op_type] & OA_DANGEROUS) { - if (curop->op_type == OP_GV) { - GV *gv = cGVOPx_gv(curop); - if (gv == PL_defgv - || (int)GvASSIGN_GENERATION(gv) == PL_generation) - break; - GvASSIGN_GENERATION_set(gv, PL_generation); - } - else if (curop->op_type == OP_PADSV || - curop->op_type == OP_PADAV || - curop->op_type == OP_PADHV || - curop->op_type == OP_PADANY) - { - if (PAD_COMPNAME_GEN(curop->op_targ) - == (STRLEN)PL_generation) - break; - PAD_COMPNAME_GEN_set(curop->op_targ, PL_generation); - - } - else if (curop->op_type == OP_RV2CV) - break; - else if (curop->op_type == OP_RV2SV || - curop->op_type == OP_RV2AV || - curop->op_type == OP_RV2HV || - curop->op_type == OP_RV2GV) { - if (lastop->op_type != OP_GV) /* funny deref? */ - break; - } - else if (curop->op_type == OP_PUSHRE) { -#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) - break; - GvASSIGN_GENERATION_set(gv, PL_generation); - } -#else - GV *const gv - = ((PMOP*)curop)->op_pmreplrootu.op_pmtargetgv; - if (gv) { - if (gv == PL_defgv - || (int)GvASSIGN_GENERATION(gv) == PL_generation) - break; - GvASSIGN_GENERATION_set(gv, PL_generation); - } -#endif - } - else - break; - } - lastop = curop; - } - if (curop != o) + if (aassign_common_vars(o)) o->op_private |= OPpASSIGN_COMMON; + LINKLIST(o); } if (right && right->op_type == OP_SPLIT && !PL_madskills) { @@ -4811,19 +5137,8 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) scalar(right)); } else { - PL_eval_start = right; /* Grandfathering $[ assignment here. Bletch.*/ o = newBINOP(OP_SASSIGN, flags, scalar(right), op_lvalue(scalar(left), OP_SASSIGN) ); - if (PL_eval_start) - PL_eval_start = 0; - else { - if (!PL_madskills) { /* assignment to $[ is ignored when making a mad dump */ - deprecate("assignment to $["); - op_free(o); - o = newSVOP(OP_CONST, 0, newSViv(CopARYBASE_get(&PL_compiling))); - o->op_private |= OPpCONST_ARYBASE; - } - } } return o; } @@ -4871,13 +5186,10 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o) cop->op_next = (OP*)cop; cop->cop_seq = seq; - /* CopARYBASE is now "virtual", in that it's stored as a flag bit in - CopHINTS and a possible value in cop_hints_hash, so no need to copy it. - */ cop->cop_warnings = DUP_WARNINGS(PL_curcop->cop_warnings); CopHINTHASH_set(cop, cophh_copy(CopHINTHASH_get(PL_curcop))); if (label) { - Perl_store_cop_label(aTHX_ cop, label, strlen(label), 0); + Perl_cop_store_label(aTHX_ cop, label, strlen(label), 0); PL_hints |= HINT_BLOCK_SCOPE; /* It seems that we need to defer freeing this pointer, as other parts @@ -5105,7 +5417,8 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp) if (k1->op_type == OP_READDIR || k1->op_type == OP_GLOB || (k1->op_type == OP_NULL && k1->op_targ == OP_GLOB) - || k1->op_type == OP_EACH) + || k1->op_type == OP_EACH + || k1->op_type == OP_AEACH) { warnop = ((k1->op_type == OP_NULL) ? (OPCODE)k1->op_targ : k1->op_type); @@ -5291,6 +5604,12 @@ Perl_newRANGE(pTHX_ I32 flags, OP *left, OP *right) flip->op_private = left->op_type == OP_CONST ? OPpFLIP_LINENUM : 0; flop->op_private = right->op_type == OP_CONST ? OPpFLIP_LINENUM : 0; + /* check barewords before they might be optimized aways */ + if (flip->op_private && cSVOPx(left)->op_private & OPpCONST_STRICT) + no_bareword_allowed(left); + if (flop->op_private && cSVOPx(right)->op_private & OPpCONST_STRICT) + no_bareword_allowed(right); + flip->op_next = o; if (!flip->op_private || !flop->op_private) LINKLIST(o); /* blow off optimizer unless constant */ @@ -5349,7 +5668,8 @@ Perl_newLOOPOP(pTHX_ I32 flags, I32 debuggable, OP *expr, OP *block) if (k1 && (k1->op_type == OP_READDIR || k1->op_type == OP_GLOB || (k1->op_type == OP_NULL && k1->op_targ == OP_GLOB) - || k1->op_type == OP_EACH)) + || k1->op_type == OP_EACH + || k1->op_type == OP_AEACH)) expr = newUNOP(OP_DEFINED, 0, expr); break; } @@ -5437,7 +5757,8 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, if (k1 && (k1->op_type == OP_READDIR || k1->op_type == OP_GLOB || (k1->op_type == OP_NULL && k1->op_targ == OP_GLOB) - || k1->op_type == OP_EACH)) + || k1->op_type == OP_EACH + || k1->op_type == OP_AEACH)) expr = newUNOP(OP_DEFINED, 0, expr); break; } @@ -5579,7 +5900,7 @@ Perl_newFOROP(pTHX_ I32 flags, OP *sv, OP *expr, OP *block, OP *cont) } } else { - const PADOFFSET offset = Perl_pad_findmy(aTHX_ STR_WITH_LEN("$_"), 0); + const PADOFFSET offset = pad_findmy_pvs("$_", 0); if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS_isOUR(offset)) { sv = newGVOP(OP_GV, 0, PL_defgv); } @@ -5918,10 +6239,7 @@ Perl_newWHENOP(pTHX_ OP *cond, OP *block) scalar(ref_array_or_hash(cond))); } - return newGIVWHENOP( - cond_op, - op_append_elem(block->op_type, block, newOP(OP_BREAK, OPf_SPECIAL)), - OP_ENTERWHEN, OP_LEAVEWHEN, 0); + return newGIVWHENOP(cond_op, block, OP_ENTERWHEN, OP_LEAVEWHEN, 0); } void @@ -5930,8 +6248,6 @@ Perl_cv_ckproto_len(pTHX_ const CV *cv, const GV *gv, const char *p, { PERL_ARGS_ASSERT_CV_CKPROTO_LEN; - /* Can't just use a strcmp on the prototype, as CONSTSUBs "cheat" by - relying on SvCUR, and doubling up the buffer to hold CvFILE(). */ if (((!p != !SvPOK(cv)) /* One has prototype, one has not. */ || (p && (len != SvCUR(cv) /* Not the same length. */ || memNE(p, SvPVX_const(cv), len)))) @@ -6196,13 +6512,18 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) #ifdef PERL_MAD || block->op_type == OP_NULL #endif - )&& !attrs) { + )) { if (CvFLAGS(PL_compcv)) { /* might have had built-in attrs applied */ - if (CvLVALUE(PL_compcv) && ! CvLVALUE(cv) && ckWARN(WARN_MISC)) + const bool pureperl = !CvISXSUB(cv) && CvROOT(cv); + if (CvLVALUE(PL_compcv) && ! CvLVALUE(cv) && pureperl + && ckWARN(WARN_MISC)) Perl_warner(aTHX_ packWARN(WARN_MISC), "lvalue attribute ignored after the subroutine has been defined"); - CvFLAGS(cv) |= (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS & ~CVf_LVALUE); + CvFLAGS(cv) |= + (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS + & ~(CVf_LVALUE * pureperl)); } + if (attrs) goto attrs; /* just a "sub foo;" when &foo is already defined */ SAVEFREESV(PL_compcv); goto done; @@ -6286,12 +6607,9 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) CvOUTSIDE(PL_compcv) = temp_cv; CvPADLIST(PL_compcv) = temp_av; -#ifdef USE_ITHREADS - if (CvFILE(cv) && !CvISXSUB(cv)) { - /* for XSUBs CvFILE point directly to static memory; __FILE__ */ + if (CvFILE(cv) && CvDYNFILE(cv)) { Safefree(CvFILE(cv)); } -#endif CvFILE_set_from_cop(cv, PL_curcop); CvSTASH_set(cv, PL_curstash); @@ -6328,6 +6646,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) CvFILE_set_from_cop(cv, PL_curcop); CvSTASH_set(cv, PL_curstash); } + attrs: if (attrs) { /* Need to do a C. */ HV *stash = name && GvSTASH(CvGV(cv)) ? GvSTASH(CvGV(cv)) : PL_curstash; @@ -6366,14 +6685,8 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) exit. */ PL_breakable_sub_gen++; - if (CvLVALUE(cv)) { - CvROOT(cv) = newUNOP(OP_LEAVESUBLV, 0, - op_lvalue(scalarseq(block), OP_LEAVESUBLV)); - block->op_attached = 1; - } - else { - /* This makes sub {}; work as expected. */ - if (block->op_type == OP_STUB) { + /* This makes sub {}; work as expected. */ + if (block->op_type == OP_STUB) { OP* const newblock = newSTATEOP(0, NULL, 0); #ifdef PERL_MAD op_getmad(block,newblock,'B'); @@ -6381,16 +6694,18 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) op_free(block); #endif block = newblock; - } - else - block->op_attached = 1; - CvROOT(cv) = newUNOP(OP_LEAVESUB, 0, scalarseq(block)); } + else block->op_attached = 1; + CvROOT(cv) = CvLVALUE(cv) + ? newUNOP(OP_LEAVESUBLV, 0, + op_lvalue(scalarseq(block), OP_LEAVESUBLV)) + : newUNOP(OP_LEAVESUB, 0, scalarseq(block)); CvROOT(cv)->op_private |= OPpREFCOUNTED; OpREFCNT_set(CvROOT(cv), 1); CvSTART(cv) = LINKLIST(CvROOT(cv)); CvROOT(cv)->op_next = 0; CALL_PEEP(CvSTART(cv)); + finalize_optree(CvROOT(cv)); /* now that optimizer has done its work, adjust pad values */ @@ -6553,7 +6868,7 @@ Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv) CopSTASH_set(PL_curcop,stash); } - /* file becomes the CvFILE. For an XS, it's supposed to be static storage, + /* file becomes the CvFILE. For an XS, it's usually static storage, and so doesn't get free()d. (It's expected to be from the C pre- processor __FILE__ directive). But we need a dynamically allocated one, and we need it to get freed. */ @@ -6581,40 +6896,10 @@ Perl_newXS_flags(pTHX_ const char *name, XSUBADDR_t subaddr, PERL_ARGS_ASSERT_NEWXS_FLAGS; if (flags & XS_DYNAMIC_FILENAME) { - /* We need to "make arrangements" (ie cheat) to ensure that the - filename lasts as long as the PVCV we just created, but also doesn't - leak */ - STRLEN filename_len = strlen(filename); - STRLEN proto_and_file_len = filename_len; - char *proto_and_file; - STRLEN proto_len; - - if (proto) { - proto_len = strlen(proto); - proto_and_file_len += proto_len; - - Newx(proto_and_file, proto_and_file_len + 1, char); - Copy(proto, proto_and_file, proto_len, char); - Copy(filename, proto_and_file + proto_len, filename_len + 1, char); - } else { - proto_len = 0; - proto_and_file = savepvn(filename, filename_len); - } - - /* This gets free()d. :-) */ - sv_usepvn_flags(MUTABLE_SV(cv), proto_and_file, proto_and_file_len, - SV_HAS_TRAILING_NUL); - if (proto) { - /* This gives us the correct prototype, rather than one with the - file name appended. */ - SvCUR_set(cv, proto_len); - } else { - SvPOK_off(cv); - } - CvFILE(cv) = proto_and_file + proto_len; - } else { - sv_setpv(MUTABLE_SV(cv), proto); + CvFILE(cv) = savepv(filename); + CvDYNFILE_on(cv); } + sv_setpv(MUTABLE_SV(cv), proto); return cv; } @@ -6690,6 +6975,7 @@ Perl_newXS(pTHX_ const char *name, XSUBADDR_t subaddr, const char *filename) (void)gv_fetchfile(filename); CvFILE(cv) = (char *)filename; /* NOTE: not copied, as it is expected to be an external constant string */ + assert(!CvDYNFILE(cv)); /* cv_undef should have turned it off */ CvISXSUB_on(cv); CvXSUB(cv) = subaddr; @@ -6746,6 +7032,7 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block) CvSTART(cv) = LINKLIST(CvROOT(cv)); CvROOT(cv)->op_next = 0; CALL_PEEP(CvSTART(cv)); + finalize_optree(CvROOT(cv)); #ifdef PERL_MAD op_getmad(o,pegop,'n'); op_getmad_weak(block, pegop, 'b'); @@ -6915,7 +7202,7 @@ Perl_ck_anoncode(pTHX_ OP *o) { PERL_ARGS_ASSERT_CK_ANONCODE; - cSVOPo->op_targ = pad_add_anon(cSVOPo->op_sv, o->op_type); + cSVOPo->op_targ = pad_add_anon((CV*)cSVOPo->op_sv, o->op_type); if (!PL_madskills) cSVOPo->op_sv = NULL; return o; @@ -6928,14 +7215,6 @@ Perl_ck_bitop(pTHX_ OP *o) PERL_ARGS_ASSERT_CK_BITOP; -#define OP_IS_NUMCOMPARE(op) \ - ((op) == OP_LT || (op) == OP_I_LT || \ - (op) == OP_GT || (op) == OP_I_GT || \ - (op) == OP_LE || (op) == OP_I_LE || \ - (op) == OP_GE || (op) == OP_I_GE || \ - (op) == OP_EQ || (op) == OP_I_EQ || \ - (op) == OP_NE || (op) == OP_I_NE || \ - (op) == OP_NCMP || (op) == OP_I_NCMP) o->op_private = (U8)(PL_hints & HINT_INTEGER); if (!(o->op_flags & OPf_STACKED) /* Not an assignment */ && (o->op_type == OP_BIT_OR @@ -7334,8 +7613,10 @@ Perl_ck_ftst(pTHX_ OP *o) if ((PL_hints & HINT_FILETEST_ACCESS) && OP_IS_FILETEST_ACCESS(o->op_type)) o->op_private |= OPpFT_ACCESS; if (PL_check[kidtype] == Perl_ck_ftst - && kidtype != OP_STAT && kidtype != OP_LSTAT) + && kidtype != OP_STAT && kidtype != OP_LSTAT) { o->op_private |= OPpFT_STACKED; + kid->op_private |= OPpFT_STACKING; + } } else { #ifdef PERL_MAD @@ -7373,6 +7654,7 @@ Perl_ck_fun(pTHX_ OP *o) register OP *kid = cLISTOPo->op_first; OP *sibl; I32 numargs = 0; + bool seen_optional = FALSE; if (kid->op_type == OP_PUSHMARK || (kid->op_type == OP_NULL && kid->op_targ == OP_PUSHMARK)) @@ -7380,10 +7662,25 @@ Perl_ck_fun(pTHX_ OP *o) tokid = &kid->op_sibling; kid = kid->op_sibling; } - if (!kid && PL_opargs[type] & OA_DEFGV) - *tokid = kid = newDEFSVOP(); + if (kid && kid->op_type == OP_COREARGS) { + bool optional = FALSE; + while (oa) { + numargs++; + if (oa & OA_OPTIONAL) optional = TRUE; + oa = oa >> 4; + } + if (optional) o->op_private |= numargs; + return o; + } + + while (oa) { + if (oa & OA_OPTIONAL || (oa & 7) == OA_LIST) { + if (!kid && !seen_optional && PL_opargs[type] & OA_DEFGV) + *tokid = kid = newDEFSVOP(); + seen_optional = TRUE; + } + if (!kid) break; - while (oa && kid) { numargs++; sibl = kid->op_sibling; #ifdef PERL_MAD @@ -7434,9 +7731,15 @@ Perl_ck_fun(pTHX_ OP *o) kid->op_sibling = sibl; *tokid = kid; } - else if (kid->op_type != OP_RV2AV && kid->op_type != OP_PADAV) + else if (kid->op_type == OP_CONST + && ( !SvROK(cSVOPx_sv(kid)) + || SvTYPE(SvRV(cSVOPx_sv(kid))) != SVt_PVAV ) + ) bad_type(numargs, "array", PL_op_desc[type], kid); - op_lvalue(kid, type); + /* Defer checks to run-time if we have a scalar arg */ + if (kid->op_type == OP_RV2AV || kid->op_type == OP_PADAV) + op_lvalue(kid, type); + else scalar(kid); break; case OA_HVREF: if (kid->op_type == OP_CONST && @@ -7647,7 +7950,6 @@ Perl_ck_glob(pTHX_ OP *o) } #if !defined(PERL_EXTERNAL_GLOB) - /* XXX this can be tightened up and made more failsafe. */ if (!(gv && GvCVu(gv) && GvIMPORTED_CV(gv))) { GV *glob_gv; ENTER; @@ -7745,7 +8047,7 @@ Perl_ck_grep(pTHX_ OP *o) gwop->op_flags |= OPf_KIDS; gwop->op_other = LINKLIST(kid); kid->op_next = (OP*)gwop; - offset = Perl_pad_findmy(aTHX_ STR_WITH_LEN("$_"), 0); + offset = pad_findmy_pvs("$_", 0); if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS_isOUR(offset)) { o->op_private = gwop->op_private = 0; gwop->op_targ = pad_alloc(type, SVs_PADTMP); @@ -7773,8 +8075,11 @@ Perl_ck_index(pTHX_ OP *o) OP *kid = cLISTOPo->op_first->op_sibling; /* get past pushmark */ if (kid) kid = kid->op_sibling; /* get past "big" */ - if (kid && kid->op_type == OP_CONST) + if (kid && kid->op_type == OP_CONST) { + const bool save_taint = PL_tainted; fbm_compile(((SVOP*)kid)->op_sv, 0); + PL_tainted = save_taint; + } } return ck_fun(o); } @@ -7992,7 +8297,7 @@ Perl_ck_match(pTHX_ OP *o) PERL_ARGS_ASSERT_CK_MATCH; if (o->op_type != OP_QR && PL_compcv) { - const PADOFFSET offset = Perl_pad_findmy(aTHX_ STR_WITH_LEN("$_"), 0); + const PADOFFSET offset = pad_findmy_pvs("$_", 0); if (offset != NOT_IN_PAD && !(PAD_COMPNAME_FLAGS_isOUR(offset))) { o->op_targ = offset; o->op_private |= OPpTARGET_MY; @@ -8206,19 +8511,6 @@ Perl_ck_return(pTHX_ OP *o) if (CvLVALUE(PL_compcv)) { for (; kid; kid = kid->op_sibling) op_lvalue(kid, OP_LEAVESUBLV); - } else { - for (; kid; kid = kid->op_sibling) - if ((kid->op_type == OP_NULL) - && ((kid->op_flags & (OPf_SPECIAL|OPf_KIDS)) == (OPf_SPECIAL|OPf_KIDS))) { - /* This is a do block */ - OP *op = kUNOP->op_first; - if (op->op_type == OP_LEAVE && op->op_flags & OPf_KIDS) { - op = cUNOPx(op)->op_first; - assert(op->op_type == OP_ENTER && !(op->op_flags & OPf_SPECIAL)); - /* Force the use of the caller's context */ - op->op_flags |= OPf_SPECIAL; - } - } } return o; @@ -8238,7 +8530,7 @@ Perl_ck_select(pTHX_ OP *o) o->op_type = OP_SSELECT; o->op_ppaddr = PL_ppaddr[OP_SSELECT]; o = ck_fun(o); - return fold_constants(o); + return fold_constants(op_integerize(op_std_init(o))); } } o = ck_fun(o); @@ -8277,7 +8569,7 @@ Perl_ck_shift(pTHX_ OP *o) return newUNOP(type, 0, scalar(argop)); #endif } - return scalar(modkids(ck_push(o), type)); + return scalar(ck_fun(o)); } OP * @@ -8453,8 +8745,9 @@ Perl_ck_split(pTHX_ OP *o) Perl_croak(aTHX_ "panic: ck_split"); kid = kid->op_sibling; op_free(cLISTOPo->op_first); - cLISTOPo->op_first = kid; - if (!kid) { + if (kid) + cLISTOPo->op_first = kid; + else { cLISTOPo->op_first = kid = newSVOP(OP_CONST, 0, newSVpvs(" ")); cLISTOPo->op_last = kid; /* There was only one element previously */ } @@ -8798,7 +9091,14 @@ Perl_ck_entersub_args_proto(pTHX_ OP *entersubop, GV *namegv, SV *protosv) const char *p = proto; const char *const end = proto; contextclass = 0; - while (*--p != '[') {} + while (*--p != '[') + /* \[$] accepts any scalar lvalue */ + if (*p == '$' + && Perl_op_lvalue_flags(aTHX_ + scalar(o3), + OP_READ, /* not entersub */ + OP_LVALUE_NO_CROAK + )) goto wrapref; bad_type(arg, Perl_form(aTHX_ "one of %.*s", (int)(end - p), p), gv_ename(namegv), o3); @@ -8824,8 +9124,15 @@ Perl_ck_entersub_args_proto(pTHX_ OP *entersubop, GV *namegv, SV *protosv) o3->op_type == OP_HELEM || o3->op_type == OP_AELEM) goto wrapref; - if (!contextclass) + if (!contextclass) { + /* \$ accepts any scalar lvalue */ + if (Perl_op_lvalue_flags(aTHX_ + scalar(o3), + OP_READ, /* not entersub */ + OP_LVALUE_NO_CROAK + )) goto wrapref; bad_type(arg, "scalar", gv_ename(namegv), o3); + } break; case '@': if (o3->op_type == OP_RV2AV || @@ -8923,6 +9230,94 @@ Perl_ck_entersub_args_proto_or_list(pTHX_ OP *entersubop, return ck_entersub_args_list(entersubop); } +OP * +Perl_ck_entersub_args_core(pTHX_ OP *entersubop, GV *namegv, SV *protosv) +{ + int opnum = SvTYPE(protosv) == SVt_PVCV ? 0 : (int)SvUV(protosv); + OP *aop = cUNOPx(entersubop)->op_first; + + PERL_ARGS_ASSERT_CK_ENTERSUB_ARGS_CORE; + + if (!opnum) { + OP *cvop; + if (!aop->op_sibling) + aop = cUNOPx(aop)->op_first; + aop = aop->op_sibling; + for (cvop = aop; cvop->op_sibling; cvop = cvop->op_sibling) ; + if (PL_madskills) while (aop != cvop && aop->op_type == OP_STUB) { + aop = aop->op_sibling; + continue; + } + if (aop != cvop) + (void)too_many_arguments(entersubop, GvNAME(namegv)); + + op_free(entersubop); + switch(GvNAME(namegv)[2]) { + case 'F': return newSVOP(OP_CONST, 0, + newSVpv(CopFILE(PL_curcop),0)); + case 'L': return newSVOP( + OP_CONST, 0, + Perl_newSVpvf(aTHX_ + "%"IVdf, (IV)CopLINE(PL_curcop) + ) + ); + case 'P': return newSVOP(OP_CONST, 0, + (PL_curstash + ? newSVhek(HvNAME_HEK(PL_curstash)) + : &PL_sv_undef + ) + ); + } + assert(0); + } + else { + OP *prev, *cvop; + U32 paren; +#ifdef PERL_MAD + bool seenarg = FALSE; +#endif + if (!aop->op_sibling) + aop = cUNOPx(aop)->op_first; + + prev = aop; + aop = aop->op_sibling; + prev->op_sibling = NULL; + for (cvop = aop; + cvop->op_sibling; + prev=cvop, cvop = cvop->op_sibling) +#ifdef PERL_MAD + if (PL_madskills && cvop->op_sibling + && cvop->op_type != OP_STUB) seenarg = TRUE +#endif + ; + prev->op_sibling = NULL; + paren = OPf_SPECIAL * !(cvop->op_private & OPpENTERSUB_NOPAREN); + op_free(cvop); + if (aop == cvop) aop = NULL; + op_free(entersubop); + + switch (PL_opargs[opnum] & OA_CLASS_MASK) { + case OA_UNOP: + case OA_BASEOP_OR_UNOP: + case OA_FILESTATOP: + return aop ? newUNOP(opnum,paren,aop) : newOP(opnum,paren); + case OA_BASEOP: + if (aop) { +#ifdef PERL_MAD + if (!PL_madskills || seenarg) +#endif + (void)too_many_arguments(aop, GvNAME(namegv)); + op_free(aop); + } + return newOP(opnum,0); + default: + return convert(opnum,0,aop); + } + } + assert(0); + return entersubop; +} + /* =for apidoc Am|void|cv_get_call_checker|CV *cv|Perl_call_checker *ckfun_p|SV **ckobj_p @@ -9036,6 +9431,7 @@ Perl_ck_subr(pTHX_ OP *o) cv = rv2cv_op_cv(cvop, RV2CVOPCV_MARK_EARLY); namegv = cv ? (GV*)rv2cv_op_cv(cvop, RV2CVOPCV_RETURN_NAME_GV) : NULL; + o->op_private &= ~1; o->op_private |= OPpENTERSUB_HASTARG; o->op_private |= (PL_hints & HINT_STRICT_REFS); if (PERLDB_SUB && PL_curstash != PL_debstash) @@ -9110,21 +9506,6 @@ Perl_ck_trunc(pTHX_ OP *o) } OP * -Perl_ck_unpack(pTHX_ OP *o) -{ - OP *kid = cLISTOPo->op_first; - - PERL_ARGS_ASSERT_CK_UNPACK; - - if (kid->op_sibling) { - kid = kid->op_sibling; - if (!kid->op_sibling) - kid->op_sibling = newDEFSVOP(); - } - return ck_fun(o); -} - -OP * Perl_ck_substr(pTHX_ OP *o) { PERL_ARGS_ASSERT_CK_SUBSTR; @@ -9143,48 +9524,6 @@ Perl_ck_substr(pTHX_ OP *o) } OP * -Perl_ck_push(pTHX_ OP *o) -{ - dVAR; - OP *kid = o->op_flags & OPf_KIDS ? cLISTOPo->op_first : NULL; - OP *cursor = NULL; - OP *proxy = NULL; - - PERL_ARGS_ASSERT_CK_PUSH; - - /* If 1st kid is pushmark (e.g. push, unshift, splice), we need 2nd kid */ - if (kid) { - cursor = kid->op_type == OP_PUSHMARK ? kid->op_sibling : kid; - } - - /* If not array or array deref, wrap it with an array deref. - * For OP_CONST, we only wrap arrayrefs */ - if (cursor) { - if ( ( cursor->op_type != OP_PADAV - && cursor->op_type != OP_RV2AV - && cursor->op_type != OP_CONST - ) - || - ( cursor->op_type == OP_CONST - && SvROK(cSVOPx_sv(cursor)) - && SvTYPE(SvRV(cSVOPx_sv(cursor))) == SVt_PVAV - ) - ) { - proxy = newAVREF(cursor); - if ( cursor == kid ) { - cLISTOPx(o)->op_first = proxy; - } - else { - cLISTOPx(kid)->op_sibling = proxy; - } - cLISTOPx(proxy)->op_sibling = cLISTOPx(cursor)->op_sibling; - cLISTOPx(cursor)->op_sibling = NULL; - } - } - return ck_fun(o); -} - -OP * Perl_ck_each(pTHX_ OP *o) { dVAR; @@ -9207,11 +9546,16 @@ Perl_ck_each(pTHX_ OP *o) CHANGE_TYPE(o, array_type); break; case OP_CONST: - if (kid->op_private == OPpCONST_BARE) - /* we let ck_fun treat as hash */ + if (kid->op_private == OPpCONST_BARE + || !SvROK(cSVOPx_sv(kid)) + || ( SvTYPE(SvRV(cSVOPx_sv(kid))) != SVt_PVAV + && SvTYPE(SvRV(cSVOPx_sv(kid))) != SVt_PVHV ) + ) + /* we let ck_fun handle it */ break; default: CHANGE_TYPE(o, ref_type); + scalar(kid); } } /* if treating as a reference, defer additional checks to runtime */ @@ -9246,59 +9590,57 @@ S_opt_scalarhv(pTHX_ OP *rep_op) { return (OP*)unop; } -/* Checks if o acts as an in-place operator on an array. oright points to the - * beginning of the right-hand side. Returns the left-hand side of the - * assignment if o acts in-place, or NULL otherwise. */ +/* Check for in place reverse and sort assignments like "@a = reverse @a" + and modify the optree to make them work inplace */ -STATIC OP * -S_is_inplace_av(pTHX_ OP *o, OP *oright) { - OP *o2; - OP *oleft = NULL; +STATIC void +S_inplace_aassign(pTHX_ OP *o) { - PERL_ARGS_ASSERT_IS_INPLACE_AV; + OP *modop, *modop_pushmark; + OP *oright; + OP *oleft, *oleft_pushmark; - if (!oright || - (oright->op_type != OP_RV2AV && oright->op_type != OP_PADAV) - || oright->op_next != o - || (oright->op_private & OPpLVAL_INTRO) - ) - return NULL; + PERL_ARGS_ASSERT_INPLACE_AASSIGN; - /* o2 follows the chain of op_nexts through the LHS of the - * assign (if any) to the aassign op itself */ - o2 = o->op_next; - if (!o2 || o2->op_type != OP_NULL) - return NULL; - o2 = o2->op_next; - if (!o2 || o2->op_type != OP_PUSHMARK) - return NULL; - o2 = o2->op_next; - if (o2 && o2->op_type == OP_GV) - o2 = o2->op_next; - if (!o2 - || (o2->op_type != OP_PADAV && o2->op_type != OP_RV2AV) - || (o2->op_private & OPpLVAL_INTRO) - ) - return NULL; - oleft = o2; - o2 = o2->op_next; - if (!o2 || o2->op_type != OP_NULL) - return NULL; - o2 = o2->op_next; - if (!o2 || o2->op_type != OP_AASSIGN - || (o2->op_flags & OPf_WANT) != OPf_WANT_VOID) - return NULL; + assert((o->op_flags & OPf_WANT) == OPf_WANT_VOID); - /* check that the sort is the first arg on RHS of assign */ + assert(cUNOPo->op_first->op_type == OP_NULL); + modop_pushmark = cUNOPx(cUNOPo->op_first)->op_first; + assert(modop_pushmark->op_type == OP_PUSHMARK); + modop = modop_pushmark->op_sibling; - o2 = cUNOPx(o2)->op_first; - if (!o2 || o2->op_type != OP_NULL) - return NULL; - o2 = cUNOPx(o2)->op_first; - if (!o2 || o2->op_type != OP_PUSHMARK) - return NULL; - if (o2->op_sibling != o) - return NULL; + if (modop->op_type != OP_SORT && modop->op_type != OP_REVERSE) + return; + + /* no other operation except sort/reverse */ + if (modop->op_sibling) + return; + + assert(cUNOPx(modop)->op_first->op_type == OP_PUSHMARK); + oright = cUNOPx(modop)->op_first->op_sibling; + + if (modop->op_flags & OPf_STACKED) { + /* skip sort subroutine/block */ + assert(oright->op_type == OP_NULL); + oright = oright->op_sibling; + } + + assert(cUNOPo->op_first->op_sibling->op_type == OP_NULL); + oleft_pushmark = cUNOPx(cUNOPo->op_first->op_sibling)->op_first; + assert(oleft_pushmark->op_type == OP_PUSHMARK); + oleft = oleft_pushmark->op_sibling; + + /* Check the lhs is an array */ + if (!oleft || + (oleft->op_type != OP_RV2AV && oleft->op_type != OP_PADAV) + || oleft->op_sibling + || (oleft->op_private & OPpLVAL_INTRO) + ) + return; + + /* Only one thing on the rhs */ + if (oright->op_sibling) + return; /* check the array is the same on both sides */ if (oleft->op_type == OP_RV2AV) { @@ -9308,16 +9650,38 @@ S_is_inplace_av(pTHX_ OP *o, OP *oright) { || cGVOPx_gv(cUNOPx(oleft)->op_first) != cGVOPx_gv(cUNOPx(oright)->op_first) ) - return NULL; + return; } else if (oright->op_type != OP_PADAV || oright->op_targ != oleft->op_targ ) - return NULL; + return; - return oleft; + /* This actually is an inplace assignment */ + + modop->op_private |= OPpSORT_INPLACE; + + /* transfer MODishness etc from LHS arg to RHS arg */ + oright->op_flags = oleft->op_flags; + + /* remove the aassign op and the lhs */ + op_null(o); + op_null(oleft_pushmark); + if (oleft->op_type == OP_RV2AV && cUNOPx(oleft)->op_first) + op_null(cUNOPx(oleft)->op_first); + op_null(oleft); } +#define MAX_DEFERRED 4 + +#define DEFER(o) \ + if (defer_ix == (MAX_DEFERRED-1)) { \ + CALL_RPEEP(defer_queue[defer_base]); \ + defer_base = (defer_base + 1) % MAX_DEFERRED; \ + defer_ix--; \ + } \ + defer_queue[(defer_base + ++defer_ix) % MAX_DEFERRED] = o; + /* A peephole optimizer. We visit the ops in the order they're to execute. * See the comments at the top of this file for more details about when * peep() is called */ @@ -9327,15 +9691,24 @@ Perl_rpeep(pTHX_ register OP *o) { dVAR; register OP* oldop = NULL; + OP* defer_queue[MAX_DEFERRED]; /* small queue of deferred branches */ + int defer_base = 0; + int defer_ix = -1; if (!o || o->op_opt) return; ENTER; SAVEOP(); SAVEVPTR(PL_curcop); - for (; o; o = o->op_next) { - if (o->op_opt) + for (;; o = o->op_next) { + if (o && o->op_opt) + o = NULL; + if (!o) { + while (defer_ix >= 0) + CALL_RPEEP(defer_queue[(defer_base + defer_ix--) % MAX_DEFERRED]); break; + } + /* By default, this op has now been optimised. A couple of cases below clear this again. */ o->op_opt = 1; @@ -9398,49 +9771,6 @@ Perl_rpeep(pTHX_ register OP *o) } break; - case OP_CONST: - if (cSVOPo->op_private & OPpCONST_STRICT) - no_bareword_allowed(o); -#ifdef USE_ITHREADS - case OP_HINTSEVAL: - case OP_METHOD_NAMED: - /* Relocate sv to the pad for thread safety. - * Despite being a "constant", the SV is written to, - * for reference counts, sv_upgrade() etc. */ - if (cSVOP->op_sv) { - const PADOFFSET ix = pad_alloc(OP_CONST, SVs_PADTMP); - if (o->op_type != OP_METHOD_NAMED && SvPADTMP(cSVOPo->op_sv)) { - /* If op_sv is already a PADTMP then it is being used by - * some pad, so make a copy. */ - sv_setsv(PAD_SVl(ix),cSVOPo->op_sv); - SvREADONLY_on(PAD_SVl(ix)); - SvREFCNT_dec(cSVOPo->op_sv); - } - else 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 - PL_sv_undef as a "free" AV entry and will merrily - replace them with a new SV, causing pad_alloc to think - that this pad slot is free. (When, clearly, it is not) - */ - SvOK_off(PAD_SVl(ix)); - SvPADTMP_on(PAD_SVl(ix)); - SvREADONLY_on(PAD_SVl(ix)); - } - 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. */ - SvREADONLY_on(PAD_SVl(ix)); - } - cSVOPo->op_sv = NULL; - o->op_targ = ix; - } -#endif - break; - case OP_CONCAT: if (o->op_next && o->op_next->op_type == OP_STRINGIFY) { if (o->op_next->op_private & OPpTARGET_MY) { @@ -9496,9 +9826,7 @@ Perl_rpeep(pTHX_ register OP *o) pop->op_next->op_type == OP_AELEM && !(pop->op_next->op_private & (OPpLVAL_INTRO|OPpLVAL_DEFER|OPpDEREF|OPpMAYBE_LVSUB)) && - (i = SvIV(((SVOP*)pop)->op_sv) - CopARYBASE_get(PL_curcop)) - <= 255 && - i >= 0) + (i = SvIV(((SVOP*)pop)->op_sv)) <= 255 && i >= 0) { GV *gv; if (cSVOPx(pop)->op_private & OPpCONST_STRICT) @@ -9514,10 +9842,10 @@ Perl_rpeep(pTHX_ register OP *o) if (o->op_type == OP_GV) { gv = cGVOPo_gv; GvAVn(gv); + o->op_type = OP_AELEMFAST; } else - o->op_flags |= OPf_SPECIAL; - o->op_type = OP_AELEMFAST; + o->op_type = OP_AELEMFAST_LEX; } break; } @@ -9532,17 +9860,6 @@ Perl_rpeep(pTHX_ register OP *o) o->op_ppaddr = PL_ppaddr[OP_GVSV]; } } - else if ((o->op_private & OPpEARLY_CV) && ckWARN(WARN_PROTOTYPE)) { - GV * const gv = cGVOPo_gv; - if (SvTYPE(gv) == SVt_PVGV && GvCV(gv) && SvPVX_const(GvCV(gv))) { - /* XXX could check prototype here instead of just carping */ - SV * const sv = sv_newmortal(); - gv_efullname3(sv, gv, NULL); - Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), - "%"SVf"() called too early to check prototype", - SVfARG(sv)); - } - } else if (o->op_next->op_type == OP_READLINE && o->op_next->op_next->op_type == OP_CONCAT && (o->op_next->op_next->op_flags & OPf_STACKED)) @@ -9574,7 +9891,10 @@ Perl_rpeep(pTHX_ register OP *o) sop = fop->op_sibling; while (cLOGOP->op_other->op_type == OP_NULL) cLOGOP->op_other = cLOGOP->op_other->op_next; - CALL_RPEEP(cLOGOP->op_other); + while (o->op_next && ( o->op_type == o->op_next->op_type + || o->op_next->op_type == OP_NULL)) + o->op_next = o->op_next->op_next; + DEFER(cLOGOP->op_other); stitch_keys: o->op_opt = 1; @@ -9625,20 +9945,21 @@ Perl_rpeep(pTHX_ register OP *o) case OP_ONCE: while (cLOGOP->op_other->op_type == OP_NULL) cLOGOP->op_other = cLOGOP->op_other->op_next; - CALL_RPEEP(cLOGOP->op_other); + DEFER(cLOGOP->op_other); break; case OP_ENTERLOOP: case OP_ENTERITER: while (cLOOP->op_redoop->op_type == OP_NULL) cLOOP->op_redoop = cLOOP->op_redoop->op_next; - CALL_RPEEP(cLOOP->op_redoop); while (cLOOP->op_nextop->op_type == OP_NULL) cLOOP->op_nextop = cLOOP->op_nextop->op_next; - CALL_RPEEP(cLOOP->op_nextop); while (cLOOP->op_lastop->op_type == OP_NULL) cLOOP->op_lastop = cLOOP->op_lastop->op_next; - CALL_RPEEP(cLOOP->op_lastop); + /* a while(1) loop doesn't have an op_next that escapes the + * loop, so we have to explicitly follow the op_lastop to + * process the rest of the code */ + DEFER(cLOOP->op_lastop); break; case OP_SUBST: @@ -9647,156 +9968,18 @@ Perl_rpeep(pTHX_ register OP *o) cPMOP->op_pmstashstartu.op_pmreplstart->op_type == OP_NULL) cPMOP->op_pmstashstartu.op_pmreplstart = cPMOP->op_pmstashstartu.op_pmreplstart->op_next; - CALL_RPEEP(cPMOP->op_pmstashstartu.op_pmreplstart); - break; - - case OP_EXEC: - if (o->op_next && o->op_next->op_type == OP_NEXTSTATE - && ckWARN(WARN_SYNTAX)) - { - if (o->op_next->op_sibling) { - const OPCODE type = o->op_next->op_sibling->op_type; - if (type != OP_EXIT && type != OP_WARN && type != OP_DIE) { - const line_t oldline = CopLINE(PL_curcop); - CopLINE_set(PL_curcop, CopLINE((COP*)o->op_next)); - Perl_warner(aTHX_ packWARN(WARN_EXEC), - "Statement unlikely to be reached"); - Perl_warner(aTHX_ packWARN(WARN_EXEC), - "\t(Maybe you meant system() when you said exec()?)\n"); - CopLINE_set(PL_curcop, oldline); - } - } - } + DEFER(cPMOP->op_pmstashstartu.op_pmreplstart); break; - case OP_HELEM: { - UNOP *rop; - SV *lexname; - GV **fields; - SV **svp, *sv; - const char *key = NULL; - STRLEN keylen; - - if (((BINOP*)o)->op_last->op_type != OP_CONST) - break; - - /* Make the CONST have a shared SV */ - svp = cSVOPx_svp(((BINOP*)o)->op_last); - if ((!SvFAKE(sv = *svp) || !SvREADONLY(sv)) - && SvTYPE(sv) < SVt_PVMG && !SvROK(sv)) { - key = SvPV_const(sv, keylen); - lexname = newSVpvn_share(key, - SvUTF8(sv) ? -(I32)keylen : (I32)keylen, - 0); - SvREFCNT_dec(sv); - *svp = lexname; - } - - if ((o->op_private & (OPpLVAL_INTRO))) - break; - - rop = (UNOP*)((BINOP*)o)->op_first; - if (rop->op_type != OP_RV2HV || rop->op_first->op_type != OP_PADSV) - break; - lexname = *av_fetch(PL_comppad_name, rop->op_first->op_targ, TRUE); - if (!SvPAD_TYPED(lexname)) - break; - fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE); - if (!fields || !GvHV(*fields)) - break; - key = SvPV_const(*svp, keylen); - if (!hv_fetch(GvHV(*fields), key, - SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE)) - { - Perl_croak(aTHX_ "No such class field \"%s\" " - "in variable %s of type %s", - key, SvPV_nolen_const(lexname), HvNAME_get(SvSTASH(lexname))); - } - - break; - } - - case OP_HSLICE: { - UNOP *rop; - SV *lexname; - GV **fields; - SV **svp; - const char *key; - STRLEN keylen; - SVOP *first_key_op, *key_op; - - if ((o->op_private & (OPpLVAL_INTRO)) - /* I bet there's always a pushmark... */ - || ((LISTOP*)o)->op_first->op_sibling->op_type != OP_LIST) - /* hmmm, no optimization if list contains only one key. */ - break; - rop = (UNOP*)((LISTOP*)o)->op_last; - if (rop->op_type != OP_RV2HV) - break; - if (rop->op_first->op_type == OP_PADSV) - /* @$hash{qw(keys here)} */ - rop = (UNOP*)rop->op_first; - else { - /* @{$hash}{qw(keys here)} */ - if (rop->op_first->op_type == OP_SCOPE - && cLISTOPx(rop->op_first)->op_last->op_type == OP_PADSV) - { - rop = (UNOP*)cLISTOPx(rop->op_first)->op_last; - } - else - break; - } - - lexname = *av_fetch(PL_comppad_name, rop->op_targ, TRUE); - if (!SvPAD_TYPED(lexname)) - break; - fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE); - if (!fields || !GvHV(*fields)) - break; - /* Again guessing that the pushmark can be jumped over.... */ - first_key_op = (SVOP*)((LISTOP*)((LISTOP*)o)->op_first->op_sibling) - ->op_first->op_sibling; - for (key_op = first_key_op; key_op; - key_op = (SVOP*)key_op->op_sibling) { - if (key_op->op_type != OP_CONST) - continue; - svp = cSVOPx_svp(key_op); - key = SvPV_const(*svp, keylen); - if (!hv_fetch(GvHV(*fields), key, - SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE)) - { - Perl_croak(aTHX_ "No such class field \"%s\" " - "in variable %s of type %s", - key, SvPV_nolen(lexname), HvNAME_get(SvSTASH(lexname))); - } - } - break; - } - case OP_RV2SV: - case OP_RV2AV: - case OP_RV2HV: - if (oldop - && ( oldop->op_type == OP_AELEM - || oldop->op_type == OP_PADSV - || oldop->op_type == OP_RV2SV - || oldop->op_type == OP_RV2GV - || oldop->op_type == OP_HELEM - ) - && (oldop->op_private & OPpDEREF) - ) { - o->op_private |= OPpDEREFed; - } - case OP_SORT: { - /* will point to RV2AV or PADAV op on LHS/RHS of assign */ - OP *oleft; - OP *o2; - /* check that RHS of sort is a single plain array */ OP *oright = cUNOPo->op_first; if (!oright || oright->op_type != OP_PUSHMARK) break; + if (o->op_private & OPpSORT_INPLACE) + break; + /* reverse sort ... can be optimised. */ if (!cUNOPo->op_sibling) { /* Nothing follows us on the list. */ @@ -9816,72 +9999,16 @@ Perl_rpeep(pTHX_ register OP *o) } } - /* make @a = sort @a act in-place */ - - oright = cUNOPx(oright)->op_sibling; - if (!oright) - break; - if (oright->op_type == OP_NULL) { /* skip sort block/sub */ - oright = cUNOPx(oright)->op_sibling; - } - - oleft = is_inplace_av(o, oright); - if (!oleft) - break; - - /* transfer MODishness etc from LHS arg to RHS arg */ - oright->op_flags = oleft->op_flags; - o->op_private |= OPpSORT_INPLACE; - - /* excise push->gv->rv2av->null->aassign */ - o2 = o->op_next->op_next; - op_null(o2); /* PUSHMARK */ - o2 = o2->op_next; - if (o2->op_type == OP_GV) { - op_null(o2); /* GV */ - o2 = o2->op_next; - } - op_null(o2); /* RV2AV or PADAV */ - o2 = o2->op_next->op_next; - op_null(o2); /* AASSIGN */ - - o->op_next = o2->op_next; - break; } case OP_REVERSE: { OP *ourmark, *theirmark, *ourlast, *iter, *expushmark, *rv2av; OP *gvop = NULL; - OP *oleft, *oright; LISTOP *enter, *exlist; - /* @a = reverse @a */ - if ((oright = cLISTOPo->op_first) - && (oright->op_type == OP_PUSHMARK) - && (oright = oright->op_sibling) - && (oleft = is_inplace_av(o, oright))) { - OP *o2; - - /* transfer MODishness etc from LHS arg to RHS arg */ - oright->op_flags = oleft->op_flags; - o->op_private |= OPpREVERSE_INPLACE; - - /* excise push->gv->rv2av->null->aassign */ - o2 = o->op_next->op_next; - op_null(o2); /* PUSHMARK */ - o2 = o2->op_next; - if (o2->op_type == OP_GV) { - op_null(o2); /* GV */ - o2 = o2->op_next; - } - op_null(o2); /* RV2AV or PADAV */ - o2 = o2->op_next->op_next; - op_null(o2); /* AASSIGN */ - - o->op_next = o2->op_next; + if (o->op_private & OPpSORT_INPLACE) break; - } enter = (LISTOP *) o->op_next; if (!enter) @@ -9967,51 +10094,6 @@ Perl_rpeep(pTHX_ register OP *o) break; } - case OP_SASSIGN: { - OP *rv2gv; - UNOP *refgen, *rv2cv; - LISTOP *exlist; - - if ((o->op_flags & OPf_WANT) != OPf_WANT_VOID) - break; - - if ((o->op_private & ~OPpASSIGN_BACKWARDS) != 2) - break; - - rv2gv = ((BINOP *)o)->op_last; - if (!rv2gv || rv2gv->op_type != OP_RV2GV) - break; - - refgen = (UNOP *)((BINOP *)o)->op_first; - - if (!refgen || refgen->op_type != OP_REFGEN) - break; - - exlist = (LISTOP *)refgen->op_first; - if (!exlist || exlist->op_type != OP_NULL - || exlist->op_targ != OP_LIST) - break; - - if (exlist->op_first->op_type != OP_PUSHMARK) - break; - - rv2cv = (UNOP*)exlist->op_last; - - if (rv2cv->op_type != OP_RV2CV) - break; - - assert ((rv2gv->op_private & OPpDONT_INIT_GV) == 0); - assert ((o->op_private & OPpASSIGN_CV_TO_GV) == 0); - assert ((rv2cv->op_private & OPpMAY_RETURN_CONSTANT) == 0); - - o->op_private |= OPpASSIGN_CV_TO_GV; - rv2gv->op_private |= OPpDONT_INIT_GV; - rv2cv->op_private |= OPpMAY_RETURN_CONSTANT; - - break; - } - - case OP_QR: case OP_MATCH: if (!(cPMOP->op_pmflags & PMf_ONCE)) { @@ -10123,6 +10205,174 @@ Perl_custom_op_register(pTHX_ Perl_ppaddr_t ppaddr, const XOP *xop) Perl_croak(aTHX_ "panic: can't register custom OP %s", xop->xop_name); } +/* +=head1 Functions in file op.c + +=for apidoc core_prototype +This function assigns the prototype of the named core function to C, or +to a new mortal SV if C is NULL. It returns the modified C, or +NULL if the core function has no prototype. C is a code as returned +by C. It must be negative and unequal to -KEY_CORE. + +=cut +*/ + +SV * +Perl_core_prototype(pTHX_ SV *sv, const char *name, const int code, + int * const opnum) +{ + int i = 0, n = 0, seen_question = 0, defgv = 0; + I32 oa; +#define MAX_ARGS_OP ((sizeof(I32) - 1) * 2) + char str[ MAX_ARGS_OP * 2 + 2 ]; /* One ';', one '\0' */ + bool nullret = FALSE; + + PERL_ARGS_ASSERT_CORE_PROTOTYPE; + + assert (code < 0 && code != -KEY_CORE); + + if (!sv) sv = sv_newmortal(); + +#define retsetpvs(x,y) sv_setpvs(sv, x); if(opnum) *opnum=(y); return sv + + switch (-code) { + case KEY_and : case KEY_chop: case KEY_chomp: + case KEY_cmp : case KEY_exec: case KEY_eq : + case KEY_ge : case KEY_gt : case KEY_le : + case KEY_lt : case KEY_ne : case KEY_or : + case KEY_select: case KEY_system: case KEY_x : case KEY_xor: + if (!opnum) return NULL; nullret = TRUE; goto findopnum; + case KEY_keys: retsetpvs("+", OP_KEYS); + case KEY_values: retsetpvs("+", OP_VALUES); + case KEY_each: retsetpvs("+", OP_EACH); + case KEY_push: retsetpvs("+@", OP_PUSH); + case KEY_unshift: retsetpvs("+@", OP_UNSHIFT); + case KEY_pop: retsetpvs(";+", OP_POP); + case KEY_shift: retsetpvs(";+", OP_SHIFT); + case KEY_splice: + retsetpvs("+;$$@", OP_SPLICE); + case KEY___FILE__: case KEY___LINE__: case KEY___PACKAGE__: + retsetpvs("", 0); + case KEY_readpipe: + name = "backtick"; + } + +#undef retsetpvs + + findopnum: + while (i < MAXO) { /* The slow way. */ + if (strEQ(name, PL_op_name[i]) + || strEQ(name, PL_op_desc[i])) + { + if (nullret) { assert(opnum); *opnum = i; return NULL; } + goto found; + } + i++; + } + assert(0); return NULL; /* Should not happen... */ + found: + defgv = PL_opargs[i] & OA_DEFGV; + oa = PL_opargs[i] >> OASHIFT; + while (oa) { + if (oa & OA_OPTIONAL && !seen_question && ( + !defgv || (oa & (OA_OPTIONAL - 1)) == OA_FILEREF + )) { + seen_question = 1; + str[n++] = ';'; + } + if ((oa & (OA_OPTIONAL - 1)) >= OA_AVREF + && (oa & (OA_OPTIONAL - 1)) <= OA_SCALARREF + /* But globs are already references (kinda) */ + && (oa & (OA_OPTIONAL - 1)) != OA_FILEREF + ) { + str[n++] = '\\'; + } + if ((oa & (OA_OPTIONAL - 1)) == OA_SCALARREF + && !scalar_mod_type(NULL, i)) { + str[n++] = '['; + str[n++] = '$'; + str[n++] = '@'; + str[n++] = '%'; + if (i == OP_LOCK) str[n++] = '&'; + str[n++] = '*'; + str[n++] = ']'; + } + else str[n++] = ("?$@@%&*$")[oa & (OA_OPTIONAL - 1)]; + if (oa & OA_OPTIONAL && defgv && str[n-1] == '$') { + str[n-1] = '_'; defgv = 0; + } + oa = oa >> 4; + } + if (code == -KEY_not || code == -KEY_getprotobynumber) str[n++] = ';'; + str[n++] = '\0'; + sv_setpvn(sv, str, n - 1); + if (opnum) *opnum = i; + return sv; +} + +OP * +Perl_coresub_op(pTHX_ SV * const coreargssv, const int code, + const int opnum) +{ + OP * const argop = newSVOP(OP_COREARGS,0,coreargssv); + OP *o; + + PERL_ARGS_ASSERT_CORESUB_OP; + + switch(opnum) { + case 0: + return op_append_elem(OP_LINESEQ, + argop, + newSLICEOP(0, + newSVOP(OP_CONST, 0, newSViv(-code % 3)), + newOP(OP_CALLER,0) + ) + ); + case OP_SELECT: /* which represents OP_SSELECT as well */ + if (code) + return newCONDOP( + 0, + newBINOP(OP_GT, 0, + newAVREF(newGVOP(OP_GV, 0, PL_defgv)), + newSVOP(OP_CONST, 0, newSVuv(1)) + ), + coresub_op(newSVuv((UV)OP_SSELECT), 0, + OP_SSELECT), + coresub_op(coreargssv, 0, OP_SELECT) + ); + /* FALL THROUGH */ + default: + switch (PL_opargs[opnum] & OA_CLASS_MASK) { + case OA_BASEOP: + return op_append_elem( + OP_LINESEQ, argop, + newOP(opnum, + opnum == OP_WANTARRAY ? OPpOFFBYONE << 8 : 0) + ); + case OA_BASEOP_OR_UNOP: + o = newUNOP(opnum,0,argop); + if (opnum == OP_CALLER) o->op_private |= OPpOFFBYONE; + else { + onearg: + if (is_handle_constructor(o, 1)) + argop->op_private |= OPpCOREARGS_DEREF1; + } + return o; + default: + o = convert(opnum,0,argop); + if (is_handle_constructor(o, 2)) + argop->op_private |= OPpCOREARGS_DEREF2; + if (scalar_mod_type(NULL, opnum)) + argop->op_private |= OPpCOREARGS_SCALARMOD; + if (opnum == OP_SUBSTR) { + o->op_private |= OPpMAYBE_LVSUB; + return o; + } + else goto onearg; + } + } +} + #include "XSUB.h" /* Efficient sub that returns a constant scalar value. */