In perl.git, the branch blead has been updated <http://perl5.git.perl.org/perl.git/commitdiff/a1b22abd29aa292b3a30da993984fc76d6d2e3aa?hp=2c217c4598fa36f236d5085b4d73b7282b80beb1>
- Log ----------------------------------------------------------------- commit a1b22abd29aa292b3a30da993984fc76d6d2e3aa Author: Father Chrysostomos <[email protected]> Date: Mon Nov 10 20:00:53 2014 -0800 Extend OPpTARGET_MY optimisation to state var init ck_sassign does two things: ⢠See if $lexical = <some op> can have the assignment optimised away (OPpTARGET_MY/targlex). ⢠See if we have state $x = foo, which needs to run only once per closure. The former optimisation is skipped for variable declarations (âmy $x = timeâ), because âmy $xâ does more than just return the SV at a pad offset. It also arranges for it to be cleared on scope exit. That does not apply to state variable. The OPpLVAL_INTRO flag (indicating the presence of âmyâ or âstateâ before the variable) has no run-time effect on state vars, so there is no need to skip the optimisation because of it. That optimisation destroys the assignment operator and its lhs before we get to the state var init code, which needs the lhs to do its checks. So we change the order that these checks happen, and make the state var code invoke the optimisation itself. M lib/B/Deparse.pm M op.c commit 53fd57abab4ef75c406a4b9caf3ddc7f638cae9c Author: Father Chrysostomos <[email protected]> Date: Mon Nov 10 19:33:11 2014 -0800 op.c:ck_sassign: Move targlex to static func ck_sassign does two things: ⢠See if $lexical = <some op> can have the assignment optimised away (targlex). ⢠See if we have state $x = foo, which needs to run only once per closure. Putting the former in a static routine will allow the latter to call it, too, sowe can extend the targlex optimisation to state variable initialization. M op.c commit f511a28d465679812c01f3659928743bef1d3916 Author: Father Chrysostomos <[email protected]> Date: Mon Nov 10 19:15:27 2014 -0800 op.c:ck_sassign: correct comment state $x = time does not have a listop. state $x : nifty = time does. M op.c commit d6ca65d8388b907ff537a8597ee026ad42d5c00f Author: Father Chrysostomos <[email protected]> Date: Mon Nov 10 18:57:45 2014 -0800 op.c:ck_sassign: Donât check the pad name for state The padsv op will already have its state flag set by this point, so we can merge two flag checks into one, resulting in smaller machine code. M op.c ----------------------------------------------------------------------- Summary of changes: lib/B/Deparse.pm | 4 +++- op.c | 34 ++++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm index 67d847e..716e671 100644 --- a/lib/B/Deparse.pm +++ b/lib/B/Deparse.pm @@ -3215,7 +3215,9 @@ sub pp_once { my $cond = $op->first; my $true = $cond->sibling; - return $self->deparse($true, $cx); + my $ret = $self->deparse($true, $cx); + $ret =~ s/^(\(?)\$/$1 . $self->keyword("state") . ' $'/e; + $ret; } sub loop_common { diff --git a/op.c b/op.c index 6042650..159296a 100644 --- a/op.c +++ b/op.c @@ -10139,14 +10139,11 @@ Perl_ck_smartmatch(pTHX_ OP *o) } -OP * -Perl_ck_sassign(pTHX_ OP *o) +static OP * +S_maybe_targlex(pTHX_ OP *o) { dVAR; OP * const kid = cLISTOPo->op_first; - - PERL_ARGS_ASSERT_CK_SASSIGN; - /* has a disposable target? */ if ((PL_opargs[kid->op_type] & OA_TARGLEX) && !(kid->op_flags & OPf_STACKED) @@ -10158,7 +10155,8 @@ Perl_ck_sassign(pTHX_ OP *o) /* Can just relocate the target. */ if (kkid && kkid->op_type == OP_PADSV - && !(kkid->op_private & OPpLVAL_INTRO)) + && (!(kkid->op_private & OPpLVAL_INTRO) + || kkid->op_private & OPpPAD_STATE)) { kid->op_targ = kkid->op_targ; kkid->op_targ = 0; @@ -10170,23 +10168,35 @@ Perl_ck_sassign(pTHX_ OP *o) return kid; } } + return o; +} + +OP * +Perl_ck_sassign(pTHX_ OP *o) +{ + dVAR; + OP * const kid = cLISTOPo->op_first; + + PERL_ARGS_ASSERT_CK_SASSIGN; + if (OP_HAS_SIBLING(kid)) { OP *kkid = OP_SIBLING(kid); - /* For state variable assignment, kkid is a list op whose op_last - is a padsv. */ + /* For state variable assignment with attributes, kkid is a list op + whose op_last is a padsv. */ if ((kkid->op_type == OP_PADSV || (OP_TYPE_IS_OR_WAS(kkid, OP_LIST) && (kkid = cLISTOPx(kkid)->op_last)->op_type == OP_PADSV ) ) - && (kkid->op_private & OPpLVAL_INTRO) - && SvPAD_STATE(PAD_COMPNAME_SV(kkid->op_targ))) { + && (kkid->op_private & (OPpLVAL_INTRO|OPpPAD_STATE)) + == (OPpLVAL_INTRO|OPpPAD_STATE)) { const PADOFFSET target = kkid->op_targ; OP *const other = newOP(OP_PADSV, kkid->op_flags | ((kkid->op_private & ~OPpLVAL_INTRO) << 8)); OP *const first = newOP(OP_NULL, 0); - OP *const nullop = newCONDOP(0, first, o, other); + OP *const nullop = + newCONDOP(0, first, S_maybe_targlex(aTHX_ o), other); OP *const condop = first->op_next; CHANGE_TYPE(condop, OP_ONCE); @@ -10202,7 +10212,7 @@ Perl_ck_sassign(pTHX_ OP *o) return nullop; } } - return o; + return S_maybe_targlex(aTHX_ o); } OP * -- Perl5 Master Repository
