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

<http://perl5.git.perl.org/perl.git/commitdiff/87b51e96180884a21306b55db8ed0c2e647d5e9c?hp=0000000000000000000000000000000000000000>

        at  87b51e96180884a21306b55db8ed0c2e647d5e9c (commit)

- Log -----------------------------------------------------------------
commit 87b51e96180884a21306b55db8ed0c2e647d5e9c
Author: David Mitchell <[email protected]>
Date:   Fri Oct 24 16:26:38 2014 +0100

    Add OP_MULTIDEREF
    
    This op is an optimisation for any series of one or more array or hash
    lookups and dereferences, where the key/index is a simple constant or
    package/lexical variable. If the first-level lookup is of a simple
    array/hash variable or scalar ref, then that is included in the op too.
    
    So all of the following are replaced with a single op:
    
        $h{foo}
        $a[$i]
        $a[5][$k][$i]
        $r->{$k}
        local $a[0][$i]
        exists $a[$i]{$k}
        delete $h{foo}
    
    while these aren't:
    
        $a[0]       already handled by OP_AELEMFAST
        $a[$x+1]    not a simple index
    
    and these are partially replaced:
    
        (expr)->[0]{$k}   the bit following (expr) is replaced
        $h{foo}[$x+1][0]  the first and third lookups are each done with
                          a multideref op, while the $x+1 expression and
                          middle lookup are done by existing add, aelem etc
                          ops.
    
    Up until now, aggregate dereferencing has been very heavyweight in ops; for
    example, $r->[0]{$x} is compiled as:
    
        gv[*r] s
        rv2sv sKM/DREFAV,1
        rv2av[t2] sKR/1
        const[IV 0] s
        aelem sKM/DREFHV,2
        rv2hv sKR/1
        gvsv[*x] s
        helem vK/2
    
    When executing this, in addition to the actual calls to av_fetch() and
    hv_fetch(), there is a lot of overhead of pushing SVs on and off the
    stack, and calling lots of little pp() functions from the runops loop
    (each with its potential indirect branch miss).
    
    The multideref op avoids that by running all the code in a loop in a
    switch statement. It makes use of the new UNOP_AUX type to hold an array
    of
    
        typedef union  {
            PADOFFSET pad_offset;
            SV        *sv;
            IV        iv;
            UV        uv;
        } UNOP_AUX_item;
    
    In something like $a[7][$i]{foo}, the GVs or pad offsets for @a and $i are
    stored as items in the array, along with a pointer to a const SV holding
    'foo', and the UV 7 is stored directly. Along with this, some UVs are used
    to store a sequence of actions (several actions are squeezed into a single
    UV).
    
    Then the main body of pp_multideref is a big while loop round a switch,
    which reads actions and values from the AUX array. The two big branches in
    the switch are ones that are affectively unrolled (/DREFAV, rv2av, aelem)
    and (/DREFHV, rv2hv, helem) triplets. The other branches are various entry
    points that handle retrieving the different types of initial value; for
    example 'my %h; $h{foo}' needs to get %h from the pad, while '(expr)->{foo}'
    needs to pop expr off the stack.
    
    Note that there is a slight complication with /DEREF; in the example above
    of $r->[0]{$x}, the aelem op is actually
    
        aelem sKM/DREFHV,2
    
    which means that the aelem, after having retrieved a (possibly undef)
    value from the array, is responsible for autovivifying it into a hash,
    ready for the next op. Similarly, the rv2sv that retrieves $r from the
    typeglob is responsible for autovivifying it into an AV. This action
    of doing the next op's work for it complicates matters somewhat. Within
    pp_multideref, the autovivification action is instead included as the
    first step of the current action.
    
    In terms of benchmarking with Porting/bench.pl, a simple lexical
    $a[$i][$j] shows a reduction of approx 40% in numbers of instructions
    executed, while $r->[0][0][0] uses 54% fewer. The speed-up for hash
    accesses is relatively more modest, since the actual hash lookup (i.e.
    hv_fetch()) is more expensive than an array lookup. A lexical $h{foo}
    uses 10% fewer, while $r->{foo}{bar}{baz} uses 34% fewer instructions.
    
    In general, the more lookups done, the bigger the proportionate saving.

M       MANIFEST
M       Porting/deparse-skips.txt
M       dist/Safe/t/safeops.t
M       dump.c
M       embed.fnc
M       embed.h
M       embedvar.h
M       ext/B/B.xs
M       ext/B/B/Concise.pm
M       ext/B/t/OptreeCheck.pm
M       ext/B/t/concise-xs.t
M       ext/B/t/f_sort.t
M       ext/Opcode/Opcode.pm
M       intrpvar.h
M       lib/B/Deparse.pm
M       lib/B/Deparse.t
M       lib/B/Op_private.pm
M       op.c
M       op.h
M       opcode.h
M       opnames.h
M       perl.h
M       pp.c
M       pp_hot.c
M       pp_proto.h
M       proto.h
M       regen/op_private
M       regen/opcodes
M       sv.c
M       t/lib/warnings/9uninit
A       t/op/multideref.t
M       t/op/svleak.t
M       t/perf/benchmarks
M       t/perf/opcount.t

commit 76b0bf415ee98f7413533a086b4b8ddb0a56bcb1
Author: David Mitchell <[email protected]>
Date:   Mon Oct 27 17:33:32 2014 +0000

    add UNOP_AUX OP class
    
    This is the same as a UNOP, but with the addition of an op_aux field,
    which points to an array of UNOP_AUX_item unions.
    
    It is intended as a general escape mechanism for adding per-op-type extra
    fields (or arrays of items) to UNOPs.
    
    Its class character (for regen/opcodes etc) is '+'.
    
    Currently there are no ops of this type; but shortly, OP_MULTIDEREF will
    be added, which is the original motivation for this new op type.

M       embed.fnc
M       embed.h
M       ext/B/B.pm
M       ext/B/B.xs
M       ext/B/B/Concise.pm
M       op.c
M       op.h
M       perl.h
M       proto.h
M       regen/op_private
M       regen/opcode.pl
M       regen/opcodes

commit e9692110af3d0b05332f5f0d9c5cfae68ea91036
Author: David Mitchell <[email protected]>
Date:   Sun Nov 2 16:01:00 2014 +0000

    ext/B/Makefile.PL: spot hex defines
    
    The regex in ext/B/Makefile.PL was failing to find C constants of the
    form
    
        #define FOO 0xNNN
    
    where NNN contained one or more [a-fA-F] chars
    
    With this change it imports a few more constants:
    
        CXTYPEMASK
        GVf_IMPORTED
        RV2CVOPCV_FLAG_MASK
        OPpARG4_MASK
        OPpPADRANGE_COUNTMASK

M       ext/B/Makefile.PL

commit ed0f2b9138dc17e350c4cd188b5482c9cfc5d9f4
Author: David Mitchell <[email protected]>
Date:   Thu Oct 30 10:28:06 2014 +0000

    Perl_op_sibling_splice(): update OPf_KIDS
    
    Previously this function didn't update OPf_KIDS when altering the
    children. This was only safe as long as the count of kids didn't transition
    between 0 and !0.

M       op.c

commit 01ee4d868413149dd25b5195786be11d30e47f87
Author: David Mitchell <[email protected]>
Date:   Fri Oct 24 16:23:38 2014 +0100

    add S_deb_padvar() to dump.c
    
    factor out the code that prints a pad var name in -Dt output

M       dump.c

commit f0d4043eb6895a7beb1e8322d7e8ba4f7c9621fc
Author: David Mitchell <[email protected]>
Date:   Thu Aug 7 16:34:23 2014 +0100

    add S_op_clear_gv() to op.c
    
    Abstract out the code that clear an GV attached to an op,
    since we will shortly need to do this in more than one place

M       op.c

commit 19eaaa678e2161dde25ba4918cb0c9ef9939cd3a
Author: David Mitchell <[email protected]>
Date:   Sun Jul 27 20:59:48 2014 +0100

    create S_check_hash_fields() function
    
    factor out the code in S_finalize_op() that performs checks on hash keys
    into a separate function, since we'll shortly need to call this code from
    more than one place.

M       op.c
-----------------------------------------------------------------------

--
Perl5 Master Repository

Reply via email to