X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/b5a930ec3bf87d0d126b3ddd1f5cc0587aae7f49..a034e688aeb372632feafc428b392a22393dec55:/op.c diff --git a/op.c b/op.c index 0c688da..f3f7b6a 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 @@ -120,28 +176,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 +256,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,8 +270,9 @@ 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_static) return; @@ -228,11 +286,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 +297,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 +314,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. */ @@ -410,6 +473,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); @@ -418,6 +482,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)) @@ -425,13 +503,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) @@ -449,8 +527,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); } @@ -462,7 +540,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); @@ -476,6 +554,7 @@ S_scalarboolean(pTHX_ OP *o) OP * Perl_scalar(pTHX_ OP *o) { + dVAR; OP *kid; /* assumes no premature commitment */ @@ -546,8 +625,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; @@ -661,6 +741,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: @@ -765,8 +854,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); } @@ -776,6 +865,7 @@ Perl_listkids(pTHX_ OP *o) OP * Perl_list(pTHX_ OP *o) { + dVAR; OP *kid; /* assumes no premature commitment */ @@ -851,14 +941,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); @@ -878,8 +967,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); } @@ -900,6 +989,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; @@ -1239,7 +1329,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: @@ -1286,7 +1376,7 @@ 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 argnum) { switch (o->op_type) { case OP_PIPE_OP: @@ -1311,8 +1401,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); } @@ -1322,6 +1412,7 @@ Perl_refkids(pTHX_ OP *o, I32 type) OP * Perl_ref(pTHX_ OP *o, I32 type) { + dVAR; OP *kid; if (!o || PL_error_count) @@ -1434,6 +1525,7 @@ 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 */ @@ -1510,7 +1602,11 @@ S_apply_attrs_my(pTHX_ HV *stash, OP *target, OP *attrs, OP **imopsp) meth = newSVpvn("import", 6); (void)SvUPGRADE(meth, SVt_PVIV); (void)SvIOK_on(meth); - PERL_HASH(SvUVX(meth), SvPVX(meth), SvCUR(meth)); + { + U32 hash; + PERL_HASH(hash, SvPVX(meth), SvCUR(meth)); + SvUV_set(meth, hash); + } imop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL|OPf_WANT_VOID, append_elem(OP_LIST, prepend_elem(OP_LIST, pack, list(arg)), @@ -1539,8 +1635,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; @@ -1551,7 +1647,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 *sstr = attrstr; for (; !isSPACE(*attrstr) && len; --len, ++attrstr) ; attrs = append_elem(OP_LIST, attrs, newSVOP(OP_CONST, 0, @@ -1572,7 +1668,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) @@ -1580,6 +1675,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) { @@ -1687,7 +1783,7 @@ Perl_bind_match(pTHX_ I32 type, OP *left, OP *right) 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 || + const char *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 || @@ -1728,7 +1824,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 * @@ -1743,6 +1839,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); @@ -1763,19 +1860,17 @@ Perl_scope(pTHX_ OP *o) return o; } +/* XXX kept for BINCOMPAT only */ void Perl_save_hints(pTHX) { - SAVEI32(PL_hints); - SAVESPTR(GvHV(PL_hintgv)); - GvHV(PL_hintgv) = newHVhv(GvHV(PL_hintgv)); - SAVEFREESV(GvHV(PL_hintgv)); + Perl_croak(aTHX_ "internal error: obsolete function save_hints() called"); } 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; @@ -1795,7 +1890,7 @@ Perl_block_start(pTHX_ int full) OP* Perl_block_end(pTHX_ I32 floor, OP *seq) { - int needblockscope = PL_hints & HINT_BLOCK_SCOPE; + const int needblockscope = PL_hints & HINT_BLOCK_SCOPE; OP* retval = scalarseq(seq); LEAVE_SCOPE(floor); PL_compiling.op_private = (U8)(PL_hints & HINT_PRIVATE_MASK); @@ -1808,7 +1903,7 @@ 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)); } @@ -1930,6 +2025,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; @@ -2009,8 +2105,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) @@ -2040,6 +2137,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 @@ -2053,7 +2151,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); @@ -2070,7 +2168,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); @@ -2095,10 +2193,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; @@ -2119,7 +2217,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; @@ -2161,6 +2259,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); @@ -2195,6 +2294,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; @@ -2213,6 +2313,7 @@ Perl_newOP(pTHX_ I32 type, I32 flags) OP * Perl_newUNOP(pTHX_ I32 type, I32 flags, OP *first) { + dVAR; UNOP *unop; if (!first) @@ -2236,6 +2337,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); @@ -2267,13 +2369,13 @@ Perl_newBINOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) 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; } @@ -2347,7 +2449,7 @@ 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); @@ -2588,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); @@ -2629,15 +2732,57 @@ Perl_newPMOP(pTHX_ I32 type, I32 flags) 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 (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) + 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; @@ -2646,7 +2791,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl) STRLEN plen; SV *pat = ((SVOP*)expr)->op_sv; char *p = SvPV(pat, plen); - if ((o->op_flags & OPf_SPECIAL) && strEQ(p, " ")) { + if ((o->op_flags & OPf_SPECIAL) && (*p == ' ' && p[1] == '\0')) { sv_setpvn(pat, "\\s+", 3); p = SvPV(pat, plen); pm->op_pmflags |= PMf_SKIPWHITE; @@ -2668,11 +2813,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; @@ -2769,6 +2917,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; @@ -2786,6 +2935,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; @@ -2807,6 +2957,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); @@ -2819,6 +2970,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; @@ -2836,7 +2988,7 @@ 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); @@ -2884,7 +3036,11 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg) meth = newSVpvn("VERSION",7); sv_upgrade(meth, SVt_PVIV); (void)SvIOK_on(meth); - PERL_HASH(SvUVX(meth), SvPVX(meth), SvCUR(meth)); + { + U32 hash; + PERL_HASH(hash, SvPVX(meth), SvCUR(meth)); + SvUV_set(meth, hash); + } veop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL, append_elem(OP_LIST, prepend_elem(OP_LIST, pack, list(version)), @@ -2908,7 +3064,11 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg) 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)); + { + U32 hash; + PERL_HASH(hash, SvPVX(meth), SvCUR(meth)); + SvUV_set(meth, hash); + } imop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL, append_elem(OP_LIST, prepend_elem(OP_LIST, pack, list(arg)), @@ -3014,9 +3174,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); @@ -3058,7 +3218,7 @@ Perl_newSLICEOP(pTHX_ I32 flags, OP *subscript, OP *listval) } STATIC I32 -S_list_assignment(pTHX_ register OP *o) +S_list_assignment(pTHX_ register const OP *o) { if (!o) return TRUE; @@ -3067,8 +3227,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 = list_assignment(cLOGOPo->op_first->op_sibling); + const I32 f = list_assignment(cLOGOPo->op_first->op_sibling->op_sibling); if (t && f) return TRUE; @@ -3126,6 +3286,15 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) op_free(right); return Nullop; } + /* 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); + left->op_flags &= ~(OPf_REF|OPf_SPECIAL); + return left; + } curop = list(force_list(left)); o = newBINOP(OP_AASSIGN, flags, list(force_list(right)), curop); o->op_private = (U8)(0 | (flags >> 8)); @@ -3153,7 +3322,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 || @@ -3163,8 +3332,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) @@ -3186,7 +3354,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 @@ -3263,7 +3431,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); @@ -3316,25 +3485,25 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o) 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); + 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; @@ -3364,24 +3533,45 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp) no_bareword_allowed(first); else if (ckWARN(WARN_BAREWORD) && (first->op_private & OPpCONST_BARE)) 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; - other->op_private |= OPpCONST_SHORTCIRCUIT; + 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; - first->op_private |= OPpCONST_SHORTCIRCUIT; + 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. */ { - OP *k1 = ((UNOP*)first)->op_first; - OP *k2 = k1->op_sibling; + const OP *k1 = ((UNOP*)first)->op_first; + const OP *k2 = k1->op_sibling; OPCODE warnop = 0; switch (first->op_type) { @@ -3406,7 +3596,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()", @@ -3448,6 +3638,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; @@ -3503,6 +3694,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; @@ -3551,8 +3743,9 @@ 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); + (void)debuggable; if (expr) { if (once && expr->op_type == OP_CONST && !SvTRUE(((SVOP*)expr)->op_sv)) @@ -3562,8 +3755,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 *k1 = ((UNOP*)expr)->op_first; + const OP *k2 = (k1) ? k1->op_sibling : NULL; switch (expr->op_type) { case OP_NULL: if (k2 && k2->op_type == OP_READLINE @@ -3606,21 +3799,24 @@ 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; + (void)debuggable; 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; + const OP *k1 = ((UNOP*)expr)->op_first; + const OP *k2 = (k1) ? k1->op_sibling : NULL; switch (expr->op_type) { case OP_NULL: if (k2 && k2->op_type == OP_READLINE @@ -3641,7 +3837,7 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP * if (!block) block = newOP(OP_NULL, 0); - else if (cont) { + else if (cont || has_my) { block = scope(block); } @@ -3701,6 +3897,7 @@ 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) { + dVAR; LOOP *loop; OP *wop; PADOFFSET padoff = 0; @@ -3731,7 +3928,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); } @@ -3775,7 +3972,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); @@ -3786,7 +3982,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; } @@ -3794,7 +3990,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); } @@ -3841,6 +4037,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__ */ @@ -3883,7 +4080,7 @@ 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(); @@ -3895,7 +4092,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); @@ -3950,7 +4149,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; @@ -4008,6 +4207,7 @@ Perl_op_const_sv(pTHX_ OP *o, CV *cv) void Perl_newMYSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) { + (void)floor; if (o) SAVEFREEOP(o); if (proto) @@ -4028,15 +4228,24 @@ 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) { + dVAR; STRLEN n_a; - char *name; - char *aname; + const char *name; + const char *aname; GV *gv; - char *ps = proto ? SvPVx(((SVOP*)proto)->op_sv, n_a) : Nullch; + char *ps; register CV *cv=0; SV *const_sv; name = o ? SvPVx(cSVOPo->op_sv, n_a) : Nullch; + + if (proto) { + assert(proto->op_type == OP_CONST); + ps = SvPVx(((SVOP*)proto)->op_sv, n_a); + } + else + ps = Nullch; + if (!name && PERLDB_NAMEANON && CopLINE(PL_curcop)) { SV *sv = sv_newmortal(); Perl_sv_setpvf(aTHX_ sv, "%s[%s:%"IVdf"]", @@ -4046,10 +4255,13 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) } 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 = name ? gv_fetchsv(cSVOPo->op_sv, + GV_ADDMULTI | ((block || attrs) ? 0 : GV_NOINIT), + SVt_PVCV) + : gv_fetchpv(aname ? aname + : (PL_curstash ? "__ANON__" : "__ANON__::__ANON__"), + GV_ADDMULTI | ((block || attrs) ? 0 : GV_NOINIT), + SVt_PVCV); if (o) SAVEFREEOP(o); @@ -4092,7 +4304,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) 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)) { @@ -4125,7 +4337,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) || (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), @@ -4139,7 +4351,7 @@ 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 "" */ @@ -4228,10 +4440,10 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) 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); @@ -4275,8 +4487,8 @@ 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); @@ -4311,7 +4523,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); @@ -4373,8 +4585,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; @@ -4414,7 +4627,7 @@ 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 : (PL_curstash ? "__ANON__" : "__ANON__::__ANON__"), @@ -4434,7 +4647,7 @@ Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename) /* 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); + const line_t oldline = CopLINE(PL_curcop); if (PL_copline != NOLINE) CopLINE_set(PL_curcop, PL_copline); Perl_warner(aTHX_ packWARN(WARN_REDEFINE), @@ -4461,12 +4674,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 @@ -4517,15 +4730,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)"); @@ -4534,10 +4745,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); @@ -4591,6 +4804,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; @@ -4614,6 +4828,7 @@ Perl_oopsAV(pTHX_ OP *o) OP * Perl_oopsHV(pTHX_ OP *o) { + dVAR; switch (o->op_type) { case OP_PADSV: case OP_PADAV: @@ -4639,6 +4854,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]; @@ -4663,6 +4879,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]; @@ -4681,7 +4898,12 @@ Perl_oopsCV(pTHX_ OP *o) { Perl_croak(aTHX_ "NOT IMPL LINE %d",__LINE__); /* STUB */ - return o; + (void)o; +#ifndef HASATTRIBUTE + /* No __attribute__, so the compiler doesn't know that croak never returns + */ + return 0; +#endif } OP * @@ -4693,6 +4915,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]; @@ -4705,7 +4928,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) @@ -4732,8 +4956,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 * left = cBINOPo->op_first; + const OP * right = left->op_sibling; if ((OP_IS_NUMCOMPARE(left->op_type) && (left->op_flags & OPf_PARENS) == 0) || (OP_IS_NUMCOMPARE(right->op_type) && @@ -4751,7 +4975,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; @@ -4761,10 +4985,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; @@ -4823,7 +5048,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) { @@ -4838,6 +5063,7 @@ 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; @@ -4897,8 +5123,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) @@ -4946,21 +5172,20 @@ Perl_ck_gvconst(pTHX_ register OP *o) 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; /* 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 char *badtype = Nullch; switch (o->op_type) { case OP_RV2SV: @@ -4984,9 +5209,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"; @@ -5000,8 +5224,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 @@ -5013,7 +5237,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 @@ -5047,7 +5271,8 @@ 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 */ @@ -5056,11 +5281,11 @@ Perl_ck_ftst(pTHX_ OP *o) SVOP *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)); + gv_fetchsv(kid->op_sv, TRUE, SVt_PVIO)); op_free(o); o = newop; + return o; } else { if ((PL_hints & HINT_FILETEST_ACCESS) && @@ -5084,11 +5309,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) { @@ -5099,9 +5320,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)) { @@ -5142,13 +5365,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) )); + 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; @@ -5162,13 +5384,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) )); + 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; @@ -5195,8 +5416,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; @@ -5214,7 +5434,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; @@ -5247,7 +5467,7 @@ Perl_ck_fun(pTHX_ OP *o) name = 0; if ((op = ((BINOP*)kid)->op_first)) { SV *tmpstr = Nullsv; - char *a = + const char *a = kid->op_type == OP_AELEM ? "[]" : "{}"; if (((op->op_type == OP_RV2AV) || @@ -5266,7 +5486,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 *padname = PAD_COMPNAME_PV(op->op_targ); if (padname) tmpstr = @@ -5337,6 +5557,7 @@ Perl_ck_fun(pTHX_ OP *o) OP * Perl_ck_glob(pTHX_ OP *o) { + dVAR; GV *gv; o = ck_fun(o); @@ -5359,7 +5580,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; } @@ -5391,9 +5612,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]; @@ -5403,7 +5625,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; @@ -5470,7 +5694,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); } @@ -5515,7 +5739,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); } @@ -5576,6 +5800,19 @@ Perl_ck_sassign(pTHX_ OP *o) return kid; } } + /* optimise C to C */ + if (kid->op_type == OP_UNDEF) { + OP *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; } @@ -5583,7 +5820,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; @@ -5697,7 +5934,7 @@ Perl_ck_require(pTHX_ OP *o) if (*s == ':' && s[1] == ':') { *s = '/'; Move(s+2, s+1, strlen(s+2)+1, char); - --SvCUR(kid->op_sv); + SvCUR_set(kid->op_sv, SvCUR(kid->op_sv) - 1); } } if (SvREADONLY(kid->op_sv)) { @@ -5732,8 +5969,8 @@ 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); } @@ -5753,6 +5990,7 @@ Perl_ck_retarget(pTHX_ OP *o) 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 */ @@ -5773,7 +6011,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; @@ -5854,8 +6092,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)); @@ -5882,12 +6121,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; @@ -5896,14 +6137,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) @@ -5916,6 +6159,7 @@ S_simplify_sort(pTHX_ OP *o) OP * Perl_ck_split(pTHX_ OP *o) { + dVAR; register OP *kid; if (o->op_flags & OPf_STACKED) @@ -5935,7 +6179,7 @@ Perl_ck_split(pTHX_ OP *o) if (kid->op_type != OP_MATCH || kid->op_flags & OPf_STACKED) { OP *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; @@ -5972,11 +6216,10 @@ OP * Perl_ck_join(pTHX_ OP *o) { if (ckWARN(WARN_SYNTAX)) { - OP *kid = cLISTOPo->op_first->op_sibling; + const 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 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); @@ -5986,42 +6229,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) @@ -6036,7 +6243,7 @@ Perl_ck_subr(pTHX_ OP *o) 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) ; @@ -6061,7 +6268,7 @@ Perl_ck_subr(pTHX_ OP *o) o->op_private |= OPpENTERSUB_DB; } else { - delete=1; + delete_op = 1; if (ckWARN(WARN_ASSERTIONS) && !(PL_hints & HINT_ASSERTIONSSEEN)) { Perl_warner(aTHX_ packWARN(WARN_ASSERTIONS), "Impossible to activate assertion call"); @@ -6135,9 +6342,7 @@ Perl_ck_subr(pTHX_ OP *o) OP *sibling = o2->op_sibling; SV *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; @@ -6167,8 +6372,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 != '['); @@ -6251,7 +6456,7 @@ Perl_ck_subr(pTHX_ OP *o) 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)); } @@ -6311,11 +6516,14 @@ 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_opt) @@ -6344,7 +6552,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. */ @@ -6424,7 +6632,7 @@ Perl_peep(pTHX_ register OP *o) 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)) && @@ -6433,6 +6641,8 @@ Perl_peep(pTHX_ register OP *o) i >= 0) { GV *gv; + 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); @@ -6537,7 +6747,7 @@ Perl_peep(pTHX_ register OP *o) 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), @@ -6550,7 +6760,9 @@ Perl_peep(pTHX_ register OP *o) break; case OP_HELEM: { + UNOP *rop; SV *lexname; + GV **fields; SV **svp, *sv; char *key = NULL; STRLEN keylen; @@ -6570,22 +6782,121 @@ Perl_peep(pTHX_ register OP *o) 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(*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(SvSTASH(lexname))); + } + break; } - case OP_SORT: { - /* make @a = sort @a act in-place */ + case OP_HSLICE: { + UNOP *rop; + SV *lexname; + GV **fields; + SV **svp; + 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(*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(SvSTASH(lexname))); + } + } + break; + } + + case OP_SORT: { /* will point to RV2AV or PADAV op on LHS/RHS of assign */ OP *oleft, *oright; OP *o2; - o->op_opt = 1; - /* check that RHS of sort is a single plain array */ 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 *reverse = o->op_next; + + if (reverse->op_type == OP_REVERSE && + (reverse->op_flags & OPf_WANT) == OPf_WANT_LIST) { + OP *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; @@ -6625,6 +6936,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 @@ -6660,9 +6982,97 @@ 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_opt = 1; break; @@ -6672,45 +7082,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. */ @@ -6728,3 +7137,13 @@ const_sv_xsub(pTHX_ CV* cv) ST(0) = (SV*)XSANY.any_ptr; XSRETURN(1); } + +/* + * Local variables: + * c-indentation-style: bsd + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + * + * vim: shiftwidth=4: +*/