X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/87ebf1e3df9537a204b21f0405c6e60f2acdcc47..61b16eb90f32a2433d6de43e477a03b8d9fed039:/op.c diff --git a/op.c b/op.c index 2a76ae4..72c6809 100644 --- a/op.c +++ b/op.c @@ -297,9 +297,11 @@ Perl_Slab_Alloc(pTHX_ size_t sz) DEBUG_S_warn((aTHX_ "allocating op at %p, slab %p", (void*)o, (void*)slab)); gotit: - /* lastsib == 1, op_sibling == 0 implies a solitary unattached op */ - o->op_lastsib = 1; - assert(!o->op_sibling); +#ifdef PERL_OP_PARENT + /* moresib == 0, op_sibling == 0 implies a solitary unattached op */ + assert(!o->op_moresib); + assert(!o->op_sibparent); +#endif return (void *)o; } @@ -400,7 +402,7 @@ Perl_opslab_free(pTHX_ OPSLAB *slab) PERL_UNUSED_CONTEXT; DEBUG_S_warn((aTHX_ "freeing slab %p", (void*)slab)); assert(slab->opslab_refcnt == 1); - for (; slab; slab = slab2) { + do { slab2 = slab->opslab_next; #ifdef DEBUGGING slab->opslab_refcnt = ~(size_t)0; @@ -415,7 +417,8 @@ Perl_opslab_free(pTHX_ OPSLAB *slab) #else PerlMemShared_free(slab); #endif - } + slab = slab2; + } while (slab); } void @@ -507,7 +510,7 @@ Perl_op_refcnt_dec(pTHX_ OP *o) #define RETURN_UNLIMITED_NUMBER (PERL_INT_MAX / 2) -#define CHANGE_TYPE(o,type) \ +#define OpTYPE_set(o,type) \ STMT_START { \ o->op_type = (OPCODE)type; \ o->op_ppaddr = PL_ppaddr[type]; \ @@ -1180,7 +1183,7 @@ Perl_op_null(pTHX_ OP *o) return; op_clear(o); o->op_targ = o->op_type; - CHANGE_TYPE(o, OP_NULL); + OpTYPE_set(o, OP_NULL); } void @@ -1208,32 +1211,33 @@ Perl_op_refcnt_unlock(pTHX) =for apidoc op_sibling_splice A general function for editing the structure of an existing chain of -op_sibling nodes. By analogy with the perl-level splice() function, allows +op_sibling nodes. By analogy with the perl-level C function, allows you to delete zero or more sequential nodes, replacing them with zero or more different nodes. Performs the necessary op_first/op_last housekeeping on the parent node and op_sibling manipulation on the children. The last deleted node will be marked as as the last node by -updating the op_sibling or op_lastsib field as appropriate. +updating the op_sibling/op_sibparent or op_moresib field as appropriate. Note that op_next is not manipulated, and nodes are not freed; that is the responsibility of the caller. It also won't create a new list op for an empty list etc; use higher-level functions like op_append_elem() for that. -parent is the parent node of the sibling chain. +C is the parent node of the sibling chain. It may passed as C if +the splicing doesn't affect the first or last op in the chain. -start is the node preceding the first node to be spliced. Node(s) +C is the node preceding the first node to be spliced. Node(s) following it will be deleted, and ops will be inserted after it. If it is -NULL, the first node onwards is deleted, and nodes are inserted at the +C, the first node onwards is deleted, and nodes are inserted at the beginning. -del_count is the number of nodes to delete. If zero, no nodes are deleted. +C is the number of nodes to delete. If zero, no nodes are deleted. If -1 or greater than or equal to the number of remaining kids, all remaining kids are deleted. -insert is the first of a chain of nodes to be inserted in place of the nodes. -If NULL, no nodes are inserted. +C is the first of a chain of nodes to be inserted in place of the nodes. +If C, no nodes are inserted. -The head of the chain of deleted ops is returned, or NULL if no ops were +The head of the chain of deleted ops is returned, or C if no ops were deleted. For example: @@ -1257,18 +1261,27 @@ For example: splice(P, B, 0, X-Y) | | NULL A-B-C-D A-B-X-Y-C-D + +For lower-level direct manipulation of C and C, +see C>, C>, C>. + =cut */ OP * Perl_op_sibling_splice(OP *parent, OP *start, int del_count, OP* insert) { - OP *first = start ? OpSIBLING(start) : cLISTOPx(parent)->op_first; + OP *first; OP *rest; OP *last_del = NULL; OP *last_ins = NULL; - PERL_ARGS_ASSERT_OP_SIBLING_SPLICE; + if (start) + first = OpSIBLING(start); + else if (!parent) + goto no_parent; + else + first = cLISTOPx(parent)->op_first; assert(del_count >= -1); @@ -1277,8 +1290,7 @@ Perl_op_sibling_splice(OP *parent, OP *start, int del_count, OP* insert) while (--del_count && OpHAS_SIBLING(last_del)) last_del = OpSIBLING(last_del); rest = OpSIBLING(last_del); - OpSIBLING_set(last_del, NULL); - last_del->op_lastsib = 1; + OpLASTSIB_set(last_del, NULL); } else rest = first; @@ -1287,17 +1299,17 @@ Perl_op_sibling_splice(OP *parent, OP *start, int del_count, OP* insert) last_ins = insert; while (OpHAS_SIBLING(last_ins)) last_ins = OpSIBLING(last_ins); - OpSIBLING_set(last_ins, rest); - last_ins->op_lastsib = rest ? 0 : 1; + OpMAYBESIB_set(last_ins, rest, NULL); } else insert = rest; if (start) { - OpSIBLING_set(start, insert); - start->op_lastsib = insert ? 0 : 1; + OpMAYBESIB_set(start, insert, NULL); } else { + if (!parent) + goto no_parent; cLISTOPx(parent)->op_first = insert; if (insert) parent->op_flags |= OPf_KIDS; @@ -1307,12 +1319,25 @@ Perl_op_sibling_splice(OP *parent, OP *start, int del_count, OP* insert) if (!rest) { /* update op_last etc */ - U32 type = parent->op_type; + U32 type; OP *lastop; - if (type == OP_NULL) - type = parent->op_targ; - type = PL_opargs[type] & OA_CLASS_MASK; + if (!parent) + goto no_parent; + + /* ought to use OP_CLASS(parent) here, but that can't handle + * ex-foo OP_NULL ops. Also note that XopENTRYCUSTOM() can't + * either */ + type = parent->op_type; + if (type == OP_CUSTOM) { + dTHX; + type = XopENTRYCUSTOM(parent, xop_class); + } + else { + if (type == OP_NULL) + type = parent->op_targ; + type = PL_opargs[type] & OA_CLASS_MASK; + } lastop = last_ins ? last_ins : start ? start : NULL; if ( type == OA_BINOP @@ -1322,22 +1347,23 @@ Perl_op_sibling_splice(OP *parent, OP *start, int del_count, OP* insert) ) cLISTOPx(parent)->op_last = lastop; - if (lastop) { - lastop->op_lastsib = 1; -#ifdef PERL_OP_PARENT - lastop->op_sibling = parent; -#endif - } + if (lastop) + OpLASTSIB_set(lastop, parent); } return last_del ? first : NULL; + + no_parent: + Perl_croak_nocontext("panic: op_sibling_splice(): NULL parent"); } + +#ifdef PERL_OP_PARENT + /* =for apidoc op_parent -returns the parent OP of o, if it has a parent. Returns NULL otherwise. -(Currently perl must be built with C<-DPERL_OP_PARENT> for this feature to -work. +Returns the parent OP of C, if it has a parent. Returns C otherwise. +This function is only available on perls built with C<-DPERL_OP_PARENT>. =cut */ @@ -1346,16 +1372,13 @@ OP * Perl_op_parent(OP *o) { PERL_ARGS_ASSERT_OP_PARENT; -#ifdef PERL_OP_PARENT while (OpHAS_SIBLING(o)) o = OpSIBLING(o); - return o->op_sibling; -#else - PERL_UNUSED_ARG(o); - return NULL; -#endif + return o->op_sibparent; } +#endif + /* replace the sibling following start with a new UNOP, which becomes * the parent of the original sibling; e.g. @@ -1401,18 +1424,14 @@ S_alloc_LOGOP(pTHX_ I32 type, OP *first, OP* other) LOGOP *logop; OP *kid = first; NewOp(1101, logop, 1, LOGOP); - CHANGE_TYPE(logop, type); + OpTYPE_set(logop, type); logop->op_first = first; logop->op_other = other; logop->op_flags = OPf_KIDS; while (kid && OpHAS_SIBLING(kid)) kid = OpSIBLING(kid); - if (kid) { - kid->op_lastsib = 1; -#ifdef PERL_OP_PARENT - kid->op_sibling = (OP*)logop; -#endif - } + if (kid) + OpLASTSIB_set(kid, (OP*)logop); return logop; } @@ -1423,7 +1442,7 @@ S_alloc_LOGOP(pTHX_ I32 type, OP *first, OP* other) =for apidoc Am|OP *|op_contextualize|OP *o|I32 context Applies a syntactic context to an op tree representing an expression. -I is the op tree, and I must be C, C, +C is the op tree, and C must be C, C, or C to specify the context to apply. The modified op tree is returned. @@ -1601,9 +1620,6 @@ S_scalar_slice_warning(pTHX_ const OP *o) case OP_LOCALTIME: case OP_GMTIME: case OP_ENTEREVAL: - case OP_REACH: - case OP_RKEYS: - case OP_RVALUES: return; } @@ -1970,19 +1986,19 @@ Perl_scalarvoid(pTHX_ OP *arg) break; case OP_POSTINC: - CHANGE_TYPE(o, OP_PREINC); /* pre-increment is faster */ + OpTYPE_set(o, OP_PREINC); /* pre-increment is faster */ break; case OP_POSTDEC: - CHANGE_TYPE(o, OP_PREDEC); /* pre-decrement is faster */ + OpTYPE_set(o, OP_PREDEC); /* pre-decrement is faster */ break; case OP_I_POSTINC: - CHANGE_TYPE(o, OP_I_PREINC); /* pre-increment is faster */ + OpTYPE_set(o, OP_I_PREINC); /* pre-increment is faster */ break; case OP_I_POSTDEC: - CHANGE_TYPE(o, OP_I_PREDEC); /* pre-decrement is faster */ + OpTYPE_set(o, OP_I_PREDEC); /* pre-decrement is faster */ break; case OP_SASSIGN: { @@ -2039,9 +2055,9 @@ Perl_scalarvoid(pTHX_ OP *arg) if (kid->op_type == OP_NOT && (kid->op_flags & OPf_KIDS)) { if (o->op_type == OP_AND) { - CHANGE_TYPE(o, OP_OR); + OpTYPE_set(o, OP_OR); } else { - CHANGE_TYPE(o, OP_AND); + OpTYPE_set(o, OP_AND); } op_null(kid); } @@ -2349,7 +2365,7 @@ S_check_hash_fields_and_hekify(pTHX_ UNOP *rop, SVOP *key_op) This function finalizes the optree. Should be called directly after the complete optree is built. It does some additional -checking which can't be done in the normal ck_xxx functions and makes +checking which can't be done in the normal Cxxx functions and makes the tree thread-safe. =cut @@ -2509,9 +2525,9 @@ S_finalize_op(pTHX_ OP* o) #ifdef DEBUGGING /* check that op_last points to the last sibling, and that - * the last op_sibling field points back to the parent, and - * that the only ops with KIDS are those which are entitled to - * them */ + * the last op_sibling/op_sibparent field points back to the + * parent, and that the only ops with KIDS are those which are + * entitled to them */ U32 type = o->op_type; U32 family; bool has_last; @@ -2550,17 +2566,11 @@ S_finalize_op(pTHX_ OP* o) if (!OpHAS_SIBLING(kid)) { if (has_last) assert(kid == cLISTOPo->op_last); - assert(kid->op_sibling == o); + assert(kid->op_sibparent == o); } # else - if (OpHAS_SIBLING(kid)) { - assert(!kid->op_lastsib); - } - else { - assert(kid->op_lastsib); - if (has_last) - assert(kid == cLISTOPo->op_last); - } + if (has_last && !OpHAS_SIBLING(kid)) + assert(kid == cLISTOPo->op_last); # endif } #endif @@ -2574,14 +2584,14 @@ S_finalize_op(pTHX_ OP* o) =for apidoc Amx|OP *|op_lvalue|OP *o|I32 type Propagate lvalue ("modifiable") context to an op and its children. -I represents the context type, roughly based on the type of op that -would do the modifying, although C is represented by OP_NULL, +C represents the context type, roughly based on the type of op that +would do the modifying, although C is represented by C, because it has no op type of its own (it is signalled by a flag on the lvalue op). This function detects things that can't be modified, such as C<$x+1>, and generates errors for them. For example, C<$x+1 = 2> would cause it to be -called with an op of type OP_ADD and a C argument of OP_SASSIGN. +called with an op of type C and a C argument of C. It also flags things that need to behave specially in an lvalue context, such as C<$$x = 5> which might have to vivify a reference in C<$x>. @@ -2643,7 +2653,7 @@ S_lvref(pTHX_ OP *o, I32 type) return; } slurpy: - CHANGE_TYPE(o, OP_LVAVREF); + OpTYPE_set(o, OP_LVAVREF); o->op_private &= OPpLVAL_INTRO|OPpPAD_STATE; o->op_flags |= OPf_MOD|OPf_REF; return; @@ -2653,7 +2663,7 @@ S_lvref(pTHX_ OP *o, I32 type) case OP_RV2CV: kid = cUNOPo->op_first; if (kid->op_type == OP_NULL) - kid = cUNOPx(kUNOP->op_first->op_sibling) + kid = cUNOPx(OpSIBLING(kUNOP->op_first)) ->op_first; o->op_private = OPpLVREF_CV; if (kid->op_type == OP_GV) @@ -2700,7 +2710,7 @@ S_lvref(pTHX_ OP *o, I32 type) break; case OP_ASLICE: case OP_HSLICE: - CHANGE_TYPE(o, OP_LVREFSLICE); + OpTYPE_set(o, OP_LVREFSLICE); o->op_private &= OPpLVAL_INTRO|OPpLVREF_ELEM; return; case OP_NULL: @@ -2731,9 +2741,8 @@ S_lvref(pTHX_ OP *o, I32 type) ? "do block" : OP_DESC(o), PL_op_desc[type])); - return; } - CHANGE_TYPE(o, OP_LVREF); + OpTYPE_set(o, OP_LVREF); o->op_private &= OPpLVAL_INTRO|OPpLVREF_ELEM|OPpLVREF_TYPE|OPpPAD_STATE; if (type == OP_ENTERLOOP) @@ -2772,7 +2781,7 @@ Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags) case OP_ENTERSUB: if ((type == OP_UNDEF || type == OP_REFGEN || type == OP_LOCK) && !(o->op_flags & OPf_STACKED)) { - CHANGE_TYPE(o, OP_RV2CV); /* entersub => rv2cv */ + OpTYPE_set(o, OP_RV2CV); /* entersub => rv2cv */ assert(cUNOPo->op_first->op_type == OP_NULL); op_null(((LISTOP*)cUNOPo->op_first)->op_first);/* disable pushmark */ break; @@ -2986,7 +2995,6 @@ Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags) break; case OP_KEYS: - case OP_RKEYS: if (type != OP_SASSIGN && type != OP_LEAVESUBLV) goto nomod; goto lvalue_func; @@ -3237,14 +3245,14 @@ Perl_doref(pTHX_ OP *o, I32 type, bool set_op_ref) PERL_ARGS_ASSERT_DOREF; - if (!o || (PL_parser && PL_parser->error_count)) + if (PL_parser && PL_parser->error_count) return o; switch (o->op_type) { case OP_ENTERSUB: if ((type == OP_EXISTS || type == OP_DEFINED) && !(o->op_flags & OPf_STACKED)) { - CHANGE_TYPE(o, OP_RV2CV); /* entersub => rv2cv */ + OpTYPE_set(o, OP_RV2CV); /* entersub => rv2cv */ assert(cUNOPo->op_first->op_type == OP_NULL); op_null(((LISTOP*)cUNOPo->op_first)->op_first); /* disable pushmark */ o->op_flags |= OPf_SPECIAL; @@ -3356,24 +3364,26 @@ S_dup_attrlist(pTHX_ OP *o) STATIC void S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs) { - SV * const stashsv = stash ? newSVhek(HvNAME_HEK(stash)) : &PL_sv_no; - PERL_ARGS_ASSERT_APPLY_ATTRS; + { + SV * const stashsv = newSVhek(HvNAME_HEK(stash)); - /* fake up C */ + /* fake up C */ #define ATTRSMODULE "attributes" #define ATTRSMODULE_PM "attributes.pm" - Perl_load_module(aTHX_ PERL_LOADMOD_IMPORT_OPS, - newSVpvs(ATTRSMODULE), - NULL, - op_prepend_elem(OP_LIST, - newSVOP(OP_CONST, 0, stashsv), - op_prepend_elem(OP_LIST, - newSVOP(OP_CONST, 0, - newRV(target)), - dup_attrlist(attrs)))); + Perl_load_module( + aTHX_ PERL_LOADMOD_IMPORT_OPS, + newSVpvs(ATTRSMODULE), + NULL, + op_prepend_elem(OP_LIST, + newSVOP(OP_CONST, 0, stashsv), + op_prepend_elem(OP_LIST, + newSVOP(OP_CONST, 0, + newRV(target)), + dup_attrlist(attrs)))); + } } STATIC void @@ -3404,7 +3414,7 @@ S_apply_attrs_my(pTHX_ HV *stash, OP *target, OP *attrs, OP **imopsp) pack = newSVOP(OP_CONST, 0, newSVpvs(ATTRSMODULE)); /* Build up the real arg-list. */ - stashsv = stash ? newSVhek(HvNAME_HEK(stash)) : &PL_sv_no; + stashsv = newSVhek(HvNAME_HEK(stash)); arg = newOP(OP_PADSV, 0); arg->op_targ = target->op_targ; @@ -3412,7 +3422,7 @@ S_apply_attrs_my(pTHX_ HV *stash, OP *target, OP *attrs, OP **imopsp) newSVOP(OP_CONST, 0, stashsv), op_prepend_elem(OP_LIST, newUNOP(OP_REFGEN, 0, - op_lvalue(arg, OP_REFGEN)), + arg), dup_attrlist(attrs))); /* Fake up a method call to import */ @@ -3827,11 +3837,11 @@ Perl_op_scope(pTHX_ OP *o) if (o) { if (o->op_flags & OPf_PARENS || PERLDB_NOOPT || TAINTING_get) { o = op_prepend_elem(OP_LINESEQ, newOP(OP_ENTER, 0), o); - CHANGE_TYPE(o, OP_LEAVE); + OpTYPE_set(o, OP_LEAVE); } else if (o->op_type == OP_LINESEQ) { OP *kid; - CHANGE_TYPE(o, OP_SCOPE); + OpTYPE_set(o, OP_SCOPE); kid = ((LISTOP*)o)->op_first; if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) { op_null(kid); @@ -3895,9 +3905,9 @@ Perl_block_start(pTHX_ int full) /* =for apidoc Am|OP *|block_end|I32 floor|OP *seq -Handles compile-time scope exit. I +Handles compile-time scope exit. C is the savestack index returned by -C, and I is the body of the block. Returns the block, +C, and C is the body of the block. Returns the block, possibly modified. =cut @@ -4414,7 +4424,7 @@ S_gen_constant_list(pTHX_ OP *o) Perl_pp_anonlist(aTHX); PL_tmps_floor = oldtmps_floor; - CHANGE_TYPE(o, OP_RV2AV); + OpTYPE_set(o, 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_opt = 0; /* needs to be revisited in rpeep() */ @@ -4445,10 +4455,10 @@ S_gen_constant_list(pTHX_ OP *o) =for apidoc Am|OP *|op_append_elem|I32 optype|OP *first|OP *last Append an item to the list of ops contained directly within a list-type -op, returning the lengthened list. I is the list-type op, -and I is the op to append to the list. I specifies the -intended opcode for the list. If I is not already a list of the -right type, it will be upgraded into one. If either I or I +op, returning the lengthened list. C is the list-type op, +and C is the op to append to the list. C specifies the +intended opcode for the list. If C is not already a list of the +right type, it will be upgraded into one. If either C or C is null, the other is returned unchanged. =cut @@ -4478,10 +4488,10 @@ Perl_op_append_elem(pTHX_ I32 type, OP *first, OP *last) =for apidoc Am|OP *|op_append_list|I32 optype|OP *first|OP *last Concatenate the lists of ops contained directly within two list-type ops, -returning the combined list. I and I are the list-type ops -to concatenate. I specifies the intended opcode for the list. -If either I or I is not already a list of the right type, -it will be upgraded into one. If either I or I is null, +returning the combined list. C and C are the list-type ops +to concatenate. C specifies the intended opcode for the list. +If either C or C is not already a list of the right type, +it will be upgraded into one. If either C or C is null, the other is returned unchanged. =cut @@ -4502,16 +4512,11 @@ Perl_op_append_list(pTHX_ I32 type, OP *first, OP *last) if (last->op_type != (unsigned)type) return op_append_elem(type, first, last); - ((LISTOP*)first)->op_last->op_lastsib = 0; - OpSIBLING_set(((LISTOP*)first)->op_last, ((LISTOP*)last)->op_first); + OpMORESIB_set(((LISTOP*)first)->op_last, ((LISTOP*)last)->op_first); ((LISTOP*)first)->op_last = ((LISTOP*)last)->op_last; - ((LISTOP*)first)->op_last->op_lastsib = 1; -#ifdef PERL_OP_PARENT - ((LISTOP*)first)->op_last->op_sibling = first; -#endif + OpLASTSIB_set(((LISTOP*)first)->op_last, first); first->op_flags |= (last->op_flags & OPf_KIDS); - S_op_destroy(aTHX_ last); return first; @@ -4521,10 +4526,10 @@ Perl_op_append_list(pTHX_ I32 type, OP *first, OP *last) =for apidoc Am|OP *|op_prepend_elem|I32 optype|OP *first|OP *last Prepend an item to the list of ops contained directly within a list-type -op, returning the lengthened list. I is the op to prepend to the -list, and I is the list-type op. I specifies the intended -opcode for the list. If I is not already a list of the right type, -it will be upgraded into one. If either I or I is null, +op, returning the lengthened list. C is the op to prepend to the +list, and C is the list-type op. C specifies the intended +opcode for the list. If C is not already a list of the right type, +it will be upgraded into one. If either C or C is null, the other is returned unchanged. =cut @@ -4558,8 +4563,8 @@ Perl_op_prepend_elem(pTHX_ I32 type, OP *first, OP *last) /* =for apidoc Am|OP *|op_convert_list|I32 type|I32 flags|OP *o -Converts I into a list op if it is not one already, and then converts it -into the specified I, calling its check function, allocating a target if +Converts C into a list op if it is not one already, and then converts it +into the specified C, calling its check function, allocating a target if it needs one, and folding constants. A list-type op is usually constructed one kid at a time via C, @@ -4577,7 +4582,10 @@ Perl_op_convert_list(pTHX_ I32 type, I32 flags, OP *o) if (!o || o->op_type != OP_LIST) o = force_list(o, 0); else + { o->op_flags &= ~OPf_WANT; + o->op_private &= ~OPpLVAL_INTRO; + } if (!(PL_opargs[type] & OA_MARK)) op_null(cLISTOPo->op_first); @@ -4589,7 +4597,7 @@ Perl_op_convert_list(pTHX_ I32 type, I32 flags, OP *o) } } - CHANGE_TYPE(o, type); + OpTYPE_set(o, type); o->op_flags |= flags; if (flags & OPf_FOLDED) o->op_folded = 1; @@ -4642,8 +4650,7 @@ S_force_list(pTHX_ OP *o, bool nullit) if (o) { /* manually detach any siblings then add them back later */ rest = OpSIBLING(o); - OpSIBLING_set(o, NULL); - o->op_lastsib = 1; + OpLASTSIB_set(o, NULL); } o = newLISTOP(OP_LIST, 0, o, NULL); if (rest) @@ -4657,16 +4664,16 @@ S_force_list(pTHX_ OP *o, bool nullit) /* =for apidoc Am|OP *|newLISTOP|I32 type|I32 flags|OP *first|OP *last -Constructs, checks, and returns an op of any list type. I is -the opcode. I gives the eight bits of C, except that -C will be set automatically if required. I and I +Constructs, checks, and returns an op of any list type. C is +the opcode. C gives the eight bits of C, except that +C will be set automatically if required. C and C supply up to two ops to be direct children of the list op; they are consumed by this function and become part of the constructed op tree. For most list operators, the check function expects all the kid ops to be -present already, so calling C (e.g.,) is not +present already, so calling C (e.g.) is not appropriate. What you want to do in that case is create an op of type -OP_LIST, append more children to it, and then call L. +C, append more children to it, and then call L. See L for more information. @@ -4684,7 +4691,7 @@ Perl_newLISTOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) NewOp(1101, listop, 1, LISTOP); - CHANGE_TYPE(listop, type); + OpTYPE_set(listop, type); if (first || last) flags |= OPf_KIDS; listop->op_flags = (U8)flags; @@ -4694,26 +4701,19 @@ Perl_newLISTOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) else if (!first && last) first = last; else if (first) - OpSIBLING_set(first, last); + OpMORESIB_set(first, last); listop->op_first = first; listop->op_last = last; if (type == OP_LIST) { OP* const pushop = newOP(OP_PUSHMARK, 0); - pushop->op_lastsib = 0; - OpSIBLING_set(pushop, first); + OpMORESIB_set(pushop, first); listop->op_first = pushop; listop->op_flags |= OPf_KIDS; if (!last) listop->op_last = pushop; } - if (first) - first->op_lastsib = 0; - if (listop->op_last) { - listop->op_last->op_lastsib = 1; -#ifdef PERL_OP_PARENT - listop->op_last->op_sibling = (OP*)listop; -#endif - } + if (listop->op_last) + OpLASTSIB_set(listop->op_last, (OP*)listop); return CHECKOP(type, listop); } @@ -4722,7 +4722,7 @@ Perl_newLISTOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) =for apidoc Am|OP *|newOP|I32 type|I32 flags Constructs, checks, and returns an op of any base type (any type that -has no extra fields). I is the opcode. I gives the +has no extra fields). C is the opcode. C gives the eight bits of C, and, shifted up eight bits, the eight bits of C. @@ -4746,7 +4746,7 @@ Perl_newOP(pTHX_ I32 type, I32 flags) || (PL_opargs[type] & OA_CLASS_MASK) == OA_LOOPEXOP); NewOp(1101, o, 1, OP); - CHANGE_TYPE(o, type); + OpTYPE_set(o, type); o->op_flags = (U8)flags; o->op_next = o; @@ -4761,11 +4761,11 @@ Perl_newOP(pTHX_ I32 type, I32 flags) /* =for apidoc Am|OP *|newUNOP|I32 type|I32 flags|OP *first -Constructs, checks, and returns an op of any unary type. I is -the opcode. I gives the eight bits of C, except that +Constructs, checks, and returns an op of any unary type. C is +the opcode. C gives the eight bits of C, except that C will be set automatically if required, and, shifted up eight bits, the eight bits of C, except that the bit with value 1 -is automatically set. I supplies an optional op to be the direct +is automatically set. C supplies an optional op to be the direct child of the unary op; it is consumed by this function and become part of the constructed op tree. @@ -4798,15 +4798,13 @@ Perl_newUNOP(pTHX_ I32 type, I32 flags, OP *first) first = force_list(first, 1); NewOp(1101, unop, 1, UNOP); - CHANGE_TYPE(unop, type); + OpTYPE_set(unop, type); unop->op_first = first; unop->op_flags = (U8)(flags | OPf_KIDS); unop->op_private = (U8)(1 | (flags >> 8)); -#ifdef PERL_OP_PARENT if (!OpHAS_SIBLING(first)) /* true unless weird syntax error */ - first->op_sibling = (OP*)unop; -#endif + OpLASTSIB_set(first, (OP*)unop); unop = (UNOP*) CHECKOP(type, unop); if (unop->op_next) @@ -4818,8 +4816,8 @@ Perl_newUNOP(pTHX_ I32 type, I32 flags, OP *first) /* =for apidoc newUNOP_AUX -Similar to C, but creates an UNOP_AUX struct instead, with op_aux -initialised to aux +Similar to C, but creates an C struct instead, with C +initialised to C =cut */ @@ -4841,10 +4839,8 @@ Perl_newUNOP_AUX(pTHX_ I32 type, I32 flags, OP *first, UNOP_AUX_item *aux) unop->op_private = (U8)((first ? 1 : 0) | (flags >> 8)); unop->op_aux = aux; -#ifdef PERL_OP_PARENT if (first && !OpHAS_SIBLING(first)) /* true unless weird syntax error */ - first->op_sibling = (OP*)unop; -#endif + OpLASTSIB_set(first, (OP*)unop); unop = (UNOP_AUX*) CHECKOP(type, unop); @@ -4855,13 +4851,13 @@ Perl_newUNOP_AUX(pTHX_ I32 type, I32 flags, OP *first, UNOP_AUX_item *aux) =for apidoc Am|OP *|newMETHOP|I32 type|I32 flags|OP *first Constructs, checks, and returns an op of method type with a method name -evaluated at runtime. I is the opcode. I gives the eight +evaluated at runtime. C is the opcode. C gives the eight bits of C, except that C will be set automatically, and, shifted up eight bits, the eight bits of C, except that -the bit with value 1 is automatically set. I supplies an +the bit with value 1 is automatically set. C supplies an op which evaluates method name; it is consumed by this function and become part of the constructed op tree. -Supported optypes: OP_METHOD. +Supported optypes: C. =cut */ @@ -4881,10 +4877,8 @@ S_newMETHOP_internal(pTHX_ I32 type, I32 flags, OP* dynamic_meth, SV* const_meth methop->op_u.op_first = dynamic_meth; methop->op_private = (U8)(1 | (flags >> 8)); -#ifdef PERL_OP_PARENT if (!OpHAS_SIBLING(dynamic_meth)) - dynamic_meth->op_sibling = (OP*)methop; -#endif + OpLASTSIB_set(dynamic_meth, (OP*)methop); } else { assert(const_meth); @@ -4900,7 +4894,7 @@ S_newMETHOP_internal(pTHX_ I32 type, I32 flags, OP* dynamic_meth, SV* const_meth methop->op_rclass_sv = NULL; #endif - CHANGE_TYPE(methop, type); + OpTYPE_set(methop, type); return CHECKOP(type, methop); } @@ -4914,11 +4908,11 @@ Perl_newMETHOP (pTHX_ I32 type, I32 flags, OP* dynamic_meth) { =for apidoc Am|OP *|newMETHOP_named|I32 type|I32 flags|SV *const_meth Constructs, checks, and returns an op of method type with a constant -method name. I is the opcode. I gives the eight bits of +method name. C is the opcode. C gives the eight bits of C, and, shifted up eight bits, the eight bits of -C. I supplies a constant method name; +C. C supplies a constant method name; it must be a shared COW string. -Supported optypes: OP_METHOD_NAMED. +Supported optypes: C. =cut */ @@ -4932,11 +4926,11 @@ Perl_newMETHOP_named (pTHX_ I32 type, I32 flags, SV* const_meth) { /* =for apidoc Am|OP *|newBINOP|I32 type|I32 flags|OP *first|OP *last -Constructs, checks, and returns an op of any binary type. I -is the opcode. I gives the eight bits of C, except +Constructs, checks, and returns an op of any binary type. C +is the opcode. C gives the eight bits of C, except that C will be set automatically, and, shifted up eight bits, the eight bits of C, except that the bit with value 1 or -2 is automatically set as required. I and I supply up to +2 is automatically set as required. C and C supply up to two ops to be the direct children of the binary op; they are consumed by this function and become part of the constructed op tree. @@ -4957,7 +4951,7 @@ Perl_newBINOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) if (!first) first = newOP(OP_NULL, 0); - CHANGE_TYPE(binop, type); + OpTYPE_set(binop, type); binop->op_first = first; binop->op_flags = (U8)(flags | OPf_KIDS); if (!last) { @@ -4966,20 +4960,15 @@ Perl_newBINOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) } else { binop->op_private = (U8)(2 | (flags >> 8)); - OpSIBLING_set(first, last); - first->op_lastsib = 0; + OpMORESIB_set(first, last); } -#ifdef PERL_OP_PARENT if (!OpHAS_SIBLING(last)) /* true unless weird syntax error */ - last->op_sibling = (OP*)binop; -#endif + OpLASTSIB_set(last, (OP*)binop); binop->op_last = OpSIBLING(binop->op_first); -#ifdef PERL_OP_PARENT if (binop->op_last) - binop->op_last->op_sibling = (OP*)binop; -#endif + OpLASTSIB_set(binop->op_last, (OP*)binop); binop = (BINOP*)CHECKOP(type, binop); if (binop->op_next || binop->op_type != (OPCODE)type) @@ -5172,7 +5161,7 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) } } - /* now see which range will peter our first, if either. */ + /* now see which range will peter out first, if either. */ tdiff = tlast - tfirst; rdiff = rlast - rfirst; tcount += tdiff + 1; @@ -5343,7 +5332,7 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) =for apidoc Am|OP *|newPMOP|I32 type|I32 flags Constructs, checks, and returns an op of any pattern matching type. -I is the opcode. I gives the eight bits of C +C is the opcode. C gives the eight bits of C and, shifted up eight bits, the eight bits of C. =cut @@ -5359,7 +5348,7 @@ Perl_newPMOP(pTHX_ I32 type, I32 flags) || type == OP_CUSTOM); NewOp(1101, pmop, 1, PMOP); - CHANGE_TYPE(pmop, type); + OpTYPE_set(pmop, type); pmop->op_flags = (U8)flags; pmop->op_private = (U8)(0 | (flags >> 8)); if (PL_opargs[type] & OA_RETSCALAR) @@ -5784,8 +5773,8 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl, bool isreg, I32 floor) =for apidoc Am|OP *|newSVOP|I32 type|I32 flags|SV *sv Constructs, checks, and returns an op of any type that involves an -embedded SV. I is the opcode. I gives the eight bits -of C. I gives the SV to embed in the op; this function +embedded SV. C is the opcode. C gives the eight bits +of C. C gives the SV to embed in the op; this function takes ownership of one reference to it. =cut @@ -5805,7 +5794,7 @@ Perl_newSVOP(pTHX_ I32 type, I32 flags, SV *sv) || type == OP_CUSTOM); NewOp(1101, svop, 1, SVOP); - CHANGE_TYPE(svop, type); + OpTYPE_set(svop, type); svop->op_sv = sv; svop->op_next = (OP*)svop; svop->op_flags = (U8)flags; @@ -5847,9 +5836,9 @@ Perl_newDEFSVOP(pTHX) =for apidoc Am|OP *|newPADOP|I32 type|I32 flags|SV *sv Constructs, checks, and returns an op of any type that involves a -reference to a pad element. I is the opcode. I gives the +reference to a pad element. C is the opcode. C gives the eight bits of C. A pad slot is automatically allocated, and -is populated with I; this function takes ownership of one reference +is populated with C; this function takes ownership of one reference to it. This function only exists if Perl has been compiled to use ithreads. @@ -5871,7 +5860,7 @@ Perl_newPADOP(pTHX_ I32 type, I32 flags, SV *sv) || type == OP_CUSTOM); NewOp(1101, padop, 1, PADOP); - CHANGE_TYPE(padop, type); + OpTYPE_set(padop, type); padop->op_padix = pad_alloc(type, isGV(sv) ? SVf_READONLY : SVs_PADTMP); SvREFCNT_dec(PAD_SVl(padop->op_padix)); @@ -5892,8 +5881,8 @@ Perl_newPADOP(pTHX_ I32 type, I32 flags, SV *sv) =for apidoc Am|OP *|newGVOP|I32 type|I32 flags|GV *gv Constructs, checks, and returns an op of any type that involves an -embedded reference to a GV. I is the opcode. I gives the -eight bits of C. I identifies the GV that the op should +embedded reference to a GV. C is the opcode. C gives the +eight bits of C. C identifies the GV that the op should reference; calling this function does not transfer ownership of any reference to it. @@ -5916,8 +5905,8 @@ Perl_newGVOP(pTHX_ I32 type, I32 flags, GV *gv) =for apidoc Am|OP *|newPVOP|I32 type|I32 flags|char *pv Constructs, checks, and returns an op of any type that involves an -embedded C-level pointer (PV). I is the opcode. I gives -the eight bits of C. I supplies the C-level pointer, which +embedded C-level pointer (PV). C is the opcode. C gives +the eight bits of C. C supplies the C-level pointer, which must have been allocated using C; the memory will be freed when the op is destroyed. @@ -5938,7 +5927,7 @@ Perl_newPVOP(pTHX_ I32 type, I32 flags, char *pv) || (PL_opargs[type] & OA_CLASS_MASK) == OA_LOOPEXOP); NewOp(1101, pvop, 1, PVOP); - CHANGE_TYPE(pvop, type); + OpTYPE_set(pvop, type); pvop->op_pv = pv; pvop->op_next = (OP*)pvop; pvop->op_flags = (U8)flags; @@ -6116,15 +6105,15 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg) Loads the module whose name is pointed to by the string part of name. Note that the actual module name, not its filename, should be given. Eg, "Foo::Bar" instead of "Foo/Bar.pm". flags can be any of -PERL_LOADMOD_DENY, PERL_LOADMOD_NOIMPORT, or PERL_LOADMOD_IMPORT_OPS +C, C, or C (or 0 for no flags). ver, if specified and not NULL, provides version semantics similar to C. The optional trailing SV* -arguments can be used to specify arguments to the module's import() +arguments can be used to specify arguments to the module's C method, similar to C. They must be -terminated with a final NULL pointer. Note that this list can only -be omitted when the PERL_LOADMOD_NOIMPORT flag has been used. -Otherwise at least a single NULL pointer to designate the default +terminated with a final C pointer. Note that this list can only +be omitted when the C flag has been used. +Otherwise at least a single C pointer to designate the default import list is required. The reference count for each specified C parameter is decremented. @@ -6232,11 +6221,11 @@ Perl_dofile(pTHX_ OP *term, I32 force_builtin) =for apidoc Am|OP *|newSLICEOP|I32 flags|OP *subscript|OP *listval -Constructs, checks, and returns an C (list slice) op. I +Constructs, checks, and returns an C (list slice) op. C gives the eight bits of C, except that C will be set automatically, and, shifted up eight bits, the eight bits of C, except that the bit with value 1 or 2 is automatically -set as required. I and I supply the parameters of +set as required. C and C supply the parameters of the slice; they are consumed by this function and become part of the constructed op tree. @@ -6314,149 +6303,23 @@ S_assignment_type(pTHX_ const OP *o) return ret; } -/* - Helper function for newASSIGNOP to detect commonality between the - lhs and the rhs. (It is actually called very indirectly. newASSIGNOP - flags the op and the peephole optimizer calls this helper function - if the flag is set.) Marks all variables with PL_generation. If it - returns TRUE the assignment must be able to handle common variables. - - PL_generation sorcery: - An assignment like ($a,$b) = ($c,$d) is easier than - ($a,$b) = ($c,$a), since there is no need for temporary vars. - To detect whether there are common vars, the global var - PL_generation is incremented for each assign op we compile. - Then, while compiling the assign op, we run through all the - variables on both sides of the assignment, setting a spare slot - in each of them to PL_generation. If any of them already have - that value, we know we've got commonality. Also, if the - generation number is already set to PERL_INT_MAX, then - the variable is involved in aliasing, so we also have - potential commonality in that case. We could use a - single bit marker, but then we'd have to make 2 passes, first - to clear the flag, then to test and set it. And that - wouldn't help with aliasing, either. To find somewhere - to store these values, evil chicanery is done with SvUVX(). -*/ -PERL_STATIC_INLINE bool -S_aassign_common_vars(pTHX_ OP* o) -{ - OP *curop; - for (curop = cUNOPo->op_first; curop; curop = OpSIBLING(curop)) { - if (PL_opargs[curop->op_type] & OA_DANGEROUS) { - if (curop->op_type == OP_GV || curop->op_type == OP_GVSV - || curop->op_type == OP_AELEMFAST) { - GV *gv = cGVOPx_gv(curop); - if (gv == PL_defgv - || (int)GvASSIGN_GENERATION(gv) == PL_generation) - return TRUE; - GvASSIGN_GENERATION_set(gv, PL_generation); - } - else if (curop->op_type == OP_PADSV || - curop->op_type == OP_PADAV || - curop->op_type == OP_PADHV || - curop->op_type == OP_AELEMFAST_LEX || - curop->op_type == OP_PADANY) - { - padcheck: - if (PAD_COMPNAME_GEN(curop->op_targ) - == (STRLEN)PL_generation - || PAD_COMPNAME_GEN(curop->op_targ) == PERL_INT_MAX) - return TRUE; - PAD_COMPNAME_GEN_set(curop->op_targ, PL_generation); - - } - else if (curop->op_type == OP_RV2CV) - return TRUE; - else if (curop->op_type == OP_RV2SV || - curop->op_type == OP_RV2AV || - curop->op_type == OP_RV2HV || - curop->op_type == OP_RV2GV) { - if (cUNOPx(curop)->op_first->op_type != OP_GV) /* funny deref? */ - return TRUE; - } - else if (curop->op_type == OP_PUSHRE) { - GV *const gv = -#ifdef USE_ITHREADS - ((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff - ? MUTABLE_GV(PAD_SVl(((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff)) - : NULL; -#else - ((PMOP*)curop)->op_pmreplrootu.op_pmtargetgv; -#endif - if (gv) { - if (gv == PL_defgv - || (int)GvASSIGN_GENERATION(gv) == PL_generation) - return TRUE; - GvASSIGN_GENERATION_set(gv, PL_generation); - } - else if (curop->op_targ) - goto padcheck; - } - else if (curop->op_type == OP_PADRANGE) - /* Ignore padrange; checking its siblings is sufficient. */ - continue; - else - return TRUE; - } - else if (PL_opargs[curop->op_type] & OA_TARGLEX - && curop->op_private & OPpTARGET_MY) - goto padcheck; - - if (curop->op_flags & OPf_KIDS) { - if (aassign_common_vars(curop)) - return TRUE; - } - } - return FALSE; -} - -/* This variant only handles lexical aliases. It is called when - newASSIGNOP decides that we don’t have any common vars, as lexical ali- - ases trump that decision. */ -PERL_STATIC_INLINE bool -S_aassign_common_vars_aliases_only(pTHX_ OP *o) -{ - OP *curop; - for (curop = cUNOPo->op_first; curop; curop = OpSIBLING(curop)) { - if ((curop->op_type == OP_PADSV || - curop->op_type == OP_PADAV || - curop->op_type == OP_PADHV || - curop->op_type == OP_AELEMFAST_LEX || - curop->op_type == OP_PADANY || - ( PL_opargs[curop->op_type] & OA_TARGLEX - && curop->op_private & OPpTARGET_MY )) - && PAD_COMPNAME_GEN(curop->op_targ) == PERL_INT_MAX) - return TRUE; - - if (curop->op_type == OP_PUSHRE && curop->op_targ - && PAD_COMPNAME_GEN(curop->op_targ) == PERL_INT_MAX) - return TRUE; - - if (curop->op_flags & OPf_KIDS) { - if (S_aassign_common_vars_aliases_only(aTHX_ curop)) - return TRUE; - } - } - return FALSE; -} /* =for apidoc Am|OP *|newASSIGNOP|I32 flags|OP *left|I32 optype|OP *right -Constructs, checks, and returns an assignment op. I and I +Constructs, checks, and returns an assignment op. C and C supply the parameters of the assignment; they are consumed by this function and become part of the constructed op tree. -If I is C, C, or C, then -a suitable conditional optree is constructed. If I is the opcode +If C is C, C, or C, then +a suitable conditional optree is constructed. If C is the opcode of a binary operator, such as C, then an op is constructed that performs the binary operation and assigns the result to the left argument. -Either way, if I is non-zero then I has no effect. +Either way, if C is non-zero then C has no effect. -If I is zero, then a plain scalar or list assignment is +If C is zero, then a plain scalar or list assignment is constructed. Which type of assignment it is is automatically determined. -I gives the eight bits of C, except that C +C gives the eight bits of C, except that C will be set automatically, and, shifted up eight bits, the eight bits of C, except that the bit with value 1 or 2 is automatically set as required. @@ -6486,7 +6349,6 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) static const char no_list_state[] = "Initialization of state variables" " in list context currently forbidden"; OP *curop; - bool maybe_common_vars = TRUE; if (left->op_type == OP_ASLICE || left->op_type == OP_HSLICE) left->op_private &= ~ OPpSLICEWARNING; @@ -6500,47 +6362,24 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) if (OP_TYPE_IS_OR_WAS(left, OP_LIST)) { OP* lop = ((LISTOP*)left)->op_first; - maybe_common_vars = FALSE; while (lop) { - if (lop->op_type == OP_PADSV || - lop->op_type == OP_PADAV || - lop->op_type == OP_PADHV || - lop->op_type == OP_PADANY) { - if (!(lop->op_private & OPpLVAL_INTRO)) - maybe_common_vars = TRUE; - - if (lop->op_private & OPpPAD_STATE) { - if (left->op_private & OPpLVAL_INTRO) { - /* Each variable in state($a, $b, $c) = ... */ - } - else { - /* Each state variable in - (state $a, my $b, our $c, $d, undef) = ... */ - } - yyerror(no_list_state); - } else { - /* Each my variable in - (state $a, my $b, our $c, $d, undef) = ... */ - } - } else if (lop->op_type == OP_UNDEF || - OP_TYPE_IS_OR_WAS(lop, OP_PUSHMARK)) { - /* undef may be interesting in - (state $a, undef, state $c) */ - } else { - /* Other ops in the list. */ - maybe_common_vars = TRUE; - } + if ((lop->op_type == OP_PADSV || + lop->op_type == OP_PADAV || + lop->op_type == OP_PADHV || + lop->op_type == OP_PADANY) + && (lop->op_private & OPpPAD_STATE) + ) + yyerror(no_list_state); lop = OpSIBLING(lop); } } - else if ((left->op_private & OPpLVAL_INTRO) + else if ( (left->op_private & OPpLVAL_INTRO) + && (left->op_private & OPpPAD_STATE) && ( left->op_type == OP_PADSV || left->op_type == OP_PADAV || left->op_type == OP_PADHV - || left->op_type == OP_PADANY)) - { - if (left->op_type == OP_PADSV) maybe_common_vars = FALSE; - if (left->op_private & OPpPAD_STATE) { + || left->op_type == OP_PADANY) + ) { /* All single variable list context state assignments, hence state ($a) = ... (state $a) = ... @@ -6552,13 +6391,6 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) (state %a) = ... */ yyerror(no_list_state); - } - } - - if (maybe_common_vars) { - /* The peephole optimizer will do the full check and pos- - sibly turn this off. */ - o->op_private |= OPpASSIGN_COMMON; } if (right && right->op_type == OP_SPLIT @@ -6671,13 +6503,13 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) Constructs a state op (COP). The state op is normally a C op, but will be a C op if debugging is enabled for currently-compiled code. The state op is populated from C (or C). -If I