In perl.git, the branch smoke-me/davem/aassign2 has been created

<http://perl5.git.perl.org/perl.git/commitdiff/91ad8c5bbd551964293aee599c51d2b25b38aa8b?hp=0000000000000000000000000000000000000000>

        at  91ad8c5bbd551964293aee599c51d2b25b38aa8b (commit)

- Log -----------------------------------------------------------------
commit 91ad8c5bbd551964293aee599c51d2b25b38aa8b
Author: David Mitchell <[email protected]>
Date:   Fri Aug 14 09:23:59 2015 +0100

    fix a SV_NOSTEAL issue in pp_aassign
    
    in something like (...) = (f())[0,0]
    
    A mortal SV can appear multiple times on the RHS without being reference
    counted. If it's a string, the temptation is to steal its string buffer
    during the first copy; but this would make the second usage undef.
    
    pp_aassign() already takes account of this and uses the SV_NOSTEAL
    flag when copying - except that one common code path didn't.
    
    This commit fixes that, adds more tests, and adds more code comments
    to explain the issue.

M       pp_hot.c
M       t/op/aassign.t

commit 244c20f18c60b7001424d45c7da400117eaaa36b
Author: David Mitchell <[email protected]>
Date:   Thu Aug 13 12:26:06 2015 +0100

    fix PAD_COMPNAME_GEN documentation
    
    The generation number is no longer stored in the SvUVX() field

M       pad.h

commit b7bf2f4a47259cda6fea2eaf91d12b48aa41dfd5
Author: David Mitchell <[email protected]>
Date:   Thu Aug 13 12:21:54 2015 +0100

    document what PL_generation is for

M       intrpvar.h

commit 51f2098c83b9fd9beb50041d1843b391cbd74159
Author: David Mitchell <[email protected]>
Date:   Thu Aug 13 12:07:38 2015 +0100

    Eliminate GvASSIGN_GENERATION and _set macros
    
    Since we no longer scan package vars with PL_generation for
    OPpASSIGN_COMMON* purposes, eliminate the macros used for that purpose.

M       gv.h

commit a4003efc0278de80c3d8b67bc9e534783647bd40
Author: David Mitchell <[email protected]>
Date:   Thu Aug 13 17:00:32 2015 +0100

    Optimise 1 arg in list assign
    
    Avoid setting common scalar flags in these cases:
    
    ($x) = (...);
    (...) = ($x);

M       op.c
M       t/op/aassign.t
M       t/perf/benchmarks
M       t/perf/optree.t

commit 2894ec506b2f3a55975d11253aab9470f350d063
Author: David Mitchell <[email protected]>
Date:   Tue Aug 11 16:21:07 2015 +0100

    Eliminate PL_sawalias, GPf_ALIASED_SV
    
    These two commits:
    
        v5.21.3-759-gff2a62e "Skip no-common-vars optimisation for aliases"
        v5.21.4-210-gc997e36 "Make list assignment respect foreach aliasing"
    
    added a run-time mechanism to detect aliased package variables,
    by either "*pkg = ...," or "for $pkg (...)", and used that information
    to enable the OPpASSIGN_COMMON mechanism at runtime for detecting common
    elements in a list assign, e.g.
    
        for $alias ($a, ...) {
            ($a,$b) = (1,$alias);
        }
    
    The previous commit but one changed the OPpASSIGN_COMMON mechanism such
    that it no longer uses PL_sawalias. So this var and the mechanism for
    setting it can now be removed.
    
    This commit removes:
    
        * the PL_sawalias variable
        * the GPf_ALIASED_SV GP flag
        * the SAVEt_GP_ALIASED_SV and save_aliased_sv() save type.

M       dump.c
M       embed.fnc
M       embed.h
M       embedvar.h
M       ext/B/t/b.t
M       gv.h
M       intrpvar.h
M       pp_ctl.c
M       pp_hot.c
M       proto.h
M       scope.c
M       scope.h
M       sv.c

commit ac5bf54e891898ba517a7e555da2ee329767d1f5
Author: David Mitchell <[email protected]>
Date:   Thu Aug 13 15:01:23 2015 +0100

    make my (...) = @_ non-OPpASSIGN_COMMON_RC1
    
    Technically in
    
        my ($scalar,...) = @_
    
    due to closure/goto tricks, its possible for $scalar to appear on both
    the LHS and RHS, so we currently set the OPpASSIGN_COMMON_RC1 flag.
    
    However, this imposes extra overhead; for example 5% extra instruction
    reads and 11% extra conditional branches for
    
        my ($x,$y,$z) = @_;
    
    Given what an important construct this is, disable this flag in the
    specific case of of only my's on the LHS and only @_ on the RHS.
    It's technically incorrect, but its the same behaviour we've always had
    (it was only the previous commit which made it safe but slower).
    
    We still set the OPpASSIGN_COMMON_AGG flag for
    
        my ($...,@a) = @_
    
    since in the normal case this only adds the small additional runtime
    overhead of checking that @a is already empty.

M       ext/B/t/optree_misc.t
M       op.c
M       t/op/aassign.t
M       t/perf/optree.t

commit bacd737fbd8017d34b4c621a944d45f87560b142
Author: David Mitchell <[email protected]>
Date:   Thu Aug 13 10:32:42 2015 +0100

    re-implement OPpASSIGN_COMMON mechanism
    
    This commit almost completely replaces the current mechanism
    for detecting and handing common vars in list assignment, e.g.
    
        ($a,$b) = ($b,$a);
    
    In general outline: it creates more false positives at compile-time
    than before, but also no longer misses some false negatives. In
    compensation, it considerably reduces the run-time cost of handling
    potential and real commonality.
    
    It does this firstly by splitting the OPpASSIGN_COMMON flag into 3
    separate flags:
    
        OPpASSIGN_COMMON_AGG
        OPpASSIGN_COMMON_RC1
        OPpASSIGN_COMMON_SCALAR
    
    which indicate different classes of commonality that can be handled
    in different ways at runtime.
    
    Most importantly, it distinguishes between two basic cases. Firstly,
    common scalars (OPpASSIGN_COMMON_SCALAR), e.g.
    
        ($x,....) = (....,$x,...)
    
    where $x is modified and then sometime later its value is used again,
    but that value has changed in the meantime. In this case, we need
    replace such vars on the RHS with mortal copies before processing the
    assign.
    
    The second case is an aggregate on the LHS (OPpASSIGN_COMMON_AGG), e.g.
    
        (...,@a) = (...., $a[0],...)
    
    In this case, the issue is instead that when @a is cleared, it may free
    items on the RHS (due to the stack not being ref counted).  What is
    required here is that rather than making of a copy of each RHS element and
    storing it in the array as we progress, we make *all* the copies *before*
    clearing the array, but mortalise them in case we die in the meantime.
    
    We can further distinguish two scalar cases; sometimes it's possible
    to confirm non-commonality at run-time merely by checking that all
    the LHS scalars have a reference count of 1. If this is possible,
    we set the OPpASSIGN_COMMON_RC1 flag rather than the
    OPpASSIGN_COMMON_SCALAR flag.
    
    The major improvement in the run-time performance in the
    OPpASSIGN_COMMON_SCALAR case (or OPpASSIGN_COMMON_RC1 if rc>1 scalars are
    detected), is to use a mark-and-sweep scan of the two lists using the
    SVf_BREAK flag, to determine which elements are common, and only make
    mortal copies of those elements.  This has a very big effect on run-time
    performance; for example in the classic
    
        ($a,$b) = ($b,$a);
    
    it would formerly make temp copies of both $a and $b; now it only
    copies $a.
    
    In more detail, the mark and sweep mechanism in pp_aassign works by
    looping through each LHS and RHS SV pair in parallel. It temporarily marks
    each LHS SV with the SVf_BREAK flag, then makes a copy of each RHS element
    only if it has the SVf_BREAK flag set. When the scan is finished, the flag
    is unset on all LHS elements.
    
    One major change in compile-time flagging is that package scalar vars are
    now treated as if they could always be aliased. So we don't bother any
    more to do the compile-time PL_generation checking on package vars (we
    still do it on lexical vars). We also no longer make use of the run-time
    PL_sawalias mechanism for detecting aliased package vars (and indeed the
    next commit but one will remove that mechanism). This means that more list
    assignment expressions which feature package vars will now need to
    do a runtime mark-and-sweep (or where appropriate, RC1) test. In
    compensation, we no longer need to test for aliasing and set PL_sawalias
    in pp_gvsv and pp_gv, nor reset PL_sawalias in every pp_nextstate.
    
    Part of the reasoning behind this is that it's nearly impossible to detect
    all possible package var aliasing; for example PL_sawalias would fail to
    detect XS code doing GvSV(gv) = sv.
    
    Note that we now scan the two children of the OP_AASSIGN separately,
    and in particular we mark lexicals with PL_generation only on the
    LHS and test only on the RHS. So something like
    
        ($x,$y) = ($default, $default)
    
    will no longer be regarded as having common vars.
    
    In terms of performance, running Porting/perlbench.pl on the new
    expr::aassign:: tests in t/perf/benchmarks show that the biggest slowdown
    is around 13% more instruction reads and 20% more conditional branches in
    this:
            setup   => 'my ($v1,$v2,$v3) = 1..3; ($x,$y,$z) = 1..3;',
            code    => '($x,$y,$z) = ($v1,$v2,$v3)',
    
    where this is now a false positive due to the presence of package
    variables.
    
    The biggest speedup is 50% less instruction reads and conditional branches
    in this:
    
            setup   => '@_ = 1..3; my ($x,$y,$z)',
            code    => '($x,$y,$z) = @_',
    
    because formerly the presence of @_ pessimised things if the LHS wasn't
    a my declaration (it's still pessimised, but the runtime's faster now).
    
    Conversely, we pessimise the 'my' variant too now:
    
            setup   => '@_ = 1..3;',
            code    => 'my ($x,$y,$z) = @_',
    
    this gives 5% more instruction reads and 11% more conditional branches now.
    But see the next commit, which will cheat for that particular construct.

M       MANIFEST
M       embed.fnc
M       embed.h
M       ext/B/t/f_map.t
M       ext/B/t/f_sort.t
M       ext/B/t/optree_misc.t
M       ext/B/t/optree_samples.t
M       ext/B/t/optree_sort.t
M       lib/B/Op_private.pm
M       op.c
M       opcode.h
M       pp_hot.c
M       proto.h
M       regen/op_private
M       sv.h
A       t/op/aassign.t
M       t/op/array.t
M       t/op/hash.t
M       t/op/sort.t
M       t/perf/benchmarks
M       t/perf/optree.t
-----------------------------------------------------------------------

--
Perl5 Master Repository

Reply via email to