X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=op.c;h=2eefa1d1ebc6e79c63e1613dc13f1c658e85f331;hb=d7558cadd708841cd632b5ecc8f461233367b84d;hp=add8cc9be1200b05821f85b2eb89c4999446ad3b;hpb=db8ddb421f6758f0b11b38073916c1366f5b4515;p=p5sagit%2Fp5-mst-13.2.git diff --git a/op.c b/op.c index add8cc9..2eefa1d 100644 --- a/op.c +++ b/op.c @@ -1,7 +1,7 @@ /* op.c * * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - * 2000, 2001, 2002, 2003, by Larry Wall and others + * 2000, 2001, 2002, 2003, 2004, 2005, 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. @@ -16,6 +16,62 @@ * either way, as the saying is, if you follow me." --the Gaffer */ +/* This file contains the functions that create, manipulate and optimize + * the OP structures that hold a compiled perl program. + * + * A Perl program is compiled into a tree of OPs. Each op contains + * structural pointers (eg to its siblings and the next op in the + * execution sequence), a pointer to the function that would execute the + * op, plus any data specific to that op. For example, an OP_CONST op + * points to the pp_const() function and to an SV containing the constant + * value. When pp_const() is executed, its job is to push that SV onto the + * stack. + * + * OPs are mainly created by the newFOO() functions, which are mainly + * called from the parser (in perly.y) as the code is parsed. For example + * the Perl code $a + $b * $c would cause the equivalent of the following + * to be called (oversimplifying a bit): + * + * newBINOP(OP_ADD, flags, + * newSVREF($a), + * newBINOP(OP_MULTIPLY, flags, newSVREF($b), newSVREF($c)) + * ) + * + * Note that during the build of miniperl, a temporary copy of this file + * is made, called opmini.c. + */ + +/* +Perl's compiler is essentially a 3-pass compiler with interleaved phases: + + A bottom-up pass + A top-down pass + An execution-order pass + +The bottom-up pass is represented by all the "newOP" routines and +the ck_ routines. The bottom-upness is actually driven by yacc. +So at the point that a ck_ routine fires, we have no idea what the +context is, either upward in the syntax tree, or either forward or +backward in the execution order. (The bottom-up parser builds that +part of the execution order it knows about, but if you follow the "next" +links around, you'll find it's actually a closed loop through the +top level node. + +Whenever the bottom-up parser gets to a node that supplies context to +its components, it invokes that portion of the top-down pass that applies +to that part of the subtree (and marks the top node as processed, so +if a node further up supplies context, it doesn't have to take the +plunge again). As a particular subcase of this, as the new node is +built, it takes all the closed execution loops of its subcomponents +and links them into a new closed loop for the higher level node. But +it's still not the real execution order. + +The actual execution order is not known till we get a grammar reduction +to a top-level unit like a subroutine or file that will be called by +"name" rather than via a "next" pointer. At that point, we can call +into peep() to do that code's portion of the 3rd pass. It has to be +recursive, but it's recursive on basic blocks, not on tree nodes. +*/ #include "EXTERN.h" #define PERL_IN_OP_C @@ -72,8 +128,8 @@ Perl_Slab_Alloc(pTHX_ int m, size_t sz) void Perl_Slab_Free(pTHX_ void *op) { - I32 **ptr = (I32 **) op; - I32 *slab = ptr[-1]; + I32 * const * const ptr = (I32 **) op; + I32 * const slab = ptr[-1]; assert( ptr-1 > (I32 **) slab ); assert( ptr < ( (I32 **) slab + PERL_SLAB_SIZE) ); assert( *slab > 0 ); @@ -102,13 +158,12 @@ Perl_Slab_Free(pTHX_ void *op) #define RETURN_UNLIMITED_NUMBER (PERL_INT_MAX / 2) -STATIC char* +STATIC const char* S_gv_ename(pTHX_ GV *gv) { - STRLEN n_a; - SV* tmpsv = sv_newmortal(); + SV* const tmpsv = sv_newmortal(); gv_efullname3(tmpsv, gv, Nullch); - return SvPV(tmpsv,n_a); + return SvPV_nolen_const(tmpsv); } STATIC OP * @@ -120,28 +175,28 @@ S_no_fh_allowed(pTHX_ OP *o) } STATIC OP * -S_too_few_arguments(pTHX_ OP *o, char *name) +S_too_few_arguments(pTHX_ OP *o, const char *name) { yyerror(Perl_form(aTHX_ "Not enough arguments for %s", name)); return o; } STATIC OP * -S_too_many_arguments(pTHX_ OP *o, char *name) +S_too_many_arguments(pTHX_ OP *o, const char *name) { yyerror(Perl_form(aTHX_ "Too many arguments for %s", name)); return o; } STATIC void -S_bad_type(pTHX_ I32 n, char *t, char *name, OP *kid) +S_bad_type(pTHX_ I32 n, const char *t, const char *name, const OP *kid) { yyerror(Perl_form(aTHX_ "Type of arg %d to %s must be %s (not %s)", (int)n, name, t, OP_DESC(kid))); } STATIC void -S_no_bareword_allowed(pTHX_ OP *o) +S_no_bareword_allowed(pTHX_ const OP *o) { qerror(Perl_mess(aTHX_ "Bareword \"%"SVf"\" not allowed while \"strict subs\" in use", @@ -200,7 +255,8 @@ Perl_allocmy(pTHX_ char *name) off = pad_add_name(name, PL_in_my_stash, (PL_in_my == KEY_our - ? (PL_curstash ? PL_curstash : PL_defstash) + /* $_ is always in main::, even with our */ + ? (PL_curstash && !strEQ(name,"$_") ? PL_curstash : PL_defstash) : Nullhv ), 0 /* not fake */ @@ -213,10 +269,11 @@ Perl_allocmy(pTHX_ char *name) void Perl_op_free(pTHX_ OP *o) { - register OP *kid, *nextkid; + dVAR; OPCODE type; + PADOFFSET refcnt; - if (!o || o->op_seq == (U16)-1) + if (!o || o->op_static) return; if (o->op_private & OPpREFCOUNTED) { @@ -228,11 +285,10 @@ Perl_op_free(pTHX_ OP *o) case OP_SCOPE: case OP_LEAVEWRITE: OP_REFCNT_LOCK; - if (OpREFCNT_dec(o)) { - OP_REFCNT_UNLOCK; - return; - } + refcnt = OpREFCNT_dec(o); OP_REFCNT_UNLOCK; + if (refcnt) + return; break; default: break; @@ -240,6 +296,7 @@ Perl_op_free(pTHX_ OP *o) } if (o->op_flags & OPf_KIDS) { + register OP *kid, *nextkid; for (kid = cUNOPo->op_first; kid; kid = nextkid) { nextkid = kid->op_sibling; /* Get before next freeing kid */ op_free(kid); @@ -256,12 +313,17 @@ Perl_op_free(pTHX_ OP *o) op_clear(o); FreeOp(o); +#ifdef DEBUG_LEAKING_SCALARS + if (PL_op == o) + PL_op = Nullop; +#endif } void Perl_op_clear(pTHX_ OP *o) { + dVAR; switch (o->op_type) { case OP_NULL: /* Was holding old type, if any. */ case OP_ENTEREVAL: /* Was holding hints. */ @@ -275,17 +337,20 @@ 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 */ #ifdef USE_ITHREADS - if (cPADOPo->op_padix > 0) { - /* No GvIN_PAD_off(cGVOPo_gv) here, because other references - * may still exist on the pad */ - pad_swipe(cPADOPo->op_padix, TRUE); - cPADOPo->op_padix = 0; - } + if (cPADOPo->op_padix > 0) { + /* No GvIN_PAD_off(cGVOPo_gv) here, because other references + * may still exist on the pad */ + pad_swipe(cPADOPo->op_padix, TRUE); + cPADOPo->op_padix = 0; + } #else - SvREFCNT_dec(cSVOPo->op_sv); - cSVOPo->op_sv = Nullsv; + SvREFCNT_dec(cSVOPo->op_sv); + cSVOPo->op_sv = Nullsv; #endif + } break; case OP_METHOD_NAMED: case OP_CONST: @@ -294,7 +359,7 @@ Perl_op_clear(pTHX_ OP *o) #ifdef USE_ITHREADS /** Bug #15654 Even if op_clear does a pad_free for the target of the op, - pad_free doesn't actually remove the sv that exists in the bad + pad_free doesn't actually remove the sv that exists in the pad; instead it lives on. This results in that it could be reused as a target later on when the pad was reallocated. **/ @@ -339,20 +404,23 @@ Perl_op_clear(pTHX_ OP *o) case OP_QR: clear_pmop: { - HV *pmstash = PmopSTASH(cPMOPo); + HV * const pmstash = PmopSTASH(cPMOPo); if (pmstash && SvREFCNT(pmstash)) { - PMOP *pmop = HvPMROOT(pmstash); - PMOP *lastpmop = NULL; - while (pmop) { - if (cPMOPo == pmop) { - if (lastpmop) - lastpmop->op_pmnext = pmop->op_pmnext; - else - HvPMROOT(pmstash) = pmop->op_pmnext; - break; + MAGIC * const mg = mg_find((SV*)pmstash, PERL_MAGIC_symtab); + if (mg) { + PMOP *pmop = (PMOP*) mg->mg_obj; + PMOP *lastpmop = NULL; + while (pmop) { + if (cPMOPo == pmop) { + if (lastpmop) + lastpmop->op_pmnext = pmop->op_pmnext; + else + mg->mg_obj = (SV*) pmop->op_pmnext; + break; + } + lastpmop = pmop; + pmop = pmop->op_pmnext; } - lastpmop = pmop; - pmop = pmop->op_pmnext; } } PmopSTASH_free(cPMOPo); @@ -407,6 +475,7 @@ S_cop_free(pTHX_ COP* cop) void Perl_op_null(pTHX_ OP *o) { + dVAR; if (o->op_type == OP_NULL) return; op_clear(o); @@ -415,6 +484,20 @@ Perl_op_null(pTHX_ OP *o) o->op_ppaddr = PL_ppaddr[OP_NULL]; } +void +Perl_op_refcnt_lock(pTHX) +{ + dVAR; + OP_REFCNT_LOCK; +} + +void +Perl_op_refcnt_unlock(pTHX) +{ + dVAR; + OP_REFCNT_UNLOCK; +} + /* Contextualizers */ #define LINKLIST(o) ((o)->op_next ? (o)->op_next : linklist((OP*)o)) @@ -422,13 +505,13 @@ Perl_op_null(pTHX_ OP *o) OP * Perl_linklist(pTHX_ OP *o) { - register OP *kid; if (o->op_next) return o->op_next; /* establish postfix order */ if (cUNOPo->op_first) { + register OP *kid; o->op_next = LINKLIST(cUNOPo->op_first); for (kid = cUNOPo->op_first; kid; kid = kid->op_sibling) { if (kid->op_sibling) @@ -446,8 +529,8 @@ Perl_linklist(pTHX_ OP *o) OP * Perl_scalarkids(pTHX_ OP *o) { - OP *kid; if (o && o->op_flags & OPf_KIDS) { + OP *kid; for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) scalar(kid); } @@ -459,7 +542,7 @@ S_scalarboolean(pTHX_ OP *o) { if (o->op_type == OP_SASSIGN && cBINOPo->op_first->op_type == OP_CONST) { if (ckWARN(WARN_SYNTAX)) { - line_t oldline = CopLINE(PL_curcop); + const line_t oldline = CopLINE(PL_curcop); if (PL_copline != NOLINE) CopLINE_set(PL_curcop, PL_copline); @@ -473,10 +556,11 @@ S_scalarboolean(pTHX_ OP *o) OP * Perl_scalar(pTHX_ OP *o) { + dVAR; OP *kid; /* assumes no premature commitment */ - if (!o || (o->op_flags & OPf_WANT) || PL_error_count + if (!o || PL_error_count || (o->op_flags & OPf_WANT) || o->op_type == OP_RETURN) { return o; @@ -543,8 +627,9 @@ Perl_scalar(pTHX_ OP *o) OP * Perl_scalarvoid(pTHX_ OP *o) { + dVAR; OP *kid; - char* useless = 0; + const char* useless = 0; SV* sv; U8 want; @@ -658,6 +743,15 @@ Perl_scalarvoid(pTHX_ OP *o) useless = OP_DESC(o); break; + case OP_NOT: + kid = cUNOPo->op_first; + if (kid->op_type != OP_MATCH && kid->op_type != OP_SUBST && + kid->op_type != OP_TRANS) { + goto func_ops; + } + useless = "negative pattern binding (!~)"; + break; + case OP_RV2GV: case OP_RV2SV: case OP_RV2AV: @@ -674,10 +768,14 @@ Perl_scalarvoid(pTHX_ OP *o) else { if (ckWARN(WARN_VOID)) { useless = "a constant"; + /* don't warn on optimised away booleans, eg + * use constant Foo, 5; Foo || print; */ + if (cSVOPo->op_private & OPpCONST_SHORTCIRCUIT) + useless = 0; /* the constants 0 and 1 are permitted as they are conventionally used as dummies in constructs like 1 while some_condition_with_side_effects; */ - if (SvNIOK(sv) && (SvNV(sv) == 0.0 || SvNV(sv) == 1.0)) + else if (SvNIOK(sv) && (SvNV(sv) == 0.0 || SvNV(sv) == 1.0)) useless = 0; else if (SvPOK(sv)) { /* perl4's way of mixing documentation and code @@ -686,9 +784,9 @@ Perl_scalarvoid(pTHX_ OP *o) built upon these three nroff macros being used in void context. The pink camel has the details in the script wrapman near page 319. */ - if (strnEQ(SvPVX(sv), "di", 2) || - strnEQ(SvPVX(sv), "ds", 2) || - strnEQ(SvPVX(sv), "ig", 2)) + if (strnEQ(SvPVX_const(sv), "di", 2) || + strnEQ(SvPVX_const(sv), "ds", 2) || + strnEQ(SvPVX_const(sv), "ig", 2)) useless = 0; } } @@ -706,6 +804,16 @@ Perl_scalarvoid(pTHX_ OP *o) o->op_ppaddr = PL_ppaddr[OP_PREDEC]; break; + case OP_I_POSTINC: + o->op_type = OP_I_PREINC; /* pre-increment is faster */ + o->op_ppaddr = PL_ppaddr[OP_I_PREINC]; + break; + + case OP_I_POSTDEC: + o->op_type = OP_I_PREDEC; /* pre-decrement is faster */ + o->op_ppaddr = PL_ppaddr[OP_I_PREDEC]; + break; + case OP_OR: case OP_AND: case OP_DOR: @@ -758,8 +866,8 @@ Perl_scalarvoid(pTHX_ OP *o) OP * Perl_listkids(pTHX_ OP *o) { - OP *kid; if (o && o->op_flags & OPf_KIDS) { + OP *kid; for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) list(kid); } @@ -769,6 +877,7 @@ Perl_listkids(pTHX_ OP *o) OP * Perl_list(pTHX_ OP *o) { + dVAR; OP *kid; /* assumes no premature commitment */ @@ -844,14 +953,13 @@ Perl_list(pTHX_ OP *o) OP * Perl_scalarseq(pTHX_ OP *o) { - OP *kid; - if (o) { if (o->op_type == OP_LINESEQ || o->op_type == OP_SCOPE || o->op_type == OP_LEAVE || o->op_type == OP_LEAVETRY) { + OP *kid; for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) { if (kid->op_sibling) { scalarvoid(kid); @@ -871,8 +979,8 @@ Perl_scalarseq(pTHX_ OP *o) STATIC OP * S_modkids(pTHX_ OP *o, I32 type) { - OP *kid; if (o && o->op_flags & OPf_KIDS) { + OP *kid; for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) mod(kid, type); } @@ -893,6 +1001,7 @@ S_modkids(pTHX_ OP *o, I32 type) OP * Perl_mod(pTHX_ OP *o, I32 type) { + dVAR; OP *kid; /* -1 = error on localize, 0 = ignore localize, 1 = ok to localize */ int localize = -1; @@ -1108,7 +1217,7 @@ Perl_mod(pTHX_ OP *o, I32 type) break; case OP_AELEMFAST: - localize = 1; + localize = -1; PL_modcount++; break; @@ -1232,7 +1341,7 @@ Perl_mod(pTHX_ OP *o, I32 type) } STATIC bool -S_scalar_mod_type(pTHX_ OP *o, I32 type) +S_scalar_mod_type(pTHX_ const OP *o, I32 type) { switch (type) { case OP_SASSIGN: @@ -1279,12 +1388,12 @@ S_scalar_mod_type(pTHX_ OP *o, I32 type) } STATIC bool -S_is_handle_constructor(pTHX_ OP *o, I32 argnum) +S_is_handle_constructor(pTHX_ const OP *o, I32 numargs) { switch (o->op_type) { case OP_PIPE_OP: case OP_SOCKPAIR: - if (argnum == 2) + if (numargs == 2) return TRUE; /* FALL THROUGH */ case OP_SYSOPEN: @@ -1293,7 +1402,7 @@ S_is_handle_constructor(pTHX_ OP *o, I32 argnum) case OP_SOCKET: case OP_OPEN_DIR: case OP_ACCEPT: - if (argnum == 1) + if (numargs == 1) return TRUE; /* FALL THROUGH */ default: @@ -1304,8 +1413,8 @@ S_is_handle_constructor(pTHX_ OP *o, I32 argnum) OP * Perl_refkids(pTHX_ OP *o, I32 type) { - OP *kid; if (o && o->op_flags & OPf_KIDS) { + OP *kid; for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) ref(kid, type); } @@ -1313,8 +1422,9 @@ Perl_refkids(pTHX_ OP *o, I32 type) } OP * -Perl_ref(pTHX_ OP *o, I32 type) +Perl_doref(pTHX_ OP *o, I32 type, bool set_op_ref) { + dVAR; OP *kid; if (!o || PL_error_count) @@ -1334,12 +1444,12 @@ Perl_ref(pTHX_ OP *o, I32 type) case OP_COND_EXPR: for (kid = cUNOPo->op_first->op_sibling; kid; kid = kid->op_sibling) - ref(kid, type); + doref(kid, type, set_op_ref); break; case OP_RV2SV: if (type == OP_DEFINED) o->op_flags |= OPf_SPECIAL; /* don't create GV */ - ref(cUNOPo->op_first, o->op_type); + doref(cUNOPo->op_first, o->op_type, set_op_ref); /* FALL THROUGH */ case OP_PADSV: if (type == OP_RV2SV || type == OP_RV2AV || type == OP_RV2HV) { @@ -1356,28 +1466,30 @@ Perl_ref(pTHX_ OP *o, I32 type) case OP_RV2AV: case OP_RV2HV: - o->op_flags |= OPf_REF; + if (set_op_ref) + o->op_flags |= OPf_REF; /* FALL THROUGH */ case OP_RV2GV: if (type == OP_DEFINED) o->op_flags |= OPf_SPECIAL; /* don't create GV */ - ref(cUNOPo->op_first, o->op_type); + doref(cUNOPo->op_first, o->op_type, set_op_ref); break; case OP_PADAV: case OP_PADHV: - o->op_flags |= OPf_REF; + if (set_op_ref) + o->op_flags |= OPf_REF; break; case OP_SCALAR: case OP_NULL: if (!(o->op_flags & OPf_KIDS)) break; - ref(cBINOPo->op_first, type); + doref(cBINOPo->op_first, type, set_op_ref); break; case OP_AELEM: case OP_HELEM: - ref(cBINOPo->op_first, o->op_type); + doref(cBINOPo->op_first, o->op_type, set_op_ref); if (type == OP_RV2SV || type == OP_RV2AV || type == OP_RV2HV) { o->op_private |= (type == OP_RV2AV ? OPpDEREF_AV : type == OP_RV2HV ? OPpDEREF_HV @@ -1388,11 +1500,13 @@ Perl_ref(pTHX_ OP *o, I32 type) case OP_SCOPE: case OP_LEAVE: + set_op_ref = FALSE; + /* FALL THROUGH */ case OP_ENTER: case OP_LIST: if (!(o->op_flags & OPf_KIDS)) break; - ref(cLISTOPo->op_last, type); + doref(cLISTOPo->op_last, type, set_op_ref); break; default: break; @@ -1427,23 +1541,20 @@ S_dup_attrlist(pTHX_ OP *o) STATIC void S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs, bool for_my) { + dVAR; SV *stashsv; /* fake up C */ ENTER; /* need to protect against side-effects of 'use' */ SAVEINT(PL_expect); - if (stash) - stashsv = newSVpv(HvNAME(stash), 0); - else - stashsv = &PL_sv_no; + stashsv = stash ? newSVhek(HvNAME_HEK(stash)) : &PL_sv_no; #define ATTRSMODULE "attributes" #define ATTRSMODULE_PM "attributes.pm" if (for_my) { - SV **svp; /* Don't force the C if we don't need it. */ - svp = hv_fetch(GvHVn(PL_incgv), ATTRSMODULE_PM, + SV * const * const svp = hv_fetch(GvHVn(PL_incgv), ATTRSMODULE_PM, sizeof(ATTRSMODULE_PM)-1, 0); if (svp && *svp != &PL_sv_undef) ; /* already in %INC */ @@ -1486,10 +1597,8 @@ S_apply_attrs_my(pTHX_ HV *stash, OP *target, OP *attrs, OP **imopsp) pack = newSVOP(OP_CONST, 0, newSVpvn(ATTRSMODULE, sizeof(ATTRSMODULE)-1)); /* Build up the real arg-list. */ - if (stash) - stashsv = newSVpv(HvNAME(stash), 0); - else - stashsv = &PL_sv_no; + stashsv = stash ? newSVhek(HvNAME_HEK(stash)) : &PL_sv_no; + arg = newOP(OP_PADSV, 0); arg->op_targ = target->op_targ; arg = prepend_elem(OP_LIST, @@ -1500,10 +1609,7 @@ S_apply_attrs_my(pTHX_ HV *stash, OP *target, OP *attrs, OP **imopsp) dup_attrlist(attrs))); /* Fake up a method call to import */ - meth = newSVpvn("import", 6); - (void)SvUPGRADE(meth, SVt_PVIV); - (void)SvIOK_on(meth); - PERL_HASH(SvUVX(meth), SvPVX(meth), SvCUR(meth)); + meth = newSVpvn_share("import", 6, 0); imop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL|OPf_WANT_VOID, append_elem(OP_LIST, prepend_elem(OP_LIST, pack, list(arg)), @@ -1532,8 +1638,8 @@ to respect attribute syntax properly would be welcome. */ void -Perl_apply_attrs_string(pTHX_ char *stashpv, CV *cv, - char *attrstr, STRLEN len) +Perl_apply_attrs_string(pTHX_ const char *stashpv, CV *cv, + const char *attrstr, STRLEN len) { OP *attrs = Nullop; @@ -1544,7 +1650,7 @@ Perl_apply_attrs_string(pTHX_ char *stashpv, CV *cv, while (len) { for (; isSPACE(*attrstr) && len; --len, ++attrstr) ; if (len) { - char *sstr = attrstr; + const char * const sstr = attrstr; for (; !isSPACE(*attrstr) && len; --len, ++attrstr) ; attrs = append_elem(OP_LIST, attrs, newSVOP(OP_CONST, 0, @@ -1565,7 +1671,6 @@ Perl_apply_attrs_string(pTHX_ char *stashpv, CV *cv, STATIC OP * S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) { - OP *kid; I32 type; if (!o || PL_error_count) @@ -1573,6 +1678,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) type = o->op_type; if (type == OP_LIST) { + OP *kid; for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) my_kid(kid, attrs, imopsp); } else if (type == OP_UNDEF) { @@ -1584,7 +1690,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) yyerror(Perl_form(aTHX_ "Can't declare %s in %s", OP_DESC(o), PL_in_my == KEY_our ? "our" : "my")); } else if (attrs) { - GV *gv = cGVOPx_gv(cUNOPo->op_first); + GV * const gv = cGVOPx_gv(cUNOPo->op_first); PL_in_my = FALSE; PL_in_my_stash = Nullhv; apply_attrs(GvSTASH(gv), @@ -1675,15 +1781,16 @@ Perl_bind_match(pTHX_ I32 type, OP *left, OP *right) OP *o; bool ismatchop = 0; - if (ckWARN(WARN_MISC) && - (left->op_type == OP_RV2AV || + if ( (left->op_type == OP_RV2AV || left->op_type == OP_RV2HV || left->op_type == OP_PADAV || - left->op_type == OP_PADHV)) { - char *desc = PL_op_desc[(right->op_type == OP_SUBST || + left->op_type == OP_PADHV) + && ckWARN(WARN_MISC)) + { + const char * const desc = PL_op_desc[(right->op_type == OP_SUBST || right->op_type == OP_TRANS) ? right->op_type : OP_MATCH]; - const char *sample = ((left->op_type == OP_RV2AV || + const char * const sample = ((left->op_type == OP_RV2AV || left->op_type == OP_PADAV) ? "@array" : "%hash"); Perl_warner(aTHX_ packWARN(WARN_MISC), @@ -1721,7 +1828,7 @@ Perl_bind_match(pTHX_ I32 type, OP *left, OP *right) } else return bind_match(type, left, - pmruntime(newPMOP(OP_MATCH, 0), right, Nullop)); + pmruntime(newPMOP(OP_MATCH, 0), right, 0)); } OP * @@ -1736,6 +1843,7 @@ Perl_invert(pTHX_ OP *o) OP * Perl_scope(pTHX_ OP *o) { + dVAR; if (o) { if (o->op_flags & OPf_PARENS || PERLDB_NOOPT || PL_tainting) { o = prepend_elem(OP_LINESEQ, newOP(OP_ENTER, 0), o); @@ -1747,8 +1855,15 @@ Perl_scope(pTHX_ OP *o) o->op_type = OP_SCOPE; o->op_ppaddr = PL_ppaddr[OP_SCOPE]; kid = ((LISTOP*)o)->op_first; - if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) + if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) { op_null(kid); + + /* The following deals with things like 'do {1 for 1}' */ + kid = kid->op_sibling; + if (kid && + (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE)) + op_null(kid); + } } else o = newLISTOP(OP_SCOPE, 0, o, Nullop); @@ -1756,19 +1871,10 @@ Perl_scope(pTHX_ OP *o) return o; } -void -Perl_save_hints(pTHX) -{ - SAVEI32(PL_hints); - SAVESPTR(GvHV(PL_hintgv)); - GvHV(PL_hintgv) = newHVhv(GvHV(PL_hintgv)); - SAVEFREESV(GvHV(PL_hintgv)); -} - int Perl_block_start(pTHX_ int full) { - int retval = PL_savestack_ix; + const int retval = PL_savestack_ix; pad_block_start(full); SAVEHINTS(); PL_hints &= ~HINT_BLOCK_SCOPE; @@ -1788,8 +1894,8 @@ Perl_block_start(pTHX_ int full) OP* Perl_block_end(pTHX_ I32 floor, OP *seq) { - int needblockscope = PL_hints & HINT_BLOCK_SCOPE; - OP* retval = scalarseq(seq); + const int needblockscope = PL_hints & HINT_BLOCK_SCOPE; + OP* const retval = scalarseq(seq); LEAVE_SCOPE(floor); PL_compiling.op_private = (U8)(PL_hints & HINT_PRIVATE_MASK); if (needblockscope) @@ -1801,12 +1907,12 @@ Perl_block_end(pTHX_ I32 floor, OP *seq) STATIC OP * S_newDEFSVOP(pTHX) { - I32 offset = pad_findmy("$_"); + const I32 offset = pad_findmy("$_"); if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS(offset) & SVpad_OUR) { return newSVREF(newGVOP(OP_GV, 0, PL_defgv)); } else { - OP *o = newOP(OP_PADSV, 0); + OP * const o = newOP(OP_PADSV, 0); o->op_targ = offset; return o; } @@ -1845,7 +1951,7 @@ Perl_newPROG(pTHX_ OP *o) /* Register with debugger */ if (PERLDB_INTER) { - CV *cv = get_cv("DB::postponed", FALSE); + CV * const cv = get_cv("DB::postponed", FALSE); if (cv) { dSP; PUSHMARK(SP); @@ -1869,8 +1975,8 @@ Perl_localize(pTHX_ OP *o, I32 lex) ; #endif else { - if (ckWARN(WARN_PARENTHESIS) - && PL_bufptr > PL_oldbufptr && PL_bufptr[-1] == ',') + if ( PL_bufptr > PL_oldbufptr && PL_bufptr[-1] == ',' + && ckWARN(WARN_PARENTHESIS)) { char *s = PL_bufptr; bool sigil = FALSE; @@ -1923,6 +2029,7 @@ Perl_jmaybe(pTHX_ OP *o) OP * Perl_fold_constants(pTHX_ register OP *o) { + dVAR; register OP *curop; I32 type = o->op_type; SV *sv; @@ -2002,8 +2109,9 @@ Perl_fold_constants(pTHX_ register OP *o) OP * Perl_gen_constant_list(pTHX_ register OP *o) { + dVAR; register OP *curop; - I32 oldtmps_floor = PL_tmps_floor; + const I32 oldtmps_floor = PL_tmps_floor; list(o); if (PL_error_count) @@ -2022,7 +2130,7 @@ Perl_gen_constant_list(pTHX_ register OP *o) o->op_ppaddr = PL_ppaddr[OP_RV2AV]; o->op_flags &= ~OPf_REF; /* treat \(1..2) like an ordinary list */ o->op_flags |= OPf_PARENS; /* and flatten \(1..2,3) */ - o->op_seq = 0; /* needs to be revisited in peep() */ + o->op_opt = 0; /* needs to be revisited in peep() */ curop = ((UNOP*)o)->op_first; ((UNOP*)o)->op_first = newSVOP(OP_CONST, 0, SvREFCNT_inc(*PL_stack_sp--)); op_free(curop); @@ -2033,6 +2141,7 @@ Perl_gen_constant_list(pTHX_ register OP *o) OP * Perl_convert(pTHX_ I32 type, I32 flags, OP *o) { + dVAR; if (!o || o->op_type != OP_LIST) o = newLISTOP(OP_LIST, 0, o, Nullop); else @@ -2046,7 +2155,7 @@ Perl_convert(pTHX_ I32 type, I32 flags, OP *o) o->op_flags |= flags; o = CHECKOP(type, o); - if (o->op_type != type) + if (o->op_type != (unsigned)type) return o; return fold_constants(o); @@ -2063,7 +2172,7 @@ Perl_append_elem(pTHX_ I32 type, OP *first, OP *last) if (!last) return first; - if (first->op_type != type + if (first->op_type != (unsigned)type || (type == OP_LIST && (first->op_flags & OPf_PARENS))) { return newLISTOP(type, 0, first, last); @@ -2088,10 +2197,10 @@ Perl_append_list(pTHX_ I32 type, LISTOP *first, LISTOP *last) if (!last) return (OP*)first; - if (first->op_type != type) + if (first->op_type != (unsigned)type) return prepend_elem(type, (OP*)first, (OP*)last); - if (last->op_type != type) + if (last->op_type != (unsigned)type) return append_elem(type, (OP*)first, (OP*)last); first->op_last->op_sibling = last->op_first; @@ -2112,7 +2221,7 @@ Perl_prepend_elem(pTHX_ I32 type, OP *first, OP *last) if (!last) return first; - if (last->op_type == type) { + if (last->op_type == (unsigned)type) { if (type == OP_LIST) { /* already a PUSHMARK there */ first->op_sibling = ((LISTOP*)last)->op_first->op_sibling; ((LISTOP*)last)->op_first->op_sibling = first; @@ -2154,6 +2263,7 @@ Perl_force_list(pTHX_ OP *o) OP * Perl_newLISTOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) { + dVAR; LISTOP *listop; NewOp(1101, listop, 1, LISTOP); @@ -2173,8 +2283,7 @@ Perl_newLISTOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) listop->op_first = first; listop->op_last = last; if (type == OP_LIST) { - OP* pushop; - pushop = newOP(OP_PUSHMARK, 0); + OP* const pushop = newOP(OP_PUSHMARK, 0); pushop->op_sibling = first; listop->op_first = pushop; listop->op_flags |= OPf_KIDS; @@ -2188,6 +2297,7 @@ Perl_newLISTOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) OP * Perl_newOP(pTHX_ I32 type, I32 flags) { + dVAR; OP *o; NewOp(1101, o, 1, OP); o->op_type = (OPCODE)type; @@ -2206,6 +2316,7 @@ Perl_newOP(pTHX_ I32 type, I32 flags) OP * Perl_newUNOP(pTHX_ I32 type, I32 flags, OP *first) { + dVAR; UNOP *unop; if (!first) @@ -2217,7 +2328,7 @@ Perl_newUNOP(pTHX_ I32 type, I32 flags, OP *first) unop->op_type = (OPCODE)type; unop->op_ppaddr = PL_ppaddr[type]; unop->op_first = first; - unop->op_flags = flags | OPf_KIDS; + unop->op_flags = (U8)(flags | OPf_KIDS); unop->op_private = (U8)(1 | (flags >> 8)); unop = (UNOP*) CHECKOP(type, unop); if (unop->op_next) @@ -2229,6 +2340,7 @@ Perl_newUNOP(pTHX_ I32 type, I32 flags, OP *first) OP * Perl_newBINOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) { + dVAR; BINOP *binop; NewOp(1101, binop, 1, BINOP); @@ -2238,7 +2350,7 @@ Perl_newBINOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) binop->op_type = (OPCODE)type; binop->op_ppaddr = PL_ppaddr[type]; binop->op_first = first; - binop->op_flags = flags | OPf_KIDS; + binop->op_flags = (U8)(flags | OPf_KIDS); if (!last) { last = first; binop->op_private = (U8)(1 | (flags >> 8)); @@ -2257,16 +2369,16 @@ Perl_newBINOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) return fold_constants((OP *)binop); } -static int -uvcompare(const void *a, const void *b) +static int uvcompare(const void *a, const void *b) __attribute__nonnull__(1) __attribute__nonnull__(2) __attribute__pure__; +static int uvcompare(const void *a, const void *b) { - if (*((UV *)a) < (*(UV *)b)) + if (*((const UV *)a) < (*(const UV *)b)) return -1; - if (*((UV *)a) > (*(UV *)b)) + if (*((const UV *)a) > (*(const UV *)b)) return 1; - if (*((UV *)a+1) < (*(UV *)b+1)) + if (*((const UV *)a+1) < (*(const UV *)b+1)) return -1; - if (*((UV *)a+1) > (*(UV *)b+1)) + if (*((const UV *)a+1) > (*(const UV *)b+1)) return 1; return 0; } @@ -2274,24 +2386,21 @@ uvcompare(const void *a, const void *b) OP * Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) { - SV *tstr = ((SVOP*)expr)->op_sv; - SV *rstr = ((SVOP*)repl)->op_sv; + SV * const tstr = ((SVOP*)expr)->op_sv; + SV * const rstr = ((SVOP*)repl)->op_sv; STRLEN tlen; STRLEN rlen; - U8 *t = (U8*)SvPV(tstr, tlen); - U8 *r = (U8*)SvPV(rstr, rlen); + const U8 *t = (U8*)SvPV_const(tstr, tlen); + const U8 *r = (U8*)SvPV_const(rstr, rlen); register I32 i; register I32 j; - I32 del; - I32 complement; - I32 squash; I32 grows = 0; register short *tbl; + const I32 complement = o->op_private & OPpTRANS_COMPLEMENT; + const I32 squash = o->op_private & OPpTRANS_SQUASH; + I32 del = o->op_private & OPpTRANS_DELETE; PL_hints |= HINT_BLOCK_SCOPE; - complement = o->op_private & OPpTRANS_COMPLEMENT; - del = o->op_private & OPpTRANS_DELETE; - squash = o->op_private & OPpTRANS_SQUASH; if (SvUTF8(tstr)) o->op_private |= OPpTRANS_FROM_UTF; @@ -2300,10 +2409,10 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) o->op_private |= OPpTRANS_TO_UTF; if (o->op_private & (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF)) { - SV* listsv = newSVpvn("# comment\n",10); + SV* const listsv = newSVpvn("# comment\n",10); SV* transv = 0; - U8* tend = t + tlen; - U8* rend = r + rlen; + const U8* tend = t + tlen; + const U8* rend = r + rlen; STRLEN ulen; UV tfirst = 1; UV tlast = 0; @@ -2317,19 +2426,19 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) I32 bits; I32 havefinal = 0; U32 final = 0; - I32 from_utf = o->op_private & OPpTRANS_FROM_UTF; - I32 to_utf = o->op_private & OPpTRANS_TO_UTF; + const I32 from_utf = o->op_private & OPpTRANS_FROM_UTF; + const I32 to_utf = o->op_private & OPpTRANS_TO_UTF; U8* tsave = NULL; U8* rsave = NULL; if (!from_utf) { STRLEN len = tlen; - tsave = t = bytes_to_utf8(t, &len); + t = tsave = bytes_to_utf8(t, &len); tend = t + len; } if (!to_utf && rlen) { STRLEN len = rlen; - rsave = r = bytes_to_utf8(r, &len); + r = rsave = bytes_to_utf8(r, &len); rend = r + len; } @@ -2340,10 +2449,10 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) */ if (complement) { - U8 tmpbuf[UTF8_MAXLEN+1]; + U8 tmpbuf[UTF8_MAXBYTES+1]; UV *cp; UV nextmin = 0; - New(1109, cp, 2*tlen, UV); + Newx(cp, 2*tlen, UV); i = 0; transv = newSVpvn("",0); while (t < tend) { @@ -2386,7 +2495,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) t = uvuni_to_utf8_flags(tmpbuf, 0x7fffffff, UNICODE_ALLOW_SUPER); sv_catpvn(transv, (char*)tmpbuf, t - tmpbuf); - t = (U8*)SvPVX(transv); + t = (const U8*)SvPVX_const(transv); tlen = SvCUR(transv); tend = t + tlen; Safefree(cp); @@ -2538,7 +2647,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) j = rlen - 1; else cPVOPo->op_pv = (char*)Renew(tbl, 0x101+rlen-j, short); - tbl[0x100] = rlen - j; + tbl[0x100] = (short)(rlen - j); for (i=0; i < (I32)rlen - j; i++) tbl[0x101+i] = r[j+i]; } @@ -2581,6 +2690,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) OP * Perl_newPMOP(pTHX_ I32 type, I32 flags) { + dVAR; PMOP *pmop; NewOp(1101, pmop, 1, PMOP); @@ -2596,41 +2706,85 @@ Perl_newPMOP(pTHX_ I32 type, I32 flags) pmop->op_pmflags = pmop->op_pmpermflags; #ifdef USE_ITHREADS - { - SV* repointer; - if(av_len((AV*) PL_regex_pad[0]) > -1) { - repointer = av_pop((AV*)PL_regex_pad[0]); - pmop->op_pmoffset = SvIV(repointer); - SvREPADTMP_off(repointer); - sv_setiv(repointer,0); - } else { - repointer = newSViv(0); - av_push(PL_regex_padav,SvREFCNT_inc(repointer)); - pmop->op_pmoffset = av_len(PL_regex_padav); - PL_regex_pad = AvARRAY(PL_regex_padav); - } + if (av_len((AV*) PL_regex_pad[0]) > -1) { + SV * const repointer = av_pop((AV*)PL_regex_pad[0]); + pmop->op_pmoffset = SvIV(repointer); + SvREPADTMP_off(repointer); + sv_setiv(repointer,0); + } else { + SV * const repointer = newSViv(0); + av_push(PL_regex_padav,SvREFCNT_inc(repointer)); + pmop->op_pmoffset = av_len(PL_regex_padav); + PL_regex_pad = AvARRAY(PL_regex_padav); } #endif /* link into pm list */ if (type != OP_TRANS && PL_curstash) { - pmop->op_pmnext = HvPMROOT(PL_curstash); - HvPMROOT(PL_curstash) = pmop; + MAGIC *mg = mg_find((SV*)PL_curstash, PERL_MAGIC_symtab); + + if (!mg) { + mg = sv_magicext((SV*)PL_curstash, 0, PERL_MAGIC_symtab, 0, 0, 0); + } + pmop->op_pmnext = (PMOP*)mg->mg_obj; + mg->mg_obj = (SV*)pmop; PmopSTASH_set(pmop,PL_curstash); } return CHECKOP(type, pmop); } +/* Given some sort of match op o, and an expression expr containing a + * pattern, either compile expr into a regex and attach it to o (if it's + * constant), or convert expr into a runtime regcomp op sequence (if it's + * not) + * + * isreg indicates that the pattern is part of a regex construct, eg + * $x =~ /pattern/ or split /pattern/, as opposed to $x =~ $pattern or + * split "pattern", which aren't. In the former case, expr will be a list + * if the pattern contains more than one term (eg /a$b/) or if it contains + * a replacement, ie s/// or tr///. + */ + OP * -Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl) +Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg) { + dVAR; PMOP *pm; LOGOP *rcop; I32 repl_has_vars = 0; + OP* repl = Nullop; + bool reglist; + + if (o->op_type == OP_SUBST || o->op_type == OP_TRANS) { + /* last element in list is the replacement; pop it */ + OP* kid; + repl = cLISTOPx(expr)->op_last; + kid = cLISTOPx(expr)->op_first; + while (kid->op_sibling != repl) + kid = kid->op_sibling; + kid->op_sibling = Nullop; + cLISTOPx(expr)->op_last = kid; + } - if (o->op_type == OP_TRANS) + if (isreg && expr->op_type == OP_LIST && + cLISTOPx(expr)->op_first->op_sibling == cLISTOPx(expr)->op_last) + { + /* convert single element list to element */ + OP* oe = expr; + expr = cLISTOPx(oe)->op_first->op_sibling; + cLISTOPx(oe)->op_first->op_sibling = Nullop; + cLISTOPx(oe)->op_last = Nullop; + op_free(oe); + } + + if (o->op_type == OP_TRANS) { return pmtrans(o, expr, repl); + } + + reglist = isreg && expr->op_type == OP_LIST; + if (reglist) + op_null(expr); PL_hints |= HINT_BLOCK_SCOPE; pm = (PMOP*)o; @@ -2638,15 +2792,31 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl) if (expr->op_type == OP_CONST) { STRLEN plen; SV *pat = ((SVOP*)expr)->op_sv; - char *p = SvPV(pat, plen); - if ((o->op_flags & OPf_SPECIAL) && strEQ(p, " ")) { + const char *p = SvPV_const(pat, plen); + if ((o->op_flags & OPf_SPECIAL) && (*p == ' ' && p[1] == '\0')) { + U32 was_readonly = SvREADONLY(pat); + + if (was_readonly) { + if (SvFAKE(pat)) { + sv_force_normal_flags(pat, 0); + assert(!SvREADONLY(pat)); + was_readonly = 0; + } else { + SvREADONLY_off(pat); + } + } + sv_setpvn(pat, "\\s+", 3); - p = SvPV(pat, plen); + + SvFLAGS(pat) |= was_readonly; + + p = SvPV_const(pat, plen); pm->op_pmflags |= PMf_SKIPWHITE; } if (DO_UTF8(pat)) pm->op_pmdynflags |= PMdf_UTF8; - PM_SETRE(pm, CALLREGCOMP(aTHX_ p, p + plen, pm)); + /* FIXME - can we make this function take const char * args? */ + PM_SETRE(pm, CALLREGCOMP(aTHX_ (char*)p, (char*)p + plen, pm)); if (strEQ("\\s+", PM_GETRE(pm)->precomp)) pm->op_pmflags |= PMf_WHITE; op_free(expr); @@ -2661,11 +2831,14 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl) rcop->op_type = OP_REGCOMP; rcop->op_ppaddr = PL_ppaddr[OP_REGCOMP]; rcop->op_first = scalar(expr); - rcop->op_flags |= ((PL_hints & HINT_RE_EVAL) - ? (OPf_SPECIAL | OPf_KIDS) - : OPf_KIDS); + rcop->op_flags |= OPf_KIDS + | ((PL_hints & HINT_RE_EVAL) ? OPf_SPECIAL : 0) + | (reglist ? OPf_STACKED : 0); rcop->op_private = 1; rcop->op_other = o; + if (reglist) + rcop->op_targ = pad_alloc(rcop->op_type, SVs_PADTMP); + /* /$x/ may cause an eval, since $x might be qr/(?{..})/ */ PL_cv_has_eval = 1; @@ -2762,6 +2935,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl) OP * Perl_newSVOP(pTHX_ I32 type, I32 flags, SV *sv) { + dVAR; SVOP *svop; NewOp(1101, svop, 1, SVOP); svop->op_type = (OPCODE)type; @@ -2779,6 +2953,7 @@ Perl_newSVOP(pTHX_ I32 type, I32 flags, SV *sv) OP * Perl_newPADOP(pTHX_ I32 type, I32 flags, SV *sv) { + dVAR; PADOP *padop; NewOp(1101, padop, 1, PADOP); padop->op_type = (OPCODE)type; @@ -2800,6 +2975,7 @@ Perl_newPADOP(pTHX_ I32 type, I32 flags, SV *sv) OP * Perl_newGVOP(pTHX_ I32 type, I32 flags, GV *gv) { + dVAR; #ifdef USE_ITHREADS if (gv) GvIN_PAD_on(gv); @@ -2812,6 +2988,7 @@ Perl_newGVOP(pTHX_ I32 type, I32 flags, GV *gv) OP * Perl_newPVOP(pTHX_ I32 type, I32 flags, char *pv) { + dVAR; PVOP *pvop; NewOp(1101, pvop, 1, PVOP); pvop->op_type = (OPCODE)type; @@ -2829,13 +3006,13 @@ Perl_newPVOP(pTHX_ I32 type, I32 flags, char *pv) void Perl_package(pTHX_ OP *o) { - char *name; + const char *name; STRLEN len; save_hptr(&PL_curstash); save_item(PL_curstname); - name = SvPV(cSVOPo->op_sv, len); + name = SvPV_const(cSVOPo->op_sv, len); PL_curstash = gv_stashpvn(name, len, TRUE); sv_setpvn(PL_curstname, name, len); op_free(o); @@ -2857,10 +3034,10 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg) veop = Nullop; - if (version != Nullop) { - SV *vesv = ((SVOP*)version)->op_sv; + if (version) { + SV * const vesv = ((SVOP*)version)->op_sv; - if (arg == Nullop && !SvNIOKp(vesv)) { + if (!arg && !SvNIOKp(vesv)) { arg = version; } else { @@ -2874,10 +3051,7 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg) pack = newSVOP(OP_CONST, 0, newSVsv(((SVOP*)idop)->op_sv)); /* Fake up a method call to VERSION */ - meth = newSVpvn("VERSION",7); - sv_upgrade(meth, SVt_PVIV); - (void)SvIOK_on(meth); - PERL_HASH(SvUVX(meth), SvPVX(meth), SvCUR(meth)); + meth = newSVpvn_share("VERSION", 7, 0); veop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL, append_elem(OP_LIST, prepend_elem(OP_LIST, pack, list(version)), @@ -2890,6 +3064,8 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg) imop = arg; /* no import on explicit () */ else if (SvNIOKp(((SVOP*)idop)->op_sv)) { imop = Nullop; /* use 5.0; */ + if (!aver) + idop->op_private |= OPpCONST_NOVER; } else { SV *meth; @@ -2898,10 +3074,8 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg) pack = newSVOP(OP_CONST, 0, newSVsv(((SVOP*)idop)->op_sv)); /* Fake up a method call to import/unimport */ - meth = aver ? newSVpvn("import",6) : newSVpvn("unimport", 8); - (void)SvUPGRADE(meth, SVt_PVIV); - (void)SvIOK_on(meth); - PERL_HASH(SvUVX(meth), SvPVX(meth), SvCUR(meth)); + meth = aver + ? newSVpvn_share("import",6, 0) : newSVpvn_share("unimport", 8, 0); imop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL, append_elem(OP_LIST, prepend_elem(OP_LIST, pack, list(arg)), @@ -2910,7 +3084,7 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg) /* Fake up the BEGIN {}, which does its thing immediately. */ newATTRSUB(floor, - newSVOP(OP_CONST, 0, newSVpvn("BEGIN", 5)), + newSVOP(OP_CONST, 0, newSVpvn_share("BEGIN", 5, 0)), Nullop, Nullop, append_elem(OP_LINESEQ, @@ -2982,9 +3156,9 @@ Perl_load_module_nocontext(U32 flags, SV *name, SV *ver, ...) void Perl_vload_module(pTHX_ U32 flags, SV *name, SV *ver, va_list *args) { - OP *modname, *veop, *imop; + OP *veop, *imop; - modname = newSVOP(OP_CONST, 0, name); + OP * const modname = newSVOP(OP_CONST, 0, name); modname->op_private |= OPpCONST_BARE; if (ver) { veop = newSVOP(OP_CONST, 0, ver); @@ -3007,9 +3181,9 @@ Perl_vload_module(pTHX_ U32 flags, SV *name, SV *ver, va_list *args) } } { - line_t ocopline = PL_copline; - COP *ocurcop = PL_curcop; - int oexpect = PL_expect; + const line_t ocopline = PL_copline; + COP * const ocurcop = PL_curcop; + const int oexpect = PL_expect; utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(FALSE, 0), veop, modname, imop); @@ -3020,14 +3194,18 @@ Perl_vload_module(pTHX_ U32 flags, SV *name, SV *ver, va_list *args) } OP * -Perl_dofile(pTHX_ OP *term) +Perl_dofile(pTHX_ OP *term, I32 force_builtin) { OP *doop; - GV *gv; + GV *gv = Nullgv; - gv = gv_fetchpv("do", FALSE, SVt_PVCV); - if (!(gv && GvCVu(gv) && GvIMPORTED_CV(gv))) - gv = gv_fetchpv("CORE::GLOBAL::do", FALSE, SVt_PVCV); + if (!force_builtin) { + gv = gv_fetchpv("do", FALSE, SVt_PVCV); + if (!(gv && GvCVu(gv) && GvIMPORTED_CV(gv))) { + GV * const * const gvp = (GV**)hv_fetch(PL_globalstash, "do", 2, FALSE); + gv = gvp ? *gvp : Nullgv; + } + } if (gv && GvCVu(gv) && GvIMPORTED_CV(gv)) { doop = ck_subr(newUNOP(OP_ENTERSUB, OPf_STACKED, @@ -3051,7 +3229,7 @@ Perl_newSLICEOP(pTHX_ I32 flags, OP *subscript, OP *listval) } STATIC I32 -S_list_assignment(pTHX_ register OP *o) +S_is_list_assignment(pTHX_ register const OP *o) { if (!o) return TRUE; @@ -3060,8 +3238,8 @@ S_list_assignment(pTHX_ register OP *o) o = cUNOPo->op_first; if (o->op_type == OP_COND_EXPR) { - I32 t = list_assignment(cLOGOPo->op_first->op_sibling); - I32 f = list_assignment(cLOGOPo->op_first->op_sibling->op_sibling); + const I32 t = is_list_assignment(cLOGOPo->op_first->op_sibling); + const I32 f = is_list_assignment(cLOGOPo->op_first->op_sibling->op_sibling); if (t && f) return TRUE; @@ -3106,18 +3284,28 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) } } - if (list_assignment(left)) { + if (is_list_assignment(left)) { OP *curop; PL_modcount = 0; - PL_eval_start = right; /* Grandfathering $[ assignment here. Bletch.*/ + /* Grandfathering $[ assignment here. Bletch.*/ + /* Only simple assignments like C<< ($[) = 1 >> are allowed */ + PL_eval_start = (left->op_type == OP_CONST) ? right : 0; left = mod(left, OP_AASSIGN); if (PL_eval_start) PL_eval_start = 0; - else { - op_free(left); + else if (left->op_type == OP_CONST) { + /* Result of assignment is always 1 (or we'd be dead already) */ + return newSVOP(OP_CONST, 0, newSViv(1)); + } + /* optimise C to C, and likewise for hashes */ + if ((left->op_type == OP_PADAV || left->op_type == OP_PADHV) + && right->op_type == OP_STUB + && (left->op_private & OPpLVAL_INTRO)) + { op_free(right); - return Nullop; + left->op_flags &= ~(OPf_REF|OPf_SPECIAL); + return left; } curop = list(force_list(left)); o = newBINOP(OP_AASSIGN, flags, list(force_list(right)), curop); @@ -3146,7 +3334,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) GV *gv = cGVOPx_gv(curop); if (gv == PL_defgv || (int)SvCUR(gv) == PL_generation) break; - SvCUR(gv) = PL_generation; + SvCUR_set(gv, PL_generation); } else if (curop->op_type == OP_PADSV || curop->op_type == OP_PADAV || @@ -3156,8 +3344,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) if (PAD_COMPNAME_GEN(curop->op_targ) == (STRLEN)PL_generation) break; - PAD_COMPNAME_GEN(curop->op_targ) - = PL_generation; + PAD_COMPNAME_GEN_set(curop->op_targ, PL_generation); } else if (curop->op_type == OP_RV2CV) @@ -3179,7 +3366,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) #endif if (gv == PL_defgv || (int)SvCUR(gv) == PL_generation) break; - SvCUR(gv) = PL_generation; + SvCUR_set(gv, PL_generation); } } else @@ -3195,7 +3382,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) if ((tmpop = ((LISTOP*)right)->op_first) && tmpop->op_type == OP_PUSHRE) { - PMOP *pm = (PMOP*)tmpop; + PMOP * const pm = (PMOP*)tmpop; if (left->op_type == OP_RV2AV && !(left->op_private & OPpLVAL_INTRO) && !(o->op_private & OPpASSIGN_COMMON) ) @@ -3246,8 +3433,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) if (PL_eval_start) PL_eval_start = 0; else { - op_free(o); - return Nullop; + o = newSVOP(OP_CONST, 0, newSViv(PL_compiling.cop_arybase)); } } return o; @@ -3256,7 +3442,8 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) OP * Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o) { - U32 seq = intro_my(); + dVAR; + const U32 seq = intro_my(); register COP *cop; NewOp(1101, cop, 1, COP); @@ -3306,32 +3493,32 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o) CopSTASH_set(cop, PL_curstash); if (PERLDB_LINE && PL_curstash != PL_debstash) { - SV **svp = av_fetch(CopFILEAV(PL_curcop), (I32)CopLINE(cop), FALSE); - if (svp && *svp != &PL_sv_undef ) { - (void)SvIOK_on(*svp); - SvIVX(*svp) = PTR2IV(cop); + SV * const * const svp = av_fetch(CopFILEAV(PL_curcop), (I32)CopLINE(cop), FALSE); + if (svp && *svp != &PL_sv_undef ) { + (void)SvIOK_on(*svp); + SvIV_set(*svp, PTR2IV(cop)); } } - o = prepend_elem(OP_LINESEQ, (OP*)cop, o); - CHECKOP(cop->op_type, cop); - return o; + return prepend_elem(OP_LINESEQ, (OP*)cop, o); } OP * Perl_newLOGOP(pTHX_ I32 type, I32 flags, OP *first, OP *other) { + dVAR; return new_logop(type, flags, &first, &other); } STATIC OP * S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp) { + dVAR; LOGOP *logop; OP *o; OP *first = *firstp; - OP *other = *otherp; + OP * const other = *otherp; if (type == OP_XOR) /* Not short circuit, but here by precedence. */ return newBINOP(type, flags, scalar(first), scalar(other)); @@ -3355,24 +3542,47 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp) if (first->op_type == OP_CONST) { if (first->op_private & OPpCONST_STRICT) no_bareword_allowed(first); - else if (ckWARN(WARN_BAREWORD) && (first->op_private & OPpCONST_BARE)) + else if ((first->op_private & OPpCONST_BARE) && ckWARN(WARN_BAREWORD)) Perl_warner(aTHX_ packWARN(WARN_BAREWORD), "Bareword found in conditional"); - if ((type == OP_AND) == (SvTRUE(((SVOP*)first)->op_sv))) { + if ((type == OP_AND && SvTRUE(((SVOP*)first)->op_sv)) || + (type == OP_OR && !SvTRUE(((SVOP*)first)->op_sv)) || + (type == OP_DOR && !SvOK(((SVOP*)first)->op_sv))) { op_free(first); *firstp = Nullop; + if (other->op_type == OP_CONST) + other->op_private |= OPpCONST_SHORTCIRCUIT; return other; } else { + /* check for C, or C */ + const OP *o2 = other; + if ( ! (o2->op_type == OP_LIST + && (( o2 = cUNOPx(o2)->op_first)) + && o2->op_type == OP_PUSHMARK + && (( o2 = o2->op_sibling)) ) + ) + o2 = other; + if ((o2->op_type == OP_PADSV || o2->op_type == OP_PADAV + || o2->op_type == OP_PADHV) + && o2->op_private & OPpLVAL_INTRO + && ckWARN(WARN_DEPRECATED)) + { + Perl_warner(aTHX_ packWARN(WARN_DEPRECATED), + "Deprecated use of my() in false conditional"); + } + op_free(other); *otherp = Nullop; + if (first->op_type == OP_CONST) + first->op_private |= OPpCONST_SHORTCIRCUIT; return first; } } - else if (ckWARN(WARN_MISC) && (first->op_flags & OPf_KIDS) && - type != OP_DOR) /* [#24076] Don't warn for err FOO. */ + else if ((first->op_flags & OPf_KIDS) && type != OP_DOR + && ckWARN(WARN_MISC)) /* [#24076] Don't warn for err FOO. */ { - OP *k1 = ((UNOP*)first)->op_first; - OP *k2 = k1->op_sibling; + const OP * const k1 = ((UNOP*)first)->op_first; + const OP * const k2 = k1->op_sibling; OPCODE warnop = 0; switch (first->op_type) { @@ -3397,7 +3607,7 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp) break; } if (warnop) { - line_t oldline = CopLINE(PL_curcop); + const line_t oldline = CopLINE(PL_curcop); CopLINE_set(PL_curcop, PL_copline); Perl_warner(aTHX_ packWARN(WARN_MISC), "Value of %s%s can be \"0\"; test with defined()", @@ -3419,7 +3629,7 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp) logop->op_type = (OPCODE)type; logop->op_ppaddr = PL_ppaddr[type]; logop->op_first = first; - logop->op_flags = flags | OPf_KIDS; + logop->op_flags = (U8)(flags | OPf_KIDS); logop->op_other = LINKLIST(other); logop->op_private = (U8)(1 | (flags >> 8)); @@ -3439,6 +3649,7 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp) OP * Perl_newCONDOP(pTHX_ I32 flags, OP *first, OP *trueop, OP *falseop) { + dVAR; LOGOP *logop; OP *start; OP *o; @@ -3451,9 +3662,9 @@ Perl_newCONDOP(pTHX_ I32 flags, OP *first, OP *trueop, OP *falseop) scalarboolean(first); if (first->op_type == OP_CONST) { if (first->op_private & OPpCONST_BARE && - first->op_private & OPpCONST_STRICT) { - no_bareword_allowed(first); - } + first->op_private & OPpCONST_STRICT) { + no_bareword_allowed(first); + } if (SvTRUE(((SVOP*)first)->op_sv)) { op_free(first); op_free(falseop); @@ -3469,7 +3680,7 @@ Perl_newCONDOP(pTHX_ I32 flags, OP *first, OP *trueop, OP *falseop) logop->op_type = OP_COND_EXPR; logop->op_ppaddr = PL_ppaddr[OP_COND_EXPR]; logop->op_first = first; - logop->op_flags = flags | OPf_KIDS; + logop->op_flags = (U8)(flags | OPf_KIDS); logop->op_private = (U8)(1 | (flags >> 8)); logop->op_other = LINKLIST(trueop); logop->op_next = LINKLIST(falseop); @@ -3494,6 +3705,7 @@ Perl_newCONDOP(pTHX_ I32 flags, OP *first, OP *trueop, OP *falseop) OP * Perl_newRANGE(pTHX_ I32 flags, OP *left, OP *right) { + dVAR; LOGOP *range; OP *flip; OP *flop; @@ -3542,9 +3754,11 @@ Perl_newLOOPOP(pTHX_ I32 flags, I32 debuggable, OP *expr, OP *block) { OP* listop; OP* o; - int once = block && block->op_flags & OPf_SPECIAL && + const bool once = block && block->op_flags & OPf_SPECIAL && (block->op_type == OP_ENTERSUB || block->op_type == OP_NULL); + PERL_UNUSED_ARG(debuggable); + if (expr) { if (once && expr->op_type == OP_CONST && !SvTRUE(((SVOP*)expr)->op_sv)) return block; /* do {} while 0 does once */ @@ -3553,8 +3767,8 @@ Perl_newLOOPOP(pTHX_ I32 flags, I32 debuggable, OP *expr, OP *block) expr = newUNOP(OP_DEFINED, 0, newASSIGNOP(0, newDEFSVOP(), 0, expr) ); } else if (expr->op_flags & OPf_KIDS) { - OP *k1 = ((UNOP*)expr)->op_first; - OP *k2 = (k1) ? k1->op_sibling : NULL; + const OP * const k1 = ((UNOP*)expr)->op_first; + const OP * const k2 = k1 ? k1->op_sibling : NULL; switch (expr->op_type) { case OP_NULL: if (k2 && k2->op_type == OP_READLINE @@ -3574,6 +3788,10 @@ Perl_newLOOPOP(pTHX_ I32 flags, I32 debuggable, OP *expr, OP *block) } } + /* if block is null, the next append_elem() would put UNSTACK, a scalar + * op, in listop. This is wrong. [perl #27024] */ + if (!block) + block = newOP(OP_NULL, 0); listop = append_elem(OP_LINESEQ, block, newOP(OP_UNSTACK, 0)); o = new_logop(OP_AND, 0, &expr, &listop); @@ -3593,42 +3811,48 @@ Perl_newLOOPOP(pTHX_ I32 flags, I32 debuggable, OP *expr, OP *block) } OP * -Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *expr, OP *block, OP *cont) +Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 +whileline, OP *expr, OP *block, OP *cont, I32 has_my) { + dVAR; OP *redo; OP *next = 0; OP *listop; OP *o; U8 loopflags = 0; - if (expr && (expr->op_type == OP_READLINE || expr->op_type == OP_GLOB - || (expr->op_type == OP_NULL && expr->op_targ == OP_GLOB))) { - expr = newUNOP(OP_DEFINED, 0, - newASSIGNOP(0, newDEFSVOP(), 0, expr) ); - } else if (expr && (expr->op_flags & OPf_KIDS)) { - OP *k1 = ((UNOP*)expr)->op_first; - OP *k2 = (k1) ? k1->op_sibling : NULL; - switch (expr->op_type) { - case OP_NULL: - if (k2 && k2->op_type == OP_READLINE - && (k2->op_flags & OPf_STACKED) - && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR)) - expr = newUNOP(OP_DEFINED, 0, expr); - break; + PERL_UNUSED_ARG(debuggable); - case OP_SASSIGN: - 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) - expr = newUNOP(OP_DEFINED, 0, expr); - break; + if (expr) { + if (expr->op_type == OP_READLINE || expr->op_type == OP_GLOB + || (expr->op_type == OP_NULL && expr->op_targ == OP_GLOB)) { + expr = newUNOP(OP_DEFINED, 0, + newASSIGNOP(0, newDEFSVOP(), 0, expr) ); + } else if (expr->op_flags & OPf_KIDS) { + const OP * const k1 = ((UNOP*)expr)->op_first; + const OP * const k2 = (k1) ? k1->op_sibling : NULL; + switch (expr->op_type) { + case OP_NULL: + if (k2 && k2->op_type == OP_READLINE + && (k2->op_flags & OPf_STACKED) + && ((k1->op_flags & OPf_WANT) == OPf_WANT_SCALAR)) + expr = newUNOP(OP_DEFINED, 0, expr); + break; + + case OP_SASSIGN: + 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) + expr = newUNOP(OP_DEFINED, 0, expr); + break; + } } } if (!block) block = newOP(OP_NULL, 0); - else if (cont) { + else if (cont || has_my) { block = scope(block); } @@ -3636,7 +3860,7 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP * next = LINKLIST(cont); } if (expr) { - OP *unstack = newOP(OP_UNSTACK, 0); + OP * const unstack = newOP(OP_UNSTACK, 0); if (!next) next = unstack; cont = append_elem(OP_LINESEQ, cont, unstack); @@ -3686,8 +3910,9 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP * } OP * -Perl_newFOROP(pTHX_ I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *block,OP *cont) +Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP *block, OP *cont) { + dVAR; LOOP *loop; OP *wop; PADOFFSET padoff = 0; @@ -3718,7 +3943,7 @@ Perl_newFOROP(pTHX_ I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *blo Perl_croak(aTHX_ "Can't use %s for loop variable", PL_op_desc[sv->op_type]); } else { - I32 offset = pad_findmy("$_"); + const I32 offset = pad_findmy("$_"); if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS(offset) & SVpad_OUR) { sv = newGVOP(OP_GV, 0, PL_defgv); } @@ -3738,10 +3963,10 @@ Perl_newFOROP(pTHX_ I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *blo * set the STACKED flag to indicate that these values are to be * treated as min/max values by 'pp_iterinit'. */ - UNOP* flip = (UNOP*)((UNOP*)((BINOP*)expr)->op_first)->op_first; - LOGOP* range = (LOGOP*) flip->op_first; - OP* left = range->op_first; - OP* right = left->op_sibling; + UNOP* const flip = (UNOP*)((UNOP*)((BINOP*)expr)->op_first)->op_first; + LOGOP* const range = (LOGOP*) flip->op_first; + OP* const left = range->op_first; + OP* const right = left->op_sibling; LISTOP* listop; range->op_flags &= ~OPf_KIDS; @@ -3762,7 +3987,6 @@ Perl_newFOROP(pTHX_ I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *blo expr = mod(force_list(expr), OP_GREPSTART); } - loop = (LOOP*)list(convert(OP_ENTERITER, iterflags, append_elem(OP_LIST, expr, scalar(sv)))); assert(!loop->op_next); @@ -3773,7 +3997,7 @@ Perl_newFOROP(pTHX_ I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *blo { LOOP *tmp; NewOp(1234,tmp,1,LOOP); - Copy(loop,tmp,1,LOOP); + Copy(loop,tmp,1,LISTOP); FreeOp(loop); loop = tmp; } @@ -3781,7 +4005,7 @@ Perl_newFOROP(pTHX_ I32 flags,char *label,line_t forline,OP *sv,OP *expr,OP *blo Renew(loop, 1, LOOP); #endif loop->op_targ = padoff; - wop = newWHILEOP(flags, 1, loop, forline, newOP(OP_ITER, 0), block, cont); + wop = newWHILEOP(flags, 1, loop, forline, newOP(OP_ITER, 0), block, cont, 0); PL_copline = forline; return newSTATEOP(0, label, wop); } @@ -3790,7 +4014,6 @@ OP* Perl_newLOOPEX(pTHX_ I32 type, OP *label) { OP *o; - STRLEN n_a; if (type != OP_GOTO || label->op_type == OP_CONST) { /* "last()" means "last" */ @@ -3798,7 +4021,7 @@ Perl_newLOOPEX(pTHX_ I32 type, OP *label) o = newOP(type, OPf_SPECIAL); else { o = newPVOP(type, 0, savepv(label->op_type == OP_CONST - ? SvPVx(((SVOP*)label)->op_sv, n_a) + ? SvPVx_nolen_const(((SVOP*)label)->op_sv) : "")); } op_free(label); @@ -3828,6 +4051,7 @@ children can still follow the full lexical scope chain. void Perl_cv_undef(pTHX_ CV *cv) { + dVAR; #ifdef USE_ITHREADS if (CvFILE(cv) && !CvXSUB(cv)) { /* for XSUBs CvFILE point directly to static memory; __FILE__ */ @@ -3845,6 +4069,7 @@ Perl_cv_undef(pTHX_ CV *cv) op_free(CvROOT(cv)); CvROOT(cv) = Nullop; + CvSTART(cv) = Nullop; LEAVE; } SvPOK_off((SV*)cv); /* forget prototype */ @@ -3870,10 +4095,10 @@ Perl_cv_undef(pTHX_ CV *cv) } void -Perl_cv_ckproto(pTHX_ CV *cv, GV *gv, char *p) +Perl_cv_ckproto(pTHX_ const CV *cv, const GV *gv, const char *p) { - if (((!p != !SvPOK(cv)) || (p && strNE(p, SvPVX(cv)))) && ckWARN_d(WARN_PROTOTYPE)) { - SV* msg = sv_newmortal(); + if (((!p != !SvPOK(cv)) || (p && strNE(p, SvPVX_const(cv)))) && ckWARN_d(WARN_PROTOTYPE)) { + SV* const msg = sv_newmortal(); SV* name = Nullsv; if (gv) @@ -3882,7 +4107,9 @@ Perl_cv_ckproto(pTHX_ CV *cv, GV *gv, char *p) if (name) Perl_sv_catpvf(aTHX_ msg, " sub %"SVf, name); if (SvPOK(cv)) - Perl_sv_catpvf(aTHX_ msg, " (%"SVf")", (SV *)cv); + Perl_sv_catpvf(aTHX_ msg, " (%"SVf")", (const SV *)cv); + else + Perl_sv_catpv(aTHX_ msg, ": none"); sv_catpv(msg, " vs "); if (p) Perl_sv_catpvf(aTHX_ msg, "(%s)", p); @@ -3937,7 +4164,7 @@ Perl_cv_const_sv(pTHX_ CV *cv) */ SV * -Perl_op_const_sv(pTHX_ OP *o, CV *cv) +Perl_op_const_sv(pTHX_ const OP *o, CV *cv) { SV *sv = Nullsv; @@ -3948,7 +4175,7 @@ Perl_op_const_sv(pTHX_ OP *o, CV *cv) o = cLISTOPo->op_first->op_sibling; for (; o; o = o->op_next) { - OPCODE type = o->op_type; + const OPCODE type = o->op_type; if (sv && o->op_next == o) return sv; @@ -3995,6 +4222,8 @@ Perl_op_const_sv(pTHX_ OP *o, CV *cv) void Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) { + PERL_UNUSED_ARG(floor); + if (o) SAVEFREEOP(o); if (proto) @@ -4015,28 +4244,40 @@ Perl_newSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *block) CV * Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) { - STRLEN n_a; - char *name; - char *aname; + dVAR; + const char *aname; GV *gv; - char *ps = proto ? SvPVx(((SVOP*)proto)->op_sv, n_a) : Nullch; + const char *ps; + STRLEN ps_len; register CV *cv=0; SV *const_sv; + I32 gv_fetch_flags; + + const char * const name = o ? SvPVx_nolen_const(cSVOPo->op_sv) : Nullch; + + if (proto) { + assert(proto->op_type == OP_CONST); + ps = SvPVx_const(((SVOP*)proto)->op_sv, ps_len); + } + else + ps = Nullch; - name = o ? SvPVx(cSVOPo->op_sv, n_a) : Nullch; if (!name && PERLDB_NAMEANON && CopLINE(PL_curcop)) { - SV *sv = sv_newmortal(); + SV * const sv = sv_newmortal(); Perl_sv_setpvf(aTHX_ sv, "%s[%s:%"IVdf"]", PL_curstash ? "__ANON__" : "__ANON__::__ANON__", CopFILE(PL_curcop), (IV)CopLINE(PL_curcop)); - aname = SvPVX(sv); + aname = SvPVX_const(sv); } else aname = Nullch; - gv = gv_fetchpv(name ? name : (aname ? aname : - (PL_curstash ? "__ANON__" : "__ANON__::__ANON__")), - GV_ADDMULTI | ((block || attrs) ? 0 : GV_NOINIT), - SVt_PVCV); + + gv_fetch_flags = (block || attrs || (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS)) + ? GV_ADDMULTI : GV_ADDMULTI | GV_NOINIT; + gv = name ? gv_fetchsv(cSVOPo->op_sv, gv_fetch_flags, SVt_PVCV) + : gv_fetchpv(aname ? aname + : (PL_curstash ? "__ANON__" : "__ANON__::__ANON__"), + gv_fetch_flags, SVt_PVCV); if (o) SAVEFREEOP(o); @@ -4056,7 +4297,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) cv_ckproto((CV*)gv, NULL, ps); } if (ps) - sv_setpv((SV*)gv, ps); + sv_setpvn((SV*)gv, ps, ps_len); else sv_setiv((SV*)gv, -1); SvREFCNT_dec(PL_compcv); @@ -4073,13 +4314,13 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) } #endif - if (!block || !ps || *ps || attrs) + if (!block || !ps || *ps || attrs || (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS)) const_sv = Nullsv; else const_sv = op_const_sv(block, Nullcv); if (cv) { - bool exists = CvROOT(cv) || CvXSUB(cv); + const bool exists = CvROOT(cv) || CvXSUB(cv); #ifdef GV_UNIQUE_CHECK if (exists && GvUNIQUE(gv)) { @@ -4104,15 +4345,12 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) SAVEFREESV(PL_compcv); goto done; } - /* ahem, death to those who redefine active sort subs */ - if (PL_curstackinfo->si_type == PERLSI_SORT && PL_sortcop == CvSTART(cv)) - Perl_croak(aTHX_ "Can't redefine active sort subroutine %s", name); if (block) { if (ckWARN(WARN_REDEFINE) || (CvCONST(cv) && (!const_sv || sv_cmp(cv_const_sv(cv), const_sv)))) { - line_t oldline = CopLINE(PL_curcop); + const line_t oldline = CopLINE(PL_curcop); if (PL_copline != NOLINE) CopLINE_set(PL_curcop, PL_copline); Perl_warner(aTHX_ packWARN(WARN_REDEFINE), @@ -4126,10 +4364,10 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) } } if (const_sv) { - SvREFCNT_inc(const_sv); + (void)SvREFCNT_inc(const_sv); if (cv) { assert(!CvROOT(cv) && !CvCONST(cv)); - sv_setpv((SV*)cv, ""); /* prototype is "" */ + sv_setpvn((SV*)cv, "", 0); /* prototype is "" */ CvXSUBANY(cv).any_ptr = const_sv; CvXSUB(cv) = const_sv_xsub; CvCONST_on(cv); @@ -4209,16 +4447,16 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) CvSTASH(cv) = PL_curstash; if (ps) - sv_setpv((SV*)cv, ps); + sv_setpvn((SV*)cv, ps, ps_len); if (PL_error_count) { op_free(block); block = Nullop; if (name) { - char *s = strrchr(name, ':'); + const char *s = strrchr(name, ':'); s = s ? s+1 : name; if (strEQ(s, "BEGIN")) { - char *not_safe = + const char not_safe[] = "BEGIN not safe after errors--compilation aborted"; if (PL_in_eval & EVAL_KEEPERR) Perl_croak(aTHX_ not_safe); @@ -4262,30 +4500,30 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) } if (name || aname) { - char *s; - char *tname = (name ? name : aname); + const char *s; + const char *tname = (name ? name : aname); if (PERLDB_SUBLINE && PL_curstash != PL_debstash) { - SV *sv = NEWSV(0,0); - SV *tmpstr = sv_newmortal(); - GV *db_postponed = gv_fetchpv("DB::postponed", GV_ADDMULTI, SVt_PVHV); - CV *pcv; + SV * const sv = NEWSV(0,0); + SV * const tmpstr = sv_newmortal(); + GV * const db_postponed = gv_fetchpv("DB::postponed", GV_ADDMULTI, SVt_PVHV); HV *hv; Perl_sv_setpvf(aTHX_ sv, "%s:%ld-%ld", CopFILE(PL_curcop), (long)PL_subline, (long)CopLINE(PL_curcop)); gv_efullname3(tmpstr, gv, Nullch); - hv_store(GvHV(PL_DBsub), SvPVX(tmpstr), SvCUR(tmpstr), sv, 0); + hv_store(GvHV(PL_DBsub), SvPVX_const(tmpstr), SvCUR(tmpstr), sv, 0); hv = GvHVn(db_postponed); - if (HvFILL(hv) > 0 && hv_exists(hv, SvPVX(tmpstr), SvCUR(tmpstr)) - && (pcv = GvCV(db_postponed))) - { - dSP; - PUSHMARK(SP); - XPUSHs(tmpstr); - PUTBACK; - call_sv((SV*)pcv, G_DISCARD); + if (HvFILL(hv) > 0 && hv_exists(hv, SvPVX_const(tmpstr), SvCUR(tmpstr))) { + CV * const pcv = GvCV(db_postponed); + if (pcv) { + dSP; + PUSHMARK(SP); + XPUSHs(tmpstr); + PUTBACK; + call_sv((SV*)pcv, G_DISCARD); + } } } @@ -4298,7 +4536,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) goto done; if (strEQ(s, "BEGIN") && !PL_error_count) { - I32 oldscope = PL_scopestack_ix; + const I32 oldscope = PL_scopestack_ix; ENTER; SAVECOPFILE(&PL_compiling); SAVECOPLINE(&PL_compiling); @@ -4360,8 +4598,9 @@ eligible for inlining at compile-time. */ CV * -Perl_newCONSTSUB(pTHX_ HV *stash, char *name, SV *sv) +Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv) { + dVAR; CV* cv; ENTER; @@ -4382,7 +4621,7 @@ Perl_newCONSTSUB(pTHX_ HV *stash, char *name, SV *sv) cv = newXS(name, const_sv_xsub, savepv(CopFILE(PL_curcop))); CvXSUBANY(cv).any_ptr = sv; CvCONST_on(cv); - sv_setpv((SV*)cv, ""); /* prototype is "" */ + sv_setpvn((SV*)cv, "", 0); /* prototype is "" */ if (stash) CopSTASH_free(PL_curcop); @@ -4401,9 +4640,9 @@ Used by C to hook up XSUBs as Perl subs. */ CV * -Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename) +Perl_newXS(pTHX_ const char *name, XSUBADDR_t subaddr, const char *filename) { - GV *gv = gv_fetchpv(name ? name : + GV * const gv = gv_fetchpv(name ? name : (PL_curstash ? "__ANON__" : "__ANON__::__ANON__"), GV_ADDMULTI, SVt_PVCV); register CV *cv; @@ -4415,23 +4654,32 @@ Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename) if (GvCVGEN(gv)) { /* just a cached method */ SvREFCNT_dec(cv); - cv = 0; + cv = Nullcv; } else if (CvROOT(cv) || CvXSUB(cv) || GvASSUMECV(gv)) { /* already defined (or promised) */ - if (ckWARN(WARN_REDEFINE) && !(CvGV(cv) && GvSTASH(CvGV(cv)) - && strEQ(HvNAME(GvSTASH(CvGV(cv))), "autouse"))) { - line_t oldline = CopLINE(PL_curcop); - if (PL_copline != NOLINE) - CopLINE_set(PL_curcop, PL_copline); - Perl_warner(aTHX_ packWARN(WARN_REDEFINE), - CvCONST(cv) ? "Constant subroutine %s redefined" - : "Subroutine %s redefined" - ,name); - CopLINE_set(PL_curcop, oldline); + /* XXX It's possible for this HvNAME_get to return null, and get passed into strEQ */ + if (ckWARN(WARN_REDEFINE)) { + GV * const gvcv = CvGV(cv); + if (gvcv) { + HV * const stash = GvSTASH(gvcv); + if (stash) { + const char *name = HvNAME_get(stash); + if ( strEQ(name,"autouse") ) { + const line_t oldline = CopLINE(PL_curcop); + if (PL_copline != NOLINE) + CopLINE_set(PL_curcop, PL_copline); + Perl_warner(aTHX_ packWARN(WARN_REDEFINE), + CvCONST(cv) ? "Constant subroutine %s redefined" + : "Subroutine %s redefined" + ,name); + CopLINE_set(PL_curcop, oldline); + } + } + } } SvREFCNT_dec(cv); - cv = 0; + cv = Nullcv; } } @@ -4448,12 +4696,12 @@ Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename) } CvGV(cv) = gv; (void)gv_fetchfile(filename); - CvFILE(cv) = filename; /* NOTE: not copied, as it is expected to be + CvFILE(cv) = (char *)filename; /* NOTE: not copied, as it is expected to be an external constant string */ CvXSUB(cv) = subaddr; if (name) { - char *s = strrchr(name,':'); + const char *s = strrchr(name,':'); if (s) s++; else @@ -4504,15 +4752,13 @@ void Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block) { register CV *cv; - char *name; GV *gv; - STRLEN n_a; if (o) - name = SvPVx(cSVOPo->op_sv, n_a); + gv = gv_fetchsv(cSVOPo->op_sv, TRUE, SVt_PVFM); else - name = "STDOUT"; - gv = gv_fetchpv(name,TRUE, SVt_PVFM); + gv = gv_fetchpv("STDOUT", TRUE, SVt_PVFM); + #ifdef GV_UNIQUE_CHECK if (GvUNIQUE(gv)) { Perl_croak(aTHX_ "Bad symbol for form (GV is unique)"); @@ -4521,10 +4767,12 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block) GvMULTI_on(gv); if ((cv = GvFORM(gv))) { if (ckWARN(WARN_REDEFINE)) { - line_t oldline = CopLINE(PL_curcop); + const line_t oldline = CopLINE(PL_curcop); if (PL_copline != NOLINE) CopLINE_set(PL_curcop, PL_copline); - Perl_warner(aTHX_ packWARN(WARN_REDEFINE), "Format %s redefined",name); + Perl_warner(aTHX_ packWARN(WARN_REDEFINE), + o ? "Format %"SVf" redefined" + : "Format STDOUT redefined" ,cSVOPo->op_sv); CopLINE_set(PL_curcop, oldline); } SvREFCNT_dec(cv); @@ -4578,6 +4826,7 @@ Perl_newANONATTRSUB(pTHX_ I32 floor, OP *proto, OP *attrs, OP *block) OP * Perl_oopsAV(pTHX_ OP *o) { + dVAR; switch (o->op_type) { case OP_PADSV: o->op_type = OP_PADAV; @@ -4601,6 +4850,7 @@ Perl_oopsAV(pTHX_ OP *o) OP * Perl_oopsHV(pTHX_ OP *o) { + dVAR; switch (o->op_type) { case OP_PADSV: case OP_PADAV: @@ -4626,6 +4876,7 @@ Perl_oopsHV(pTHX_ OP *o) OP * Perl_newAVREF(pTHX_ OP *o) { + dVAR; if (o->op_type == OP_PADANY) { o->op_type = OP_PADAV; o->op_ppaddr = PL_ppaddr[OP_PADAV]; @@ -4650,6 +4901,7 @@ Perl_newGVREF(pTHX_ I32 type, OP *o) OP * Perl_newHVREF(pTHX_ OP *o) { + dVAR; if (o->op_type == OP_PADANY) { o->op_type = OP_PADHV; o->op_ppaddr = PL_ppaddr[OP_PADHV]; @@ -4664,14 +4916,6 @@ Perl_newHVREF(pTHX_ OP *o) } OP * -Perl_oopsCV(pTHX_ OP *o) -{ - Perl_croak(aTHX_ "NOT IMPL LINE %d",__LINE__); - /* STUB */ - return o; -} - -OP * Perl_newCVREF(pTHX_ I32 flags, OP *o) { return newUNOP(OP_RV2CV, flags, scalar(o)); @@ -4680,6 +4924,7 @@ Perl_newCVREF(pTHX_ I32 flags, OP *o) OP * Perl_newSVREF(pTHX_ OP *o) { + dVAR; if (o->op_type == OP_PADANY) { o->op_type = OP_PADSV; o->op_ppaddr = PL_ppaddr[OP_PADSV]; @@ -4692,7 +4937,8 @@ Perl_newSVREF(pTHX_ OP *o) return newUNOP(OP_RV2SV, 0, scalar(o)); } -/* Check routines. */ +/* Check routines. See the comments at the top of this file for details + * on when these are called */ OP * Perl_ck_anoncode(pTHX_ OP *o) @@ -4719,8 +4965,8 @@ Perl_ck_bitop(pTHX_ OP *o) || o->op_type == OP_BIT_AND || o->op_type == OP_BIT_XOR)) { - OP * left = cBINOPo->op_first; - OP * right = left->op_sibling; + const OP * const left = cBINOPo->op_first; + const OP * const right = left->op_sibling; if ((OP_IS_NUMCOMPARE(left->op_type) && (left->op_flags & OPf_PARENS) == 0) || (OP_IS_NUMCOMPARE(right->op_type) && @@ -4738,7 +4984,7 @@ Perl_ck_bitop(pTHX_ OP *o) OP * Perl_ck_concat(pTHX_ OP *o) { - OP *kid = cUNOPo->op_first; + const OP *kid = cUNOPo->op_first; if (kid->op_type == OP_CONCAT && !(kid->op_private & OPpTARGET_MY) && !(kUNOP->op_first->op_flags & OPf_MOD)) o->op_flags |= OPf_STACKED; @@ -4748,10 +4994,11 @@ Perl_ck_concat(pTHX_ OP *o) OP * Perl_ck_spair(pTHX_ OP *o) { + dVAR; if (o->op_flags & OPf_KIDS) { OP* newop; OP* kid; - OPCODE type = o->op_type; + const OPCODE type = o->op_type; o = modkids(ck_fun(o), type); kid = cUNOPo->op_first; newop = kUNOP->op_first->op_sibling; @@ -4776,7 +5023,7 @@ Perl_ck_delete(pTHX_ OP *o) o = ck_fun(o); o->op_private = 0; if (o->op_flags & OPf_KIDS) { - OP *kid = cUNOPo->op_first; + OP * const kid = cUNOPo->op_first; switch (kid->op_type) { case OP_ASLICE: o->op_flags |= OPf_SPECIAL; @@ -4810,7 +5057,7 @@ Perl_ck_die(pTHX_ OP *o) OP * Perl_ck_eof(pTHX_ OP *o) { - I32 type = o->op_type; + const I32 type = o->op_type; if (o->op_flags & OPf_KIDS) { if (cLISTOPo->op_first->op_type == OP_STUB) { @@ -4825,9 +5072,10 @@ Perl_ck_eof(pTHX_ OP *o) OP * Perl_ck_eval(pTHX_ OP *o) { + dVAR; PL_hints |= HINT_BLOCK_SCOPE; if (o->op_flags & OPf_KIDS) { - SVOP *kid = (SVOP*)cUNOPo->op_first; + SVOP * const kid = (SVOP*)cUNOPo->op_first; if (!kid) { o->op_flags &= ~OPf_KIDS; @@ -4870,9 +5118,9 @@ OP * Perl_ck_exit(pTHX_ OP *o) { #ifdef VMS - HV *table = GvHV(PL_hintgv); + HV * const table = GvHV(PL_hintgv); if (table) { - SV **svp = hv_fetch(table, "vmsish_exit", 11, FALSE); + SV * const * const svp = hv_fetch(table, "vmsish_exit", 11, FALSE); if (svp && *svp && SvTRUE(*svp)) o->op_private |= OPpEXIT_VMSISH; } @@ -4884,8 +5132,8 @@ Perl_ck_exit(pTHX_ OP *o) OP * Perl_ck_exec(pTHX_ OP *o) { - OP *kid; if (o->op_flags & OPf_STACKED) { + OP *kid; o = ck_fun(o); kid = cUNOPo->op_first->op_sibling; if (kid->op_type == OP_RV2GV) @@ -4901,7 +5149,7 @@ Perl_ck_exists(pTHX_ OP *o) { o = ck_fun(o); if (o->op_flags & OPf_KIDS) { - OP *kid = cUNOPo->op_first; + OP * const kid = cUNOPo->op_first; if (kid->op_type == OP_ENTERSUB) { (void) ref(kid, o->op_type); if (kid->op_type != OP_RV2CV && !PL_error_count) @@ -4919,35 +5167,23 @@ Perl_ck_exists(pTHX_ OP *o) return o; } -#if 0 -OP * -Perl_ck_gvconst(pTHX_ register OP *o) -{ - o = fold_constants(o); - if (o->op_type == OP_CONST) - o->op_type = OP_GV; - return o; -} -#endif - OP * Perl_ck_rvconst(pTHX_ register OP *o) { + dVAR; SVOP *kid = (SVOP*)cUNOPo->op_first; o->op_private |= (PL_hints & HINT_STRICT_REFS); if (kid->op_type == OP_CONST) { - char *name; int iscv; GV *gv; - SV *kidsv = kid->op_sv; - STRLEN n_a; + SV * const kidsv = kid->op_sv; /* Is it a constant from cv_const_sv()? */ if (SvROK(kidsv) && SvREADONLY(kidsv)) { SV *rsv = SvRV(kidsv); - int svtype = SvTYPE(rsv); - char *badtype = Nullch; + const int svtype = SvTYPE(rsv); + const char *badtype = Nullch; switch (o->op_type) { case OP_RV2SV: @@ -4971,9 +5207,8 @@ Perl_ck_rvconst(pTHX_ register OP *o) Perl_croak(aTHX_ "Constant is not %s reference", badtype); return o; } - name = SvPV(kidsv, n_a); if ((PL_hints & HINT_STRICT_REFS) && (kid->op_private & OPpCONST_BARE)) { - char *badthing = Nullch; + const char *badthing = Nullch; switch (o->op_type) { case OP_RV2SV: badthing = "a SCALAR"; @@ -4987,8 +5222,8 @@ Perl_ck_rvconst(pTHX_ register OP *o) } if (badthing) Perl_croak(aTHX_ - "Can't use bareword (\"%s\") as %s ref while \"strict refs\" in use", - name, badthing); + "Can't use bareword (\"%"SVf"\") as %s ref while \"strict refs\" in use", + kidsv, badthing); } /* * This is a little tricky. We only want to add the symbol if we @@ -5000,7 +5235,7 @@ Perl_ck_rvconst(pTHX_ register OP *o) */ iscv = (o->op_type == OP_RV2CV) * 2; do { - gv = gv_fetchpv(name, + gv = gv_fetchsv(kidsv, iscv | !(kid->op_private & OPpCONST_ENTERED), iscv ? SVt_PVCV @@ -5034,20 +5269,21 @@ Perl_ck_rvconst(pTHX_ register OP *o) OP * Perl_ck_ftst(pTHX_ OP *o) { - I32 type = o->op_type; + dVAR; + const I32 type = o->op_type; if (o->op_flags & OPf_REF) { /* nothing */ } else if (o->op_flags & OPf_KIDS && cUNOPo->op_first->op_type != OP_STUB) { - SVOP *kid = (SVOP*)cUNOPo->op_first; + SVOP * const kid = (SVOP*)cUNOPo->op_first; if (kid->op_type == OP_CONST && (kid->op_private & OPpCONST_BARE)) { - STRLEN n_a; - OP *newop = newGVOP(type, OPf_REF, - gv_fetchpv(SvPVx(kid->op_sv, n_a), TRUE, SVt_PVIO)); + OP * const newop = newGVOP(type, OPf_REF, + gv_fetchsv(kid->op_sv, TRUE, SVt_PVIO)); op_free(o); o = newop; + return o; } else { if ((PL_hints & HINT_FILETEST_ACCESS) && @@ -5071,11 +5307,7 @@ Perl_ck_ftst(pTHX_ OP *o) OP * Perl_ck_fun(pTHX_ OP *o) { - register OP *kid; - OP **tokid; - OP *sibl; - I32 numargs = 0; - int type = o->op_type; + const int type = o->op_type; register I32 oa = PL_opargs[type] >> OASHIFT; if (o->op_flags & OPf_STACKED) { @@ -5086,9 +5318,11 @@ Perl_ck_fun(pTHX_ OP *o) } if (o->op_flags & OPf_KIDS) { - STRLEN n_a; - tokid = &cLISTOPo->op_first; - kid = cLISTOPo->op_first; + OP **tokid = &cLISTOPo->op_first; + register OP *kid = cLISTOPo->op_first; + OP *sibl; + I32 numargs = 0; + if (kid->op_type == OP_PUSHMARK || (kid->op_type == OP_NULL && kid->op_targ == OP_PUSHMARK)) { @@ -5129,13 +5363,12 @@ Perl_ck_fun(pTHX_ OP *o) if (kid->op_type == OP_CONST && (kid->op_private & OPpCONST_BARE)) { - char *name = SvPVx(((SVOP*)kid)->op_sv, n_a); - OP *newop = newAVREF(newGVOP(OP_GV, 0, - gv_fetchpv(name, TRUE, SVt_PVAV) )); + OP * const newop = newAVREF(newGVOP(OP_GV, 0, + gv_fetchsv(((SVOP*)kid)->op_sv, TRUE, SVt_PVAV) )); if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX)) Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX), - "Array @%s missing the @ in argument %"IVdf" of %s()", - name, (IV)numargs, PL_op_desc[type]); + "Array @%"SVf" missing the @ in argument %"IVdf" of %s()", + ((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]); op_free(kid); kid = newop; kid->op_sibling = sibl; @@ -5149,13 +5382,12 @@ Perl_ck_fun(pTHX_ OP *o) if (kid->op_type == OP_CONST && (kid->op_private & OPpCONST_BARE)) { - char *name = SvPVx(((SVOP*)kid)->op_sv, n_a); - OP *newop = newHVREF(newGVOP(OP_GV, 0, - gv_fetchpv(name, TRUE, SVt_PVHV) )); + OP * const newop = newHVREF(newGVOP(OP_GV, 0, + gv_fetchsv(((SVOP*)kid)->op_sv, TRUE, SVt_PVHV) )); if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX)) Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX), - "Hash %%%s missing the %% in argument %"IVdf" of %s()", - name, (IV)numargs, PL_op_desc[type]); + "Hash %%%"SVf" missing the %% in argument %"IVdf" of %s()", + ((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]); op_free(kid); kid = newop; kid->op_sibling = sibl; @@ -5167,7 +5399,7 @@ Perl_ck_fun(pTHX_ OP *o) break; case OA_CVREF: { - OP *newop = newUNOP(OP_NULL, 0, kid); + OP * const newop = newUNOP(OP_NULL, 0, kid); kid->op_sibling = 0; linklist(kid); newop->op_next = newop; @@ -5182,8 +5414,7 @@ Perl_ck_fun(pTHX_ OP *o) (kid->op_private & OPpCONST_BARE)) { OP *newop = newGVOP(OP_GV, 0, - gv_fetchpv(SvPVx(((SVOP*)kid)->op_sv, n_a), TRUE, - SVt_PVIO) ); + gv_fetchsv(((SVOP*)kid)->op_sv, TRUE, SVt_PVIO) ); if (!(o->op_private & 1) && /* if not unop */ kid == cLISTOPo->op_last) cLISTOPo->op_last = newop; @@ -5201,7 +5432,7 @@ Perl_ck_fun(pTHX_ OP *o) /* is this op a FH constructor? */ if (is_handle_constructor(o,numargs)) { - char *name = Nullch; + const char *name = Nullch; STRLEN len = 0; flags = 0; @@ -5229,12 +5460,11 @@ Perl_ck_fun(pTHX_ OP *o) else if (kid->op_type == OP_AELEM || kid->op_type == OP_HELEM) { - OP *op; - + OP *op = ((BINOP*)kid)->op_first; name = 0; - if ((op = ((BINOP*)kid)->op_first)) { + if (op) { SV *tmpstr = Nullsv; - char *a = + const char * const a = kid->op_type == OP_AELEM ? "[]" : "{}"; if (((op->op_type == OP_RV2AV) || @@ -5242,7 +5472,7 @@ Perl_ck_fun(pTHX_ OP *o) (op = ((UNOP*)op)->op_first) && (op->op_type == OP_GV)) { /* packagevar $a[] or $h{} */ - GV *gv = cGVOPx_gv(op); + GV * const gv = cGVOPx_gv(op); if (gv) tmpstr = Perl_newSVpvf(aTHX_ @@ -5253,7 +5483,7 @@ Perl_ck_fun(pTHX_ OP *o) else if (op->op_type == OP_PADAV || op->op_type == OP_PADHV) { /* lexicalvar $a[] or $h{} */ - char *padname = + const char * const padname = PAD_COMPNAME_PV(op->op_targ); if (padname) tmpstr = @@ -5261,10 +5491,9 @@ Perl_ck_fun(pTHX_ OP *o) "%s%c...%c", padname + 1, a[0], a[1]); - } if (tmpstr) { - name = SvPV(tmpstr, len); + name = SvPV_const(tmpstr, len); sv_2mortal(tmpstr); } } @@ -5278,7 +5507,7 @@ Perl_ck_fun(pTHX_ OP *o) SV *namesv; targ = pad_alloc(OP_RV2GV, SVs_PADTMP); namesv = PAD_SVl(targ); - (void)SvUPGRADE(namesv, SVt_PV); + SvUPGRADE(namesv, SVt_PV); if (*name != '$') sv_setpvn(namesv, "$", 1); sv_catpvn(namesv, name, len); @@ -5324,6 +5553,7 @@ Perl_ck_fun(pTHX_ OP *o) OP * Perl_ck_glob(pTHX_ OP *o) { + dVAR; GV *gv; o = ck_fun(o); @@ -5346,7 +5576,7 @@ Perl_ck_glob(pTHX_ OP *o) gv = gv_fetchpv("CORE::GLOBAL::glob", FALSE, SVt_PVCV); glob_gv = gv_fetchpv("File::Glob::csh_glob", FALSE, SVt_PVCV); GvCV(gv) = GvCV(glob_gv); - SvREFCNT_inc((SV*)GvCV(gv)); + (void)SvREFCNT_inc((SV*)GvCV(gv)); GvIMPORTED_CV_on(gv); LEAVE; } @@ -5378,9 +5608,10 @@ Perl_ck_glob(pTHX_ OP *o) OP * Perl_ck_grep(pTHX_ OP *o) { + dVAR; LOGOP *gwop; OP *kid; - OPCODE type = o->op_type == OP_GREPSTART ? OP_GREPWHILE : OP_MAPWHILE; + const OPCODE type = o->op_type == OP_GREPSTART ? OP_GREPWHILE : OP_MAPWHILE; I32 offset; o->op_ppaddr = PL_ppaddr[OP_GREPSTART]; @@ -5390,7 +5621,9 @@ Perl_ck_grep(pTHX_ OP *o) OP* k; o = ck_sort(o); kid = cLISTOPo->op_first->op_sibling; - for (k = cLISTOPo->op_first->op_sibling->op_next; k; k = k->op_next) { + if (!cUNOPx(kid)->op_next) + Perl_croak(aTHX_ "panic: ck_grep"); + for (k = cUNOPx(kid)->op_first; k; k = k->op_next) { kid = k; } kid->op_next = (OP*)gwop; @@ -5457,7 +5690,7 @@ Perl_ck_lengthconst(pTHX_ OP *o) OP * Perl_ck_lfun(pTHX_ OP *o) { - OPCODE type = o->op_type; + const OPCODE type = o->op_type; return modkids(ck_fun(o), type); } @@ -5502,7 +5735,7 @@ Perl_ck_defined(pTHX_ OP *o) /* 19990527 MJD */ OP * Perl_ck_rfun(pTHX_ OP *o) { - OPCODE type = o->op_type; + const OPCODE type = o->op_type; return refkids(ck_fun(o), type); } @@ -5546,7 +5779,7 @@ Perl_ck_sassign(pTHX_ OP *o) /* Cannot steal the second time! */ && !(kid->op_private & OPpTARGET_MY)) { - OP *kkid = kid->op_sibling; + OP * const kkid = kid->op_sibling; /* Can just relocate the target. */ if (kkid && kkid->op_type == OP_PADSV @@ -5563,6 +5796,19 @@ Perl_ck_sassign(pTHX_ OP *o) return kid; } } + /* optimise C to C */ + if (kid->op_type == OP_UNDEF) { + OP * const kkid = kid->op_sibling; + if (kkid && kkid->op_type == OP_PADSV + && (kkid->op_private & OPpLVAL_INTRO)) + { + cLISTOPo->op_first = NULL; + kid->op_sibling = NULL; + op_free(o); + op_free(kid); + return kkid; + } + } return o; } @@ -5570,7 +5816,7 @@ OP * Perl_ck_match(pTHX_ OP *o) { if (o->op_type != OP_QR) { - I32 offset = pad_findmy("$_"); + const I32 offset = pad_findmy("$_"); if (offset != NOT_IN_PAD && !(PAD_COMPNAME_FLAGS(offset) & SVpad_OUR)) { o->op_targ = offset; o->op_private |= OPpTARGET_MY; @@ -5584,13 +5830,13 @@ Perl_ck_match(pTHX_ OP *o) OP * Perl_ck_method(pTHX_ OP *o) { - OP *kid = cUNOPo->op_first; + OP * const kid = cUNOPo->op_first; if (kid->op_type == OP_CONST) { SV* sv = kSVOP->op_sv; - if (!(strchr(SvPVX(sv), ':') || strchr(SvPVX(sv), '\''))) { + if (!(strchr(SvPVX_const(sv), ':') || strchr(SvPVX_const(sv), '\''))) { OP *cmop; if (!SvREADONLY(sv) || !SvFAKE(sv)) { - sv = newSVpvn_share(SvPVX(sv), SvCUR(sv), 0); + sv = newSVpvn_share(SvPVX_const(sv), SvCUR(sv), 0); } else { kSVOP->op_sv = Nullsv; @@ -5612,13 +5858,11 @@ Perl_ck_null(pTHX_ OP *o) OP * Perl_ck_open(pTHX_ OP *o) { - HV *table = GvHV(PL_hintgv); + HV * const table = GvHV(PL_hintgv); if (table) { - SV **svp; - I32 mode; - svp = hv_fetch(table, "open_IN", 7, FALSE); + SV **svp = hv_fetch(table, "open_IN", 7, FALSE); if (svp && *svp) { - mode = mode_from_discipline(*svp); + const I32 mode = mode_from_discipline(*svp); if (mode & O_BINARY) o->op_private |= OPpOPEN_IN_RAW; else if (mode & O_TEXT) @@ -5627,7 +5871,7 @@ Perl_ck_open(pTHX_ OP *o) svp = hv_fetch(table, "open_OUT", 8, FALSE); if (svp && *svp) { - mode = mode_from_discipline(*svp); + const I32 mode = mode_from_discipline(*svp); if (mode & O_BINARY) o->op_private |= OPpOPEN_OUT_RAW; else if (mode & O_TEXT) @@ -5639,18 +5883,19 @@ Perl_ck_open(pTHX_ OP *o) { /* In case of three-arg dup open remove strictness * from the last arg if it is a bareword. */ - OP *first = cLISTOPx(o)->op_first; /* The pushmark. */ - OP *last = cLISTOPx(o)->op_last; /* The bareword. */ + OP * const first = cLISTOPx(o)->op_first; /* The pushmark. */ + OP * const last = cLISTOPx(o)->op_last; /* The bareword. */ OP *oa; - char *mode; + const char *mode; if ((last->op_type == OP_CONST) && /* The bareword. */ (last->op_private & OPpCONST_BARE) && (last->op_private & OPpCONST_STRICT) && (oa = first->op_sibling) && /* The fh. */ (oa = oa->op_sibling) && /* The mode. */ + (oa->op_type == OP_CONST) && SvPOK(((SVOP*)oa)->op_sv) && - (mode = SvPVX(((SVOP*)oa)->op_sv)) && + (mode = SvPVX_const(((SVOP*)oa)->op_sv)) && mode[0] == '>' && mode[1] == '&' && /* A dup open. */ (last == oa->op_sibling)) /* The bareword. */ last->op_private &= ~OPpCONST_STRICT; @@ -5673,37 +5918,49 @@ Perl_ck_repeat(pTHX_ OP *o) OP * Perl_ck_require(pTHX_ OP *o) { - GV* gv; + GV* gv = Nullgv; if (o->op_flags & OPf_KIDS) { /* Shall we supply missing .pm? */ - SVOP *kid = (SVOP*)cUNOPo->op_first; + SVOP * const kid = (SVOP*)cUNOPo->op_first; if (kid->op_type == OP_CONST && (kid->op_private & OPpCONST_BARE)) { + SV * const sv = kid->op_sv; + U32 was_readonly = SvREADONLY(sv); char *s; - for (s = SvPVX(kid->op_sv); *s; s++) { + + if (was_readonly) { + if (SvFAKE(sv)) { + sv_force_normal_flags(sv, 0); + assert(!SvREADONLY(sv)); + was_readonly = 0; + } else { + SvREADONLY_off(sv); + } + } + + for (s = SvPVX(sv); *s; s++) { if (*s == ':' && s[1] == ':') { *s = '/'; Move(s+2, s+1, strlen(s+2)+1, char); - --SvCUR(kid->op_sv); + SvCUR_set(sv, SvCUR(sv) - 1); } } - if (SvREADONLY(kid->op_sv)) { - SvREADONLY_off(kid->op_sv); - sv_catpvn(kid->op_sv, ".pm", 3); - SvREADONLY_on(kid->op_sv); - } - else - sv_catpvn(kid->op_sv, ".pm", 3); + sv_catpvn(sv, ".pm", 3); + SvFLAGS(sv) |= was_readonly; } } - /* handle override, if any */ - gv = gv_fetchpv("require", FALSE, SVt_PVCV); - if (!(gv && GvCVu(gv) && GvIMPORTED_CV(gv))) - gv = gv_fetchpv("CORE::GLOBAL::require", FALSE, SVt_PVCV); + if (!(o->op_flags & OPf_SPECIAL)) { /* Wasn't written as CORE::require */ + /* handle override, if any */ + gv = gv_fetchpv("require", FALSE, SVt_PVCV); + if (!(gv && GvCVu(gv) && GvIMPORTED_CV(gv))) { + GV * const * const gvp = (GV**)hv_fetch(PL_globalstash, "require", 7, FALSE); + gv = gvp ? *gvp : Nullgv; + } + } if (gv && GvCVu(gv) && GvIMPORTED_CV(gv)) { - OP *kid = cUNOPo->op_first; + OP * const kid = cUNOPo->op_first; cUNOPo->op_first = 0; op_free(o); return ck_subr(newUNOP(OP_ENTERSUB, OPf_STACKED, @@ -5719,27 +5976,18 @@ Perl_ck_require(pTHX_ OP *o) OP * Perl_ck_return(pTHX_ OP *o) { - OP *kid; if (CvLVALUE(PL_compcv)) { + OP *kid; for (kid = cLISTOPo->op_first->op_sibling; kid; kid = kid->op_sibling) mod(kid, OP_LEAVESUBLV); } return o; } -#if 0 -OP * -Perl_ck_retarget(pTHX_ OP *o) -{ - Perl_croak(aTHX_ "NOT IMPL LINE %d",__LINE__); - /* STUB */ - return o; -} -#endif - OP * Perl_ck_select(pTHX_ OP *o) { + dVAR; OP* kid; if (o->op_flags & OPf_KIDS) { kid = cLISTOPo->op_first->op_sibling; /* get past pushmark */ @@ -5760,7 +6008,7 @@ Perl_ck_select(pTHX_ OP *o) OP * Perl_ck_shift(pTHX_ OP *o) { - I32 type = o->op_type; + const I32 type = o->op_type; if (!(o->op_flags & OPf_KIDS)) { OP *argop; @@ -5841,8 +6089,9 @@ S_simplify_sort(pTHX_ OP *o) { register OP *kid = cLISTOPo->op_first->op_sibling; /* get past pushmark */ OP *k; - int reversed; + int descending; GV *gv; + const char *gvname; if (!(o->op_flags & OPf_STACKED)) return; GvMULTI_on(gv_fetchpv("a", TRUE, SVt_PV)); @@ -5869,12 +6118,14 @@ S_simplify_sort(pTHX_ OP *o) gv = kGVOP_gv; if (GvSTASH(gv) != PL_curstash) return; - if (strEQ(GvNAME(gv), "a")) - reversed = 0; - else if (strEQ(GvNAME(gv), "b")) - reversed = 1; + gvname = GvNAME(gv); + if (*gvname == 'a' && gvname[1] == '\0') + descending = 0; + else if (*gvname == 'b' && gvname[1] == '\0') + descending = 1; else return; + kid = k; /* back to cmp */ if (kBINOP->op_last->op_type != OP_RV2SV) return; @@ -5883,14 +6134,16 @@ S_simplify_sort(pTHX_ OP *o) return; kid = kUNOP->op_first; /* get past rv2sv */ gv = kGVOP_gv; - if (GvSTASH(gv) != PL_curstash - || ( reversed - ? strNE(GvNAME(gv), "a") - : strNE(GvNAME(gv), "b"))) + if (GvSTASH(gv) != PL_curstash) + return; + gvname = GvNAME(gv); + if ( descending + ? !(*gvname == 'a' && gvname[1] == '\0') + : !(*gvname == 'b' && gvname[1] == '\0')) return; o->op_flags &= ~(OPf_STACKED | OPf_SPECIAL); - if (reversed) - o->op_private |= OPpSORT_REVERSE; + if (descending) + o->op_private |= OPpSORT_DESCEND; if (k->op_type == OP_NCMP) o->op_private |= OPpSORT_NUMERIC; if (k->op_type == OP_I_NCMP) @@ -5903,6 +6156,7 @@ S_simplify_sort(pTHX_ OP *o) OP * Perl_ck_split(pTHX_ OP *o) { + dVAR; register OP *kid; if (o->op_flags & OPf_STACKED) @@ -5920,9 +6174,9 @@ Perl_ck_split(pTHX_ OP *o) } if (kid->op_type != OP_MATCH || kid->op_flags & OPf_STACKED) { - OP *sibl = kid->op_sibling; + OP * const sibl = kid->op_sibling; kid->op_sibling = 0; - kid = pmruntime( newPMOP(OP_MATCH, OPf_SPECIAL), kid, Nullop); + kid = pmruntime( newPMOP(OP_MATCH, OPf_SPECIAL), kid, 0); if (cLISTOPo->op_first == cLISTOPo->op_last) cLISTOPo->op_last = kid; cLISTOPo->op_first = kid; @@ -5932,7 +6186,7 @@ Perl_ck_split(pTHX_ OP *o) kid->op_type = OP_PUSHRE; kid->op_ppaddr = PL_ppaddr[OP_PUSHRE]; scalar(kid); - if (ckWARN(WARN_REGEXP) && ((PMOP *)kid)->op_pmflags & PMf_GLOBAL) { + if (((PMOP *)kid)->op_pmflags & PMf_GLOBAL && ckWARN(WARN_REGEXP)) { Perl_warner(aTHX_ packWARN(WARN_REGEXP), "Use of /g modifier is meaningless in split"); } @@ -5958,12 +6212,11 @@ Perl_ck_split(pTHX_ OP *o) OP * Perl_ck_join(pTHX_ OP *o) { - if (ckWARN(WARN_SYNTAX)) { - OP *kid = cLISTOPo->op_first->op_sibling; - if (kid && kid->op_type == OP_MATCH) { - char *pmstr = "STRING"; - if (PM_GETRE(kPMOP)) - pmstr = PM_GETRE(kPMOP)->precomp; + const OP * const kid = cLISTOPo->op_first->op_sibling; + if (kid && kid->op_type == OP_MATCH) { + if (ckWARN(WARN_SYNTAX)) { + const REGEXP *re = PM_GETRE(kPMOP); + const char *pmstr = re ? re->precomp : "STRING"; Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "/%s/ should probably be written as \"%s\"", pmstr, pmstr); @@ -5973,42 +6226,6 @@ Perl_ck_join(pTHX_ OP *o) } OP * -Perl_ck_state(pTHX_ OP *o) -{ - /* warn on C , C<$a && my $x=1;> style statements */ - OP *kid; - o = o->op_sibling; - if (!o || o->op_type != OP_NULL || !(o->op_flags & OPf_KIDS)) - return o; - kid = cUNOPo->op_first; - if (!(kid->op_type == OP_AND || kid->op_type == OP_OR)) - return o; - kid = kUNOP->op_first->op_sibling; - if (kid->op_type == OP_SASSIGN) - kid = kBINOP->op_first->op_sibling; - else if (kid->op_type == OP_AASSIGN) - kid = kBINOP->op_first->op_sibling; - - if (kid->op_type == OP_LIST - || (kid->op_type == OP_NULL && kid->op_targ == OP_LIST)) - { - kid = kUNOP->op_first; - if (kid->op_type == OP_PUSHMARK) - kid = kid->op_sibling; - } - if ((kid->op_type == OP_PADSV || kid->op_type == OP_PADAV - || kid->op_type == OP_PADHV) - && (kid->op_private & OPpLVAL_INTRO) - && (ckWARN(WARN_DEPRECATED))) - { - Perl_warner(aTHX_ packWARN(WARN_DEPRECATED), - "Deprecated use of my() in conditional"); - } - return o; -} - - -OP * Perl_ck_subr(pTHX_ OP *o) { OP *prev = ((cUNOPo->op_first->op_sibling) @@ -6022,8 +6239,7 @@ Perl_ck_subr(pTHX_ OP *o) I32 arg = 0; I32 contextclass = 0; char *e = 0; - STRLEN n_a; - bool delete=0; + bool delete_op = 0; o->op_private |= OPpENTERSUB_HASTARG; for (cvop = o2; cvop->op_sibling; cvop = cvop->op_sibling) ; @@ -6040,7 +6256,7 @@ Perl_ck_subr(pTHX_ OP *o) else { if (SvPOK(cv)) { namegv = CvANON(cv) ? gv : CvGV(cv); - proto = SvPV((SV*)cv, n_a); + proto = SvPV_nolen((SV*)cv); } if (CvASSERTION(cv)) { if (PL_hints & HINT_ASSERTING) { @@ -6048,8 +6264,8 @@ Perl_ck_subr(pTHX_ OP *o) o->op_private |= OPpENTERSUB_DB; } else { - delete=1; - if (ckWARN(WARN_ASSERTIONS) && !(PL_hints & HINT_ASSERTIONSSEEN)) { + delete_op = 1; + if (!(PL_hints & HINT_ASSERTIONSSEEN) && ckWARN(WARN_ASSERTIONS)) { Perl_warner(aTHX_ packWARN(WARN_ASSERTIONS), "Impossible to activate assertion call"); } @@ -6062,7 +6278,7 @@ Perl_ck_subr(pTHX_ OP *o) if (o2->op_type == OP_CONST) o2->op_private &= ~OPpCONST_STRICT; else if (o2->op_type == OP_LIST) { - OP *o = ((UNOP*)o2)->op_first->op_sibling; + OP * const o = ((UNOP*)o2)->op_first->op_sibling; if (o && o->op_type == OP_CONST) o->op_private &= ~OPpCONST_STRICT; } @@ -6118,13 +6334,11 @@ Perl_ck_subr(pTHX_ OP *o) (gvop = ((UNOP*)gvop)->op_first) && gvop->op_type == OP_GV) { - GV *gv = cGVOPx_gv(gvop); - OP *sibling = o2->op_sibling; - SV *n = newSVpvn("",0); + GV * const gv = cGVOPx_gv(gvop); + OP * const sibling = o2->op_sibling; + SV * const n = newSVpvn("",0); op_free(o2); - gv_fullname3(n, gv, ""); - if (SvCUR(n)>6 && strnEQ(SvPVX(n),"main::",6)) - sv_chop(n, SvPVX(n)+6); + gv_fullname4(n, gv, "", FALSE); o2 = newSVOP(OP_CONST, 0, n); prev->op_sibling = o2; o2->op_sibling = sibling; @@ -6154,8 +6368,8 @@ Perl_ck_subr(pTHX_ OP *o) break; case ']': if (contextclass) { - char *p = proto; - char s = *p; + char *p = proto; + const char s = *p; contextclass = 0; *p = '\0'; while (*--p != '['); @@ -6203,8 +6417,8 @@ Perl_ck_subr(pTHX_ OP *o) break; wrapref: { - OP* kid = o2; - OP* sib = kid->op_sibling; + OP* const kid = o2; + OP* const sib = kid->op_sibling; kid->op_sibling = 0; o2 = newUNOP(OP_REFGEN, 0, kid); o2->op_sibling = sib; @@ -6234,11 +6448,11 @@ Perl_ck_subr(pTHX_ OP *o) mod(o2, OP_ENTERSUB); prev = o2; o2 = o2->op_sibling; - } + } /* while */ if (proto && !optional && (*proto && *proto != '@' && *proto != '%' && *proto != ';')) return too_few_arguments(o, gv_ename(namegv)); - if(delete) { + if(delete_op) { op_free(o); o=newSVOP(OP_CONST, 0, newSViv(0)); } @@ -6298,32 +6512,31 @@ Perl_ck_substr(pTHX_ OP *o) return o; } -/* A peephole optimizer. We visit the ops in the order they're to execute. */ +/* 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 */ void Perl_peep(pTHX_ register OP *o) { + dVAR; register OP* oldop = 0; - if (!o || o->op_seq) + if (!o || o->op_opt) return; ENTER; SAVEOP(); SAVEVPTR(PL_curcop); for (; o; o = o->op_next) { - if (o->op_seq) + if (o->op_opt) break; - /* The special value -1 is used by the B::C compiler backend to indicate - * that an op is statically defined and should not be freed */ - if (!PL_op_seqmax || PL_op_seqmax == (U16)-1) - PL_op_seqmax = 1; PL_op = o; switch (o->op_type) { case OP_SETSTATE: case OP_NEXTSTATE: case OP_DBSTATE: PL_curcop = ((COP*)o); /* for warnings */ - o->op_seq = PL_op_seqmax++; + o->op_opt = 1; break; case OP_CONST: @@ -6335,7 +6548,7 @@ Perl_peep(pTHX_ register OP *o) * Despite being a "constant", the SV is written to, * for reference counts, sv_upgrade() etc. */ if (cSVOP->op_sv) { - PADOFFSET ix = pad_alloc(OP_CONST, SVs_PADTMP); + const PADOFFSET ix = pad_alloc(OP_CONST, SVs_PADTMP); if (o->op_type == OP_CONST && SvPADTMP(cSVOPo->op_sv)) { /* If op_sv is already a PADTMP then it is being used by * some pad, so make a copy. */ @@ -6354,7 +6567,7 @@ Perl_peep(pTHX_ register OP *o) o->op_targ = ix; } #endif - o->op_seq = PL_op_seqmax++; + o->op_opt = 1; break; case OP_CONCAT: @@ -6372,11 +6585,11 @@ Perl_peep(pTHX_ register OP *o) op_null(o->op_next); } ignore_optimization: - o->op_seq = PL_op_seqmax++; + o->op_opt = 1; break; case OP_STUB: if ((o->op_flags & OPf_WANT) != OPf_WANT_LIST) { - o->op_seq = PL_op_seqmax++; + o->op_opt = 1; break; /* Scalar stub must produce undef. List stub is noop */ } goto nothin; @@ -6391,6 +6604,7 @@ Perl_peep(pTHX_ register OP *o) to peep() from mistakenly concluding that optimisation has already occurred. This doesn't fix the real problem, though (See 20010220.007). AMS 20010719 */ + /* op_seq functionality is now replaced by op_opt */ if (oldop && o->op_next) { oldop->op_next = o->op_next; continue; @@ -6404,25 +6618,17 @@ Perl_peep(pTHX_ register OP *o) oldop->op_next = o->op_next; continue; } - o->op_seq = PL_op_seqmax++; + o->op_opt = 1; break; + case OP_PADAV: case OP_GV: - if (o->op_next->op_type == OP_RV2SV) { - if (!(o->op_next->op_private & OPpDEREF)) { - op_null(o->op_next); - o->op_private |= o->op_next->op_private & (OPpLVAL_INTRO - | OPpOUR_INTRO); - o->op_next = o->op_next->op_next; - o->op_type = OP_GVSV; - o->op_ppaddr = PL_ppaddr[OP_GVSV]; - } - } - else if (o->op_next->op_type == OP_RV2AV) { - OP* pop = o->op_next->op_next; + if (o->op_type == OP_PADAV || o->op_next->op_type == OP_RV2AV) { + OP* pop = (o->op_type == OP_PADAV) ? + o->op_next : o->op_next->op_next; IV i; if (pop && pop->op_type == OP_CONST && - (PL_op = pop->op_next) && + ((PL_op = pop->op_next)) && pop->op_next->op_type == OP_AELEM && !(pop->op_next->op_private & (OPpLVAL_INTRO|OPpLVAL_DEFER|OPpDEREF|OPpMAYBE_LVSUB)) && @@ -6431,23 +6637,43 @@ Perl_peep(pTHX_ register OP *o) i >= 0) { GV *gv; - op_null(o->op_next); + if (cSVOPx(pop)->op_private & OPpCONST_STRICT) + no_bareword_allowed(pop); + if (o->op_type == OP_GV) + op_null(o->op_next); op_null(pop->op_next); op_null(pop); o->op_flags |= pop->op_next->op_flags & OPf_MOD; o->op_next = pop->op_next->op_next; - o->op_type = OP_AELEMFAST; o->op_ppaddr = PL_ppaddr[OP_AELEMFAST]; o->op_private = (U8)i; - gv = cGVOPo_gv; - GvAVn(gv); + if (o->op_type == OP_GV) { + gv = cGVOPo_gv; + GvAVn(gv); + } + else + o->op_flags |= OPf_SPECIAL; + o->op_type = OP_AELEMFAST; + } + o->op_opt = 1; + break; + } + + if (o->op_next->op_type == OP_RV2SV) { + if (!(o->op_next->op_private & OPpDEREF)) { + op_null(o->op_next); + o->op_private |= o->op_next->op_private & (OPpLVAL_INTRO + | OPpOUR_INTRO); + o->op_next = o->op_next->op_next; + o->op_type = OP_GVSV; + o->op_ppaddr = PL_ppaddr[OP_GVSV]; } } else if ((o->op_private & OPpEARLY_CV) && ckWARN(WARN_PROTOTYPE)) { - GV *gv = cGVOPo_gv; - if (SvTYPE(gv) == SVt_PVGV && GvCV(gv) && SvPVX(GvCV(gv))) { + 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 *sv = sv_newmortal(); + SV * const sv = sv_newmortal(); gv_efullname3(sv, gv, Nullch); Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "%"SVf"() called too early to check prototype", @@ -6466,7 +6692,7 @@ Perl_peep(pTHX_ register OP *o) op_null(o->op_next); } - o->op_seq = PL_op_seqmax++; + o->op_opt = 1; break; case OP_MAPWHILE: @@ -6479,7 +6705,7 @@ Perl_peep(pTHX_ register OP *o) case OP_DORASSIGN: case OP_COND_EXPR: case OP_RANGE: - o->op_seq = PL_op_seqmax++; + o->op_opt = 1; while (cLOGOP->op_other->op_type == OP_NULL) cLOGOP->op_other = cLOGOP->op_other->op_next; peep(cLOGOP->op_other); /* Recursive calls are not replaced by fptr calls */ @@ -6487,7 +6713,7 @@ Perl_peep(pTHX_ register OP *o) case OP_ENTERLOOP: case OP_ENTERITER: - o->op_seq = PL_op_seqmax++; + o->op_opt = 1; while (cLOOP->op_redoop->op_type == OP_NULL) cLOOP->op_redoop = cLOOP->op_redoop->op_next; peep(cLOOP->op_redoop); @@ -6502,7 +6728,7 @@ Perl_peep(pTHX_ register OP *o) case OP_QR: case OP_MATCH: case OP_SUBST: - o->op_seq = PL_op_seqmax++; + o->op_opt = 1; while (cPMOP->op_pmreplstart && cPMOP->op_pmreplstart->op_type == OP_NULL) cPMOP->op_pmreplstart = cPMOP->op_pmreplstart->op_next; @@ -6510,14 +6736,15 @@ Perl_peep(pTHX_ register OP *o) break; case OP_EXEC: - o->op_seq = PL_op_seqmax++; - if (ckWARN(WARN_SYNTAX) && o->op_next - && o->op_next->op_type == OP_NEXTSTATE) { + o->op_opt = 1; + if (o->op_next && o->op_next->op_type == OP_NEXTSTATE + && ckWARN(WARN_SYNTAX)) + { if (o->op_next->op_sibling && o->op_next->op_sibling->op_type != OP_EXIT && o->op_next->op_sibling->op_type != OP_WARN && o->op_next->op_sibling->op_type != OP_DIE) { - line_t oldline = CopLINE(PL_curcop); + const line_t oldline = CopLINE(PL_curcop); CopLINE_set(PL_curcop, CopLINE((COP*)o->op_next)); Perl_warner(aTHX_ packWARN(WARN_EXEC), @@ -6530,12 +6757,14 @@ Perl_peep(pTHX_ register OP *o) break; case OP_HELEM: { + UNOP *rop; SV *lexname; + GV **fields; SV **svp, *sv; - char *key = NULL; + const char *key = NULL; STRLEN keylen; - o->op_seq = PL_op_seqmax++; + o->op_opt = 1; if (((BINOP*)o)->op_last->op_type != OP_CONST) break; @@ -6543,29 +6772,128 @@ Perl_peep(pTHX_ register OP *o) /* Make the CONST have a shared SV */ svp = cSVOPx_svp(((BINOP*)o)->op_last); if ((!SvFAKE(sv = *svp) || !SvREADONLY(sv)) && !IS_PADCONST(sv)) { - key = SvPV(sv, keylen); + key = SvPV_const(sv, keylen); lexname = newSVpvn_share(key, SvUTF8(sv) ? -(I32)keylen : 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 (!(SvFLAGS(lexname) & SVpad_TYPED)) + break; + fields = (GV**)hv_fetch(SvSTASH(lexname), "FIELDS", 6, FALSE); + if (!fields || !GvHV(*fields)) + break; + key = SvPV_const(*svp, keylen); + if (!hv_fetch(GvHV(*fields), key, + SvUTF8(*svp) ? -(I32)keylen : 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_SORT: { - /* make @a = sort @a act in-place */ + 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 (!(SvFLAGS(lexname) & SVpad_TYPED)) + break; + fields = (GV**)hv_fetch(SvSTASH(lexname), "FIELDS", 6, 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 : 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_SORT: { /* will point to RV2AV or PADAV op on LHS/RHS of assign */ - OP *oleft, *oright; + OP *oleft; OP *o2; - o->op_seq = PL_op_seqmax++; - /* check that RHS of sort is a single plain array */ - oright = cUNOPo->op_first; + OP *oright = cUNOPo->op_first; if (!oright || oright->op_type != OP_PUSHMARK) break; + + /* reverse sort ... can be optimised. */ + if (!cUNOPo->op_sibling) { + /* Nothing follows us on the list. */ + OP * const reverse = o->op_next; + + if (reverse->op_type == OP_REVERSE && + (reverse->op_flags & OPf_WANT) == OPf_WANT_LIST) { + OP * const pushmark = cUNOPx(reverse)->op_first; + if (pushmark && (pushmark->op_type == OP_PUSHMARK) + && (cUNOPx(pushmark)->op_sibling == o)) { + /* reverse -> pushmark -> sort */ + o->op_private |= OPpSORT_REVERSE; + op_null(reverse); + pushmark->op_next = oright->op_next; + op_null(oright); + } + } + } + + /* make @a = sort @a act in-place */ + + o->op_opt = 1; + oright = cUNOPx(oright)->op_sibling; if (!oright) break; @@ -6605,6 +6933,17 @@ Perl_peep(pTHX_ register OP *o) || (o2->op_flags & OPf_WANT) != OPf_WANT_VOID) break; + /* check that the sort is the first arg on RHS of assign */ + + o2 = cUNOPx(o2)->op_first; + if (!o2 || o2->op_type != OP_NULL) + break; + o2 = cUNOPx(o2)->op_first; + if (!o2 || o2->op_type != OP_PUSHMARK) + break; + if (o2->op_sibling != o) + break; + /* check the array is the same on both sides */ if (oleft->op_type == OP_RV2AV) { if (oright->op_type != OP_RV2AV @@ -6640,11 +6979,99 @@ Perl_peep(pTHX_ register OP *o) break; } - + case OP_REVERSE: { + OP *ourmark, *theirmark, *ourlast, *iter, *expushmark, *rv2av; + OP *gvop = NULL; + LISTOP *enter, *exlist; + o->op_opt = 1; + + enter = (LISTOP *) o->op_next; + if (!enter) + break; + if (enter->op_type == OP_NULL) { + enter = (LISTOP *) enter->op_next; + if (!enter) + break; + } + /* for $a (...) will have OP_GV then OP_RV2GV here. + for (...) just has an OP_GV. */ + if (enter->op_type == OP_GV) { + gvop = (OP *) enter; + enter = (LISTOP *) enter->op_next; + if (!enter) + break; + if (enter->op_type == OP_RV2GV) { + enter = (LISTOP *) enter->op_next; + if (!enter) + break; + } + } + + if (enter->op_type != OP_ENTERITER) + break; + + iter = enter->op_next; + if (!iter || iter->op_type != OP_ITER) + break; + + expushmark = enter->op_first; + if (!expushmark || expushmark->op_type != OP_NULL + || expushmark->op_targ != OP_PUSHMARK) + break; + + exlist = (LISTOP *) expushmark->op_sibling; + if (!exlist || exlist->op_type != OP_NULL + || exlist->op_targ != OP_LIST) + break; + + if (exlist->op_last != o) { + /* Mmm. Was expecting to point back to this op. */ + break; + } + theirmark = exlist->op_first; + if (!theirmark || theirmark->op_type != OP_PUSHMARK) + break; + if (theirmark->op_sibling != o) { + /* There's something between the mark and the reverse, eg + for (1, reverse (...)) + so no go. */ + break; + } + + ourmark = ((LISTOP *)o)->op_first; + if (!ourmark || ourmark->op_type != OP_PUSHMARK) + break; + + ourlast = ((LISTOP *)o)->op_last; + if (!ourlast || ourlast->op_next != o) + break; + + rv2av = ourmark->op_sibling; + if (rv2av && rv2av->op_type == OP_RV2AV && rv2av->op_sibling == 0 + && rv2av->op_flags == (OPf_WANT_LIST | OPf_KIDS) + && enter->op_flags == (OPf_WANT_LIST | OPf_KIDS)) { + /* We're just reversing a single array. */ + rv2av->op_flags = OPf_WANT_SCALAR | OPf_KIDS | OPf_REF; + enter->op_flags |= OPf_STACKED; + } + + /* We don't have control over who points to theirmark, so sacrifice + ours. */ + theirmark->op_next = ourmark->op_next; + theirmark->op_flags = ourmark->op_flags; + ourlast->op_next = gvop ? gvop : (OP *) enter; + op_null(ourmark); + op_null(o); + enter->op_private |= OPpITER_REVERSED; + iter->op_private |= OPpITER_REVERSED; + + break; + } + default: - o->op_seq = PL_op_seqmax++; + o->op_opt = 1; break; } oldop = o; @@ -6652,45 +7079,44 @@ Perl_peep(pTHX_ register OP *o) LEAVE; } - - -char* Perl_custom_op_name(pTHX_ OP* o) +char* +Perl_custom_op_name(pTHX_ const OP* o) { - IV index = PTR2IV(o->op_ppaddr); + const IV index = PTR2IV(o->op_ppaddr); SV* keysv; HE* he; if (!PL_custom_op_names) /* This probably shouldn't happen */ - return PL_op_name[OP_CUSTOM]; + return (char *)PL_op_name[OP_CUSTOM]; keysv = sv_2mortal(newSViv(index)); he = hv_fetch_ent(PL_custom_op_names, keysv, 0, 0); if (!he) - return PL_op_name[OP_CUSTOM]; /* Don't know who you are */ + return (char *)PL_op_name[OP_CUSTOM]; /* Don't know who you are */ return SvPV_nolen(HeVAL(he)); } -char* Perl_custom_op_desc(pTHX_ OP* o) +char* +Perl_custom_op_desc(pTHX_ const OP* o) { - IV index = PTR2IV(o->op_ppaddr); + const IV index = PTR2IV(o->op_ppaddr); SV* keysv; HE* he; if (!PL_custom_op_descs) - return PL_op_desc[OP_CUSTOM]; + return (char *)PL_op_desc[OP_CUSTOM]; keysv = sv_2mortal(newSViv(index)); he = hv_fetch_ent(PL_custom_op_descs, keysv, 0, 0); if (!he) - return PL_op_desc[OP_CUSTOM]; + return (char *)PL_op_desc[OP_CUSTOM]; return SvPV_nolen(HeVAL(he)); } - #include "XSUB.h" /* Efficient sub that returns a constant scalar value. */ @@ -6701,10 +7127,20 @@ const_sv_xsub(pTHX_ CV* cv) if (items != 0) { #if 0 Perl_croak(aTHX_ "usage: %s::%s()", - HvNAME(GvSTASH(CvGV(cv))), GvNAME(CvGV(cv))); + HvNAME_get(GvSTASH(CvGV(cv))), GvNAME(CvGV(cv))); #endif } EXTEND(sp, 1); ST(0) = (SV*)XSANY.any_ptr; XSRETURN(1); } + +/* + * Local variables: + * c-indentation-style: bsd + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + * + * ex: set ts=8 sts=4 sw=4 noet: + */