diff options
-rw-r--r-- | op.c | 20 | ||||
-rw-r--r-- | opcode.h | 2 | ||||
-rwxr-xr-x | opcode.pl | 2 |
3 files changed, 21 insertions, 3 deletions
@@ -4715,7 +4715,8 @@ OP * Perl_ck_concat(pTHX_ OP *o) { OP *kid = cUNOPo->op_first; - if (kid->op_type == OP_CONCAT && !(kUNOP->op_first->op_flags & OPf_MOD)) + if (kid->op_type == OP_CONCAT && !(kid->op_private & OPpTARGET_MY) && + !(kUNOP->op_first->op_flags & OPf_MOD)) o->op_flags |= OPf_STACKED; return o; } @@ -6264,6 +6265,23 @@ Perl_peep(pTHX_ register OP *o) o->op_seq = PL_op_seqmax++; break; + case OP_CONCAT: + if (o->op_next && o->op_next->op_type == OP_STRINGIFY) { + if (o->op_next->op_private & OPpTARGET_MY) { + if (o->op_flags & OPf_STACKED) /* chained concats */ + goto ignore_optimization; + else { + /* assert(PL_opargs[o->op_type] & OA_TARGLEX); */ + o->op_targ = o->op_next->op_targ; + o->op_next->op_targ = 0; + o->op_private |= OPpTARGET_MY; + } + } + op_null(o->op_next); + } + ignore_optimization: + o->op_seq = PL_op_seqmax++; + break; case OP_STUB: if ((o->op_flags & OPf_WANT) != OPf_WANT_LIST) { o->op_seq = PL_op_seqmax++; @@ -1544,7 +1544,7 @@ EXT U32 PL_opargs[] = { 0x0002251e, /* i_add */ 0x0002252e, /* subtract */ 0x0002251e, /* i_subtract */ - 0x0002240e, /* concat */ + 0x0002250e, /* concat */ 0x0000290e, /* stringify */ 0x0002250e, /* left_shift */ 0x0002250e, /* right_shift */ @@ -537,7 +537,7 @@ add addition (+) ck_null IfsT2 S S i_add integer addition (+) ck_null ifsT2 S S subtract subtraction (-) ck_null IfsT2 S S i_subtract integer subtraction (-) ck_null ifsT2 S S -concat concatenation (.) or string ck_concat fst2 S S +concat concatenation (.) or string ck_concat fsT2 S S stringify string ck_fun fsT@ S left_shift left bitshift (<<) ck_bitop fsT2 S S |