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

<http://perl5.git.perl.org/perl.git/commitdiff/710ddd120e1631b12a599b7683917539c927a15d?hp=0000000000000000000000000000000000000000>

        at  710ddd120e1631b12a599b7683917539c927a15d (commit)

- Log -----------------------------------------------------------------
commit 710ddd120e1631b12a599b7683917539c927a15d
Author: David Mitchell <[email protected]>
Date:   Mon Feb 16 17:32:45 2015 +0000

    make my(...)=@_ use OP_SIGNATURE
    
    This isn't yet enabled by default: it requires perl to be built with
    PERL_FAKE_SIGNATURE defined.
    
    Where the first statement in a function is a simple
    
        my (....) = @_;
    
    with the my elements being any mixture of scalars or undefs, with an
    optional final array or hash, then convert that subtree of ops into
    a single OP_SIGNATURE op, which will be faster.
    
    The op will have the OPpSIGNATURE_FAKE private flag set, to distinguish
    it from real signatured subs.

M       ext/B/t/optree_misc.t
M       lib/B/Deparse.pm
M       lib/B/Deparse.t
M       lib/B/Op_private.pm
M       op.c
M       opcode.h
M       pp_hot.c
M       regen/op_private
M       t/op/sub.t
M       t/perf/opcount.t

commit 34b8ef89ea031e6d025248ddbeea2321f536ce60
Author: David Mitchell <[email protected]>
Date:   Mon Feb 16 13:51:14 2015 +0000

    add Perl_prefinalize_optree()
    
    this is a top-down optree function like Perl_finalize_optree,
    but is called before peep(), so allows you to do stuff to the
    optree before its been optimised.

M       embed.fnc
M       embed.h
M       op.c
M       proto.h

commit e2f0970fbae115d09688dc05f8f5834ae6ac9a3e
Author: David Mitchell <[email protected]>
Date:   Mon Feb 16 12:50:35 2015 +0000

    add S_postprocess_optree() to op.c
    
    Collect several of the common steps in finishing off an optree
    into a single sub (e.g. setting refcount on the root op, calling peep,
    etc).

M       op.c

commit 6cceb1891207f86be05075d2c7b77d2c0790c3a4
Author: David Mitchell <[email protected]>
Date:   Tue Jan 20 17:45:55 2015 +0000

    add OP_SIGNATURE
    
    In the current (experimental) subroutine signatures implementation, the
    checking for sufficient numbers of args, the introduction of lexical vars,
    and the assignment of @_ and/or default values to them, is done by placing
    lots of individual perl ops at the start of the function body.
    
    For example, this:
    
        sub f ($a, $b = 0, $c = "foo") {};
    
    deparses as:
    
        sub f {
            die sprintf("Too many arguments for subroutine at %s line %d.\n", 
(calle
    r)[1, 2]) unless @_ <= 3;
            die sprintf("Too few arguments for subroutine at %s line %d.\n", 
(caller
    )[1, 2]) unless @_ >= 1;
            my $a = $_[0];
            my $b = @_ >= 2 ? $_[1] : 0;
            my $c = @_ >= 3 ? $_[2] : 'foo';
            ();
        }
    
    which is of course *very* slow.
    
    This commit adds a new op, OP_SIGNATURE, of type UNOP_AUX, which handles
    most of this work in a single op. It's inspired by my OP_MULTIDEREF work,
    where 'simple' indices and keys (integers, consts, simple lex and package
    vars) were handled directly by the op using values and pointers stored in
    the op_aux array. For OP_SIGNATURE, simple default args (ints, consts, and
    sometimes lexicals and package vars) are stored in the op_aux struct,
    while more complex expressions are compiled as assign statements following
    the OP_SIGNATURE op. For example:
    
        sub f ($a, $b = 0, $c = "foo", $d = $c+1) {};
    
    now gives
    
        $ ./perl -Ilib -MO=Concise,f,-exec /tmp/signatures.t
        main::f:
        1  <;> nextstate(main 78 p:6) v:%,469762048
        2  <+> signature($a, $b=0, $c="foo", $d=<expr>) v
        3  <;> nextstate(main 81 p:6) v:%,469762048
        4  <0> padsv[$c:80,82] s
        5  <$> const[IV 1] s
        6  <2> add[$d:81,82] sK/TARGMY,2
        7  <;> nextstate(main 82 p:6) :%,469762048
        8  <1> leavesub[1 ref] K/REFC,1
    
    The performance is impressive, with a simple
    
        sub f($a, $b, $c) {}
    
    now being typically faster than
    
        sub { my ($a, $b, $c) = @_; }
    
    and signatured subs being typically twice as fast to call as they were
    before.
    
    As well as benefiting from doing nearly all the work in a single op,
    the fact that it is the first op in the function allows some fairly
    aggressive optimisations. In particular we know that newly introduced
    lexicals will always be undef and non-magical, unlike for example:
    
        f();
        my $x; # $x not undef here!
        sub f { $x = 1 }
    
    Also, it is likely that subs are always called with a particular arg being
    always the same type; for example, methods will always pass a ref as arg
    1. Given the fact that at end of scope, lexical vars with a ref count of 1
    are simply cleared in place, then in this case, by the time of the second
    call, the lexical var $self in
    
        sub f($self, ...) {...}
    
    is likely to be a !SvOK SV with a body of type SVt_IV (already suitable
    for holding an int or RV). If OP_SIGNATURE sees that the passed arg is
    SvROK, it checks whether the lexical is of type SVt_IV, and if so just
    directly does
    
        SvRV_set(...);
        SvROK_on(...)
    
    rather than calling sv_setsv(). A similar short-cut is performed for
    SvIOK values.
    
    Default values of 0 and 1 are special-cased with their own action, so
    no extra data needs storing in the op_aux array. Other integer-valued
    constant defaults are stored as an IV in op_aux. More general constants
    are stored as an SV pointer (or pad offset for threaded builds) in op_aux.
    
    Default values that are simple lexicals or package vars, such as
    
        sub f ($a, $b = $a, $c = $::Foo)
    
    are usually stored as a pad index or GV pointer in the op_aux array.
    There is a complication here in that more complex defaults are stored as
    ops that get executed *after* OP_SIGNATURE, which means that default arg
    processing can get re-ordered. For example,
    
        sub f ($a, $b = $a++, $c = $a) {}
    
    might get executed as the equivalent of
    
        # happens within OP_SIGNATURE:
        $a = $_[0];
        $b = $_[1];
        $c = $_[2] // $a;
        # delayed: happens afterwards
        $b //= $a++;
    
    since the '$a' default is handled directly by OP_SIGNATURE, while '$a++'
    is postponed. Clearly in this case this would be wrong, so the '$a'
    default is in fact handled outside the OP_SIGNATURE too in cases like
    this, leading to correct execution roughly like:
    
        # happens within OP_SIGNATURE:
        $a = $_[0];
        $b = $_[1];
        $c = $_[2];
        # happens afterwards
        $b //= $a++;
        $c //= $a
    
    This commit also makes signatured subs deparse correctly for the first
    time, and also makes t/op/signature.t pass under TEST -deparse.
    
    Note that this commit introduces a hard limit of 32767 parameters for any
    signature sub, but I can't conceive of that being an issue.

M       Porting/deparse-skips.txt
M       cv.h
M       dump.c
M       embed.fnc
M       embed.h
M       ext/B/B.pm
M       ext/B/B.xs
M       ext/Devel-Peek/t/Peek.t
M       ext/Opcode/Opcode.pm
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       perly.act
M       perly.h
M       perly.tab
M       perly.y
M       pod/perldiag.pod
M       pp_hot.c
M       pp_proto.h
M       proto.h
M       regen/opcodes
M       sv.c
M       t/lib/warnings/9uninit
M       t/op/signatures.t
M       t/op/svleak.t
M       t/op/taint.t
M       t/perf/benchmarks
M       t/perf/opcount.t
M       toke.c

commit 14f63bdde15a544bddab14aca8d8e322907dcbce
Author: David Mitchell <[email protected]>
Date:   Fri Jan 30 23:26:23 2015 +0000

    make S_op_relocate_sv() non-static
    
    This function will shortly need to be accessed from toke.c as well
    as op.c, so make it global but non-public. Also, stop it being an
    inlinable function - it's only used during compilation and isn't
    performance-critical, and is not small.

M       embed.fnc
M       embed.h
M       makedef.pl
M       op.c
M       proto.h
-----------------------------------------------------------------------

--
Perl5 Master Repository

Reply via email to