114 Commits

Author SHA1 Message Date
Paul "LeoNerd" Evans
3c2e356191 Create new OP_MULTIPARAM to implement subroutine signatures
Creates a new UNOP_AUX op type, `OP_MULTIPARAM`, that handles all of the
initial behaviour of assigning values to parameters of a subroutine
signature out of values passed by the caller. This is created in a
similar style to other multi-ops like `OP_MULTIDEREF` and
`OP_MULTICONCAT` where the op's aux structure contains a sub-program of
sorts, which describes all of the small details of operation.

Also adds a LOGOP, `OP_PARAMTEST` and UNOP `OP_PARAMSTORE` which are
responsible for implementing the default expressions of optional
parameters. These use the `SvPADSTALE` flag set on pad lexicals used as
parameters to remember whether assignment has happened, ensuring that
missing vs present-but-undef can be detected in a way that does not
depend on counting arguments on the stack.

This change is carefully designed to support two future ideas:

  * Named parameters as per PPC0024
    https://github.com/Perl/PPCs/blob/main/ppcs/ppc0024-signature-named-parameters.md

  * "no-snails"; the performance optimisation that avoids storing
    incoming argument values in the `@_` AV and instead consumes them
    directly from the stack
2025-08-25 14:06:05 +01:00
Tony Cook
cd80cda9a1 Revert "switch removal: remove given/when/break/continue"
This reverts commit dff5181acc0f5386556522c0ae4e59f672162f6e.
2025-02-16 14:51:17 +01:00
Tony Cook
a215a77dd9 Revert "switch removal: remove smartmatch"
This reverts commit cb2167d3785e61e23819ca2c58ac1e89d5e4bf3b.
2025-02-16 14:51:16 +01:00
Richard Leach
cdbed2a40e OP_SUBSTR_LEFT - a specialised OP_SUBSTR variant
This commit adds OP_SUBSTR_LEFT and associated machinery for fast
handling of the constructions:

        substr EXPR,0,LENGTH,''
and
        substr EXPR,0,LENGTH

Where EXPR is a scalar lexical, the OFFSET is zero, and either there
is no REPLACEMENT or it is the empty string. LENGTH can be anything
that OP_SUBSTR supports. These constraints allow for a very stripped
back and optimised version of pp_substr.

The primary motivation was for situations where a scalar, containing
some network packets or other binary data structure, is being parsed
piecemeal. Nibbling away at the scalar can be useful when you don't
know how exactly it will be parsed and unpacked until you get started.
It also means that you don't need to worry about correctly updating
a separate offset variable.

This operator also turns out to be an efficient way to (destructively)
break an expression up into fixed size chunks. For example, given:

    my $x = ''; my $str = "A"x100_000_000;

This code:

    $x = substr($str, 0, 5, "") while ($str);

is twice as fast as doing:

    for ($pos = 0; $pos < length($str); $pos += 5) {
        $x = substr($str, $pos, 5);
    }

Compared with blead, `$y = substr($x, 0, 5)` runs 40% faster and
`$y = substr($x, 0, 5, '')` runs 45% faster.
2025-01-13 22:11:16 +00:00
Paul "LeoNerd" Evans
6f04944602 Implement PPC0027: Create all and any operators
As these only permit `any BLOCK LIST` and not the deferred-expression
form like `grep EXPR, LIST`, we create a whole new token type, BLKLSTOP,
to represent these. The parser then only accepts the block form and not
the expression form when parsing these.
2024-12-04 16:28:06 +00:00
Tony Cook
cb2167d378 switch removal: remove smartmatch 2024-08-15 10:56:18 +10:00
Tony Cook
dff5181acc switch removal: remove given/when/break/continue
continue blocks are not removed
2024-08-15 10:56:18 +10:00
Paul "LeoNerd" Evans
63119ccaf3 Added __CLASS__ keyword, which yields the runtime class name of the invoking instance 2023-08-02 13:38:25 +01:00
Lukas Mai
b7eedb0895 fix incorrect vi filetype declarations in generated files
Vim's filetype declarations are case sensitive. The correct types for
Perl, C, and Pod are perl, c, and pod, respectively.
2023-03-24 06:10:05 +08:00
Branislav Zahradník
8a79dfad98 pp: use PP macro consistently 2023-02-20 22:32:22 +08:00
Elvin Aslanov
6a3688ca38 generated files - update mode lines to specify file type
This updates the mode-line for most of our generated files so that
they include file type information so they will be properly syntax
highlighted on github.

This does not make any other functional changes to the files.

[Note: Commit message rewritten by Yves]
2023-02-19 09:44:05 +08:00
Paul "LeoNerd" Evans
054ceeebc7 Accept field VAR = EXPR on field vars
Allows non-constant expressions with side effects. Evaluated during the
constructor of each instance.
2023-02-10 14:38:44 +00:00
Paul "LeoNerd" Evans
99b497aa90 Initial attack at basic 'class' feature
Adds a new experimental warning, feature, keywords and enough parsing to
implement basic classes with an empty `new` constructor method.

Inject a $self lexical into method bodies; populate it with the object instance, suitably shifted
Creates a new OP_METHSTART opcode to perform method setup
Define an aux flag to remark which stashes are classes

Basic implementation of fields.

Basic anonymous methods.
2023-02-10 12:07:02 +00:00
Paul "LeoNerd" Evans
abf1aa2b09 Define OP_HELEMEXISTSOR, a handy LOGOP shortcut for HELEM existence tests
This op is constructed using an OP_HELEM as the op_first and any scalar
expression as the op_other.

It is roughly equivalent to the following perl code:

  exists $hv{$key} ? $hv{$key} : OTHER

except that the HV and the KEY expression are evaluated only once, and
only one hv_* function is invoked to both test and obtain the value. It
is therefore smaller and more efficient.

Likewise, adding the OPpHELEMEXISTSOR_DELETE flag turns it into the
equivalent of

  exists $hv{$key} ? delete $hv{$key} : OTHER
2022-12-19 17:27:55 +00:00
Richard Leach
10a5c91382 OP_EMPTYAVHV - optimized empty ANONLIST/ANONHASH
This commit introduces a new OP to replace cases of OP_ANONLIST and
OP_ANONHASH where there are zero elements, which is very common in
Perl code.

As an example, `my $x = {}` is currently implemented like this:
    ...
    6     <2> sassign vKS/2 ->7
    4        <@> anonhash sK* ->5
    3           <0> pushmark s ->4
    5        <0> padsv[$x:1,2] sRM*/LVINTRO ->6

The pushmark serves no meaningful purpose when there are zero
elements and the anonhash, besides undoing the pushmark,
performs work that is unnecessary for this special case.

The peephole optimizer, which also checks for applicability of a
related TARGMY optimization, transforms this example into:
    ...
    -     <1> ex-sassign vKS/2 ->4
    3        <@> emptyavhv[$x:1,2] vK*/LVINTRO,ANONHASH,TARGMY ->4
    -           <0> ex-pushmark s ->3
    -        <0> ex-padsv sRM*/LVINTRO ->-
2022-10-24 23:21:17 +01:00
Richard Leach
aafefcb901 OP_AELEMFASTLEX_STORE - combined sassign/aelemfast_lex
This commit introduces a new OP to replace simple cases of OP_SASSIGN
and OP_AELEMFAST_LEX. (Similar concept to GH #19943)

For example, `my @ary; $ary[0] = "boo"` is currently implemented as:
    7     <2> sassign vKS/2 ->8
    5        <$> const[PV "boo"] s ->6
    -        <1> ex-aelem sKRM*/2 ->7
    6           <0> aelemfast_lex[@ary:1,2] sRM ->7
    -           <0> ex-const s ->-

But now will be turned into:
    6     <1> aelemfastlex_store[@ary:1,2] vKS ->7
    5        <$> const(PV "boo") s ->6
    -        <1> ex-aelem sKRM*/2 ->6
    -           <0> ex-aelemfast_lex sRM ->6
    -           <0> ex-const s ->-

This is intended to be a transparent performance optimization.
It should be applicable for RHS optrees of varying complexity.
2022-09-07 20:27:27 +01:00
Richard Leach
9fdd7fc479 Implement OP_PADSV_STORE - combined sassign/padsv OP
This commit introduces a new OP to replace simple cases
of OP_SASSIGN and OP_PADSV.

For example, 'my $x = 1' is currently implemented as:

1  <;> nextstate(main 1 -e:1) v:{
2  <$> const(IV 1) s
3  <0> padsv[$x:1,2] sRM*/LVINTRO
4  <2> sassign vKS/2

But now will be turned into:

1  <;> nextstate(main 1 -e:1) v:{
2  <$> const(IV 1) s
3  <1> padsv_store[$x:1,2] vKMS/LVINTRO

This intended to be a transparent performance optimization.
It should be applicable for RHS optrees of varying complexity.
2022-08-17 11:19:10 +01:00
James Raspass
a02b8151f9 Add builtin::is_tainted
Also tweak the implementation of the other two boolean builtins (is_bool
& is_weak) to be slightly more efficient.
2022-07-05 11:17:31 +10:00
Tomasz Konojacki
0351a629e7 hide private functions with __attribute__((visibility("hidden")))
This allows us to enforce API boundaries and potentially enables
compiler optimisations.

We've been always hiding non-public symbols on Windows. This commit
brings that to the other platforms.
2022-06-18 08:51:14 +02:00
Paul "LeoNerd" Evans
5a94615fd1 Rename is{bool,weak} to is_{bool,weak} 2022-03-07 16:44:11 +00:00
James Raspass
17a8df7077 Add ceil & floor to builtin 2022-01-24 00:35:51 +00:00
Paul "LeoNerd" Evans
d2817bd771 Add builtin::blessed, refaddr and reftype 2021-12-08 00:05:10 +00:00
Paul "LeoNerd" Evans
6ac93b496c Add builtin:: funcs for handling weakrefs
Also, ensure that B::Deparse understands the OA_TARGMY optimisation of
OP_ISBOOL
2021-12-04 11:39:22 +00:00
Paul "LeoNerd" Evans
852c1a8467 Direct optree implementations of builtin:: functions
Turn builtin::true/false into OP_CONSTs

Add a dedicated OP_ISBOOL, make an efficient op version of builtin::isbool()
2021-12-01 22:03:37 +00:00
Paul "LeoNerd" Evans
f79e2ff95f Create defer syntax and OP_PUSHDEFER opcode
Adds syntax `defer { BLOCK }` to create a deferred block; code that is
deferred until the scope exits. This syntax is guarded by

  use feature 'defer';

Adds a new opcode, `OP_PUSHDEFER`, which is a LOGOP whose `op_other` field
gives the start of an optree to be deferred until scope exit. That op
pointer will be stored on the save stack and invoked as part of scope
unwind.

Included is support for `B::Deparse` to deparse the optree back into
syntax.
2021-08-25 13:52:09 +01:00
Paul "LeoNerd" Evans
383bf72f37 A totally new optree structure for try/catch involving three new optypes 2021-02-14 13:40:50 +00:00
Paul "LeoNerd" Evans
a1325b902d Initial attempt at feature 'try'
* Add feature, experimental warning, keyword
 * Basic parsing
 * Basic implementation as optree fragment

See also
  https://github.com/Perl/perl5/issues/18504
2021-02-04 14:20:53 +00:00
Zefram
02b85d3dab chained comparisons 2020-03-12 22:34:26 -06:00
Dagfinn Ilmari Mannsåker
f955cd4a58 pp_i_modulo(): remove workaround for ancient glibc bug
Old glibc versions had a buggy modulo implementation for 64 bit
integers on 32-bit architectures.  This was fixed in glibc 2.3,
released in 2002 (the version check in the code is overly cautious).

Removing the alternate PP function support is left for the next
commit, in case we need to resurrect it in future.
2020-02-05 10:49:24 +00:00
Paul "LeoNerd" Evans
813e85a03d Add the isa operator
Adds a new infix operator named `isa`, with the semantics that

  $x isa SomeClass

is true if and only if `$x` is a blessed object reference that is either
`SomeClass` directly, or includes the class somewhere in its @ISA
hierarchy. It is false without warning or error for non-references or
non-blessed references.

This operator respects `->isa` method overloading, and is intended to
replace boilerplate code such as

  use Scalar::Util 'blessed';

  blessed($x) and $x->isa("SomeClass")
2019-12-09 23:19:05 +00:00
Zefram
7896dde748 revert smartmatch to 5.27.6 behaviour
The pumpking has determined that the CPAN breakage caused by changing
smartmatch [perl #132594] is too great for the smartmatch changes to
stay in for 5.28.

This reverts most of the merge in commit
da4e040f42421764ef069371d77c008e6b801f45.  All core behaviour and
documentation is reverted.  The removal of use of smartmatch from a couple
of tests (that aren't testing smartmatch) remains.  Customisation of
a couple of CPAN modules to make them portable across smartmatch types
remains.  A small bugfix in scope.c also remains.
2017-12-29 12:39:31 +00:00
Zefram
15e4ac9a42 internally change "when" to "whereso"
The names of ops, context types, functions, etc., all change in accordance
with the change of keyword.
2017-12-05 22:30:50 +00:00
Zefram
16ea2c1905 merge leavegiven op type into leaveloop
The leaveloop op type can already do the whole job, with leavegiven being
a near duplicate of it.  Replace all uses of leavegiven with leaveloop.
2017-12-05 21:24:19 +00:00
Zefram
97b4caa610 remove useless "break" mechanism 2017-11-29 20:19:20 +00:00
David Mitchell
e839e6ed99 Add OP_MULTICONCAT op
Allow multiple OP_CONCAT, OP_CONST ops, plus optionally an OP_SASSIGN
or OP_STRINGIFY, to be combined into a single OP_MULTICONCAT op, which can
make things a *lot* faster: 4x or more.

In more detail: it will optimise into a single OP_MULTICONCAT, most
expressions of the form

    LHS RHS

where LHS is one of

    (empty)
    my $lexical =
    $lexical    =
    $lexical   .=
    expression  =
    expression .=

and RHS is one of

    (A . B . C . ...)            where A,B,C etc are expressions and/or
                                 string constants

    "aAbBc..."                   where a,A,b,B etc are expressions and/or
                                 string constants

    sprintf "..%s..%s..", A,B,.. where the format is a constant string
                                 containing only '%s' and '%%' elements,
                                 and A,B, etc are scalar expressions (so
                                 only a fixed, compile-time-known number of
                                 args: no arrays or list context function
                                 calls etc)

It doesn't optimise other forms, such as

    ($a . $b) . ($c. $d)

    ((($a .= $b) .= $c) .= $d);

(although sub-parts of those expressions might be converted to an
OP_MULTICONCAT). This is partly because it would be hard to maintain the
correct ordering of tie or overload calls.

The compiler uses heuristics to determine when to convert: in general,
expressions involving a single OP_CONCAT aren't converted, unless some
other saving can be made, for example if an OP_CONST can be eliminated, or
in the presence of 'my $x = .. ' which OP_MULTICONCAT can apply
OPpTARGET_MY to, but OP_CONST can't.

The multiconcat op is of type UNOP_AUX, with the op_aux structure directly
holding a pointer to a single constant char* string plus a list of segment
lengths. So for

    "a=$a b=$b\n";

the constant string is "a= b=\n", and the segment lengths are (2,3,1).
If the constant string has different non-utf8 and utf8 representations
(such as "\x80") then both variants are pre-computed and stored in the aux
struct, along with two sets of segment lengths.

For all the above LHS types, any SASSIGN op is optimised away. For a LHS
of '$lex=', '$lex.=' or 'my $lex=', the PADSV is optimised away too.

For example where $a and $b are lexical vars, this statement:

    my $c = "a=$a, b=$b\n";

formerly compiled to

    const[PV "a="] s
    padsv[$a:1,3] s
    concat[t4] sK/2
    const[PV ", b="] s
    concat[t5] sKS/2
    padsv[$b:1,3] s
    concat[t6] sKS/2
    const[PV "\n"] s
    concat[t7] sKS/2
    padsv[$c:2,3] sRM*/LVINTRO
    sassign vKS/2

and now compiles to:

    padsv[$a:1,3] s
    padsv[$b:1,3] s
    multiconcat("a=, b=\n",2,4,1)[$c:2,3] vK/LVINTRO,TARGMY,STRINGIFY

In terms of how much faster it is, this code:

    my $a = "the quick brown fox jumps over the lazy dog";
    my $b = "to be, or not to be; sorry, what was the question again?";

    for my $i (1..10_000_000) {
        my $c = "a=$a, b=$b\n";
    }

runs 2.7 times faster, and if you throw utf8 mixtures in it gets even
better. This loop runs 4 times faster:

    my $s;
    my $a = "ab\x{100}cde";
    my $b = "fghij";
    my $c = "\x{101}klmn";

    for my $i (1..10_000_000) {
        $s = "\x{100}wxyz";
        $s .= "foo=$a bar=$b baz=$c";
    }

The main ways in which OP_MULTICONCAT gains its speed are:

* any OP_CONSTs are eliminated, and the constant bits (already in the
  right encoding) are copied directly from the constant string attached to
  the op's aux structure.

* It optimises away any SASSIGN op, and possibly a PADSV op on the LHS, in
  all cases; OP_CONCAT only did this in very limited circumstances.

* Because it has a holistic view of the entire concatenation expression,
  it can do the whole thing in one efficient go, rather than creating and
  copying intermediate results. pp_multiconcat() goes to considerable
  efforts to avoid inefficiencies. For example it will only SvGROW() the
  target once, and to the exact size needed, no matter what mix of utf8
  and non-utf8 appear on the LHS and RHS.  It never allocates any
  temporary SVs except possibly in the case of tie or overloading.

* It does all its own appending and utf8 handling rather than calling
  out to functions like sv_catsv().

* It's very good at handling the LHS appearing on the RHS; for example in

    $x = "abcd";
    $x = "-$x-$x-";

  It will do roughly the equivalent of the following (where targ is $x);

    SvPV_force(targ);
    SvGROW(targ, 11);
    p = SvPVX(targ);
    Move(p,   p+1,  4, char);
    Copy("-", p,    1, char);
    Copy("-", p+5,  1, char);
    Copy(p+1, p+6,  4, char);
    Copy("-", p+10, 1, char);
    SvCUR(targ) = 11;
    p[11] = '\0';

  Formerly, pp_concat would have used multiple PADTMPs or temporary SVs to
  handle situations like that.

The code is quite big; both S_maybe_multiconcat() and pp_multiconcat()
(the main compile-time and runtime parts of the implementation) are over
700 lines each. It turns out that when you combine multiple ops, the
number of edge cases grows exponentially ;-)
2017-10-31 15:31:26 +00:00
David Mitchell
5012eebe55 make OP_SPLIT a PMOP, and eliminate OP_PUSHRE
Most ops that execute a regex, such as match and subst, are of type PMOP.
A PMOP allows the actual regex to be attached directly to that op, due
to its extra fields.

OP_SPLIT is different; it is just a plain LISTOP, but it always has an
OP_PUSHRE as its first child, which *is* a PMOP and which has the regex
attached.

At runtime, pp_pushre()'s only job is to push itself (i.e. the current
PL_op) onto the stack. Later pp_split() pops this to get access to the
regex it wants to execute.

This is a bit unpleasant, because we're pushing an OP* onto the stack,
which is supposed to be an array of SV*'s. As a bit of a hack, on
DEBUGGING builds we push a PVLV with the PL_op address embedded instead,
but this still isn't very satisfactory.

Now that regexes are first-class SVs, we could push a REGEXP onto the
stack rather than PL_op. However, there is an optimisation of @array =
split which eliminates the assign and embeds the array's GV/padix directly
in the PUSHRE op. So split still needs access to that op. But the pushre
op will always be splitop->op_first anyway, so one possibility is to just
skip executing the pushre altogether, and make pp_split just directly
access op_first instead to get the regex and @array info.

But if we're doing that, then why not just go the full hog and make
OP_SPLIT into a PMOP, and eliminate the OP_PUSHRE op entirely: with the
data that was spread across the two ops now combined into just the one
split op.

That is exactly what this commit does.

For a simple compile-time pattern like  split(/foo/, $s, 1), the optree
looks like:

    before:
        <@> split[t2] lK
           </> pushre(/"foo"/) s/RTIME
           <0> padsv[$s:1,2] s
           <$> const(IV 1) s

    after:
        </> split(/"foo"/)[t2] lK/RTIME
           <0> padsv[$s:1,2] s
           <$> const[IV 1] s

while for a run-time expression like split(/$pat/, $s, 1),

    before:
        <@> split[t3] lK
           </> pushre() sK/RTIME
              <|> regcomp(other->8) sK
                 <0> padsv[$pat:2,3] s
           <0> padsv[$s:1,3] s
           <$> const(IV 1)s

    after:
        </> split()[t3] lK/RTIME
           <|> regcomp(other->8) sK
              <0> padsv[$pat:2,3] s
           <0> padsv[$s:1,3] s
           <$> const[IV 1] s

This makes the code faster and simpler.

At the same time, two new private flags have been added for OP_SPLIT -
OPpSPLIT_ASSIGN and OPpSPLIT_LEX - which make it explicit that the
assign op has been optimised away, and if so, whether the array is
lexical.

Also, deparsing of split has been improved, to the extent that

    perl TEST -deparse op/split.t

now passes.

Also, a couple of panic messages in pp_split() have been replaced with
asserts().
2016-10-04 11:18:40 +01:00
David Mitchell
4fa06845e7 add OP_ARGELEM, OP_ARGDEFELEM, OP_ARGCHECK ops
Currently subroutine signature parsing emits many small discrete ops
to implement arg handling. This commit replaces them with a couple of ops
per signature element, plus an initial signature check op.

These new ops are added to the OP tree during parsing, so will be visible
to hooks called up to and including peephole optimisation. It is intended
soon that the peephole optimiser will take these per-element ops, and
replace them with a single OP_SIGNATURE op which handles the whole
signature in a single go. So normally these ops wont actually get executed
much. But adding these intermediate-level ops gives three advantages:

1) it allows the parser to efficiently generate subtrees containing
   individual signature elements, which can't be done if only OP_SIGNATURE
   or discrete ops are available;
2) prior to optimisation, it provides a simple and straightforward
   representation of the signature;
3) hooks can mess with the signature OP subtree in ways that make it
   no longer possible to optimise into an OP_SIGNATURE, but which can
   still be executed, deparsed etc (if less efficiently).

This code:

    use feature "signatures";
    sub f($a, $, $b = 1, @c)  {$a}

under 'perl -MO=Concise,f' now gives:

    d  <1> leavesub[1 ref] K/REFC,1 ->(end)
    -     <@> lineseq KP ->d
    1        <;> nextstate(main 84 foo:6) v:%,469762048 ->2
    2        <+> argcheck(3,1,@) v ->3
    3        <;> nextstate(main 81 foo:6) v:%,469762048 ->4
    4        <+> argelem(0)[$a:81,84] v/SV ->5
    5        <;> nextstate(main 82 foo:6) v:%,469762048 ->6
    8        <+> argelem(2)[$b:82,84] vKS/SV ->9
    6           <|> argdefelem(other->7)[2] sK ->8
    7              <$> const(IV 1) s ->8
    9        <;> nextstate(main 83 foo:6) v:%,469762048 ->a
    a        <+> argelem(3)[@c:83,84] v/AV ->b
    -        <;> ex-nextstate(main 84 foo:6) v:%,469762048 ->b
    b        <;> nextstate(main 84 foo:6) v:%,469762048 ->c
    c        <0> padsv[$a:81,84] s ->d

The argcheck(3,1,@) op knows the number of positional params (3), the
number of optional params (1), and whether it has an array / hash slurpy
element at the end. This op is responsible for checking that @_ contains
the right number of args.

A simple argelem(0)[$a] op does the equivalent of 'my $a = $_[0]'.
Similarly, argelem(3)[@c] is equivalent to 'my @c = @_[3..$#_]'.
If it has a child, it gets its arg from the stack rather than using $_[N].
Currently the only used child is the logop argdefelem.

argdefelem(other->7)[2] is equivalent to '@_ > 2 ? $_[2] : other'.

[ These ops currently assume that the lexical var being introduced
is undef/empty and non-magival etc. This is an incorrect assumption and
is fixed in a few commits' time ]
2016-08-03 20:54:40 +01:00
Father Chrysostomos
881018827f Add avhvswitch op
&CORE::keys() et al. will use this to switch between keys and akeys
depending on the argument type.
2016-05-20 22:13:42 -07:00
jimc
0927ade08b better glibc i_modulo bug handling
pp-i-modulo code currently detects a glibc bug at runtime, at the 1st
exec of each I_MODULO op.  This is suboptimal; the bug should be
detectable early, and PL_ppaddr[I_MODULO] updated just once, before
any optrees are built.

Then, because we avoid the need to fixup I_MODULO ops in already built
optrees, we can drop the !PERL_DEBUG_READONLY_OPS limitation on the
alternative/workaround I_MODULO implementation that avoids the bug.

perl.c:

bug detection code is copied from PP(i_modulo),
into S_fixup_platform_bugs(), and called from perl_construct().
It patches Perl_pp_i_modulo_1() into PL_ppaddr[I_MODULO] when needed.

pp.c:

PP(i_modulo_0), the original implementation, is renamed to PP(i_modulo)

PP(i_modulo_1), the bug-fix workaround, is renamed _glibc_bugfix
                it is #ifdefd as before, but dropping !PERL_DEBUG_READONLY_OPS

PP(i_modulo) - the 1st-exec switcher code, is dropped

ocode.pl:

Two i_modulo entries are added to @raw_alias.
- 1st alias:  Perl_pp_i_modulo		    => 'i_modulo'
- 2nd alt:    Perl_pp_i_modulo_glibc_bugfix => 'i_modulo'

1st is a restatement of the default alias/mapping that would be
created without the line.  2nd line is then seen as alternative to the
explicit mapping set by 1st.

Alternative functions are written to pp_proto.h after the standard
Perl_pp_* list, and include #if-cond, #endif wrappings, as was
specified by 2nd @raw_alias addition.

Changes tested by inserting '1 ||' into the 3 ifdefs and bug-detection code.

TODO:

In pp_proto.h generation, the #ifdef wrapping code which handles the
alternative functions looks like it should also be used for the
non-alternate functions.  In particular, there are a handful of
pp-function prototypes that should be wrapped with #ifdef HAS_SOCKET.
That said, there have been no problem reports, so I left it alone.

TonyC: make S_fixup_platform_bugs static, porting/libperl.t was failing.
2016-05-17 16:37:49 +10:00
David Mitchell
20e9643135 split pp_postdec() from pp_postinc() and improve
pp_postinc() handles both $x++ and $x-- (and the integer variants
pp_i_postinc/dec). Split it into two separate functions, as handling
both inc and dec in the same function requires 3 extra conditionals.

At the same time make the code more efficient.

As currently written it:
1) checked for "bad" SVs (such as read-only) and croaked;
2) did a sv_setsv(TARG, TOPs) to return a copy of the original value;
2) checked for a IOK-only SV and if so, directly incremented the IVX slot;
3) else called out to sv_inc/dec() to handle the more complex cases.

This commit combines the checks in (1) and (3) into one single big
check of flags, and for the simple integer case, skips 2) and does
a more efficient SETi() instead.
For the non-simple case, both pp_postinc() and pp_postdec() now call a
common static function to handle everything else.

Porting/bench.pl shows the following raw numbers for
'$y = $x++' ($x and $y lexical and holding integers):

         before    after
         ------    -----
    Ir    306.0    223.0
    Dr    106.0     82.0
    Dw     51.0     44.0
  COND     48.0     33.0
   IND      8.0      6.0

COND_m      1.9      0.0
 IND_m      4.0      4.0
2015-11-10 13:52:34 +00:00
David Mitchell
4c2c31284e split pp_predec() from pp_preinc() and improve
pp_preinc() handles both ++$x and --$x (and the integer variants
pp_i_preinc/dec). Split it into two separate functions, as handling
both inc and dec in the same function requires 3 extra conditionals.

At the same time make the code more efficient.

As currently written it:
1) checked for "bad" SVs (such as read-only) and croaked;
2) checked for a IOK-only SV and directly incremented the IVX slot;
3) else called out to sv_inc() to handle the more complex cases.

This commit combines the checks in (1) and (2) into one single big
check of flags, and anything "bad" simply skips the IOK-only code
and calls sv_dec(), which can do its own checking of read-only etc
and croak if necessary. Porting/bench.pl shows the following raw numbers
for ++$x ($x lexical and holding an integer):

         before    after
       -------- --------
    Ir     77.0     56.0
    Dr     30.0     24.0
    Dw     10.0     10.0
  COND     12.0      9.0
   IND      2.0      2.0

COND_m     -0.1      0.0
 IND_m      2.0      2.0

Even having split the function into two, the combined size of the two new
functions is smaller than the single previous function.
2015-11-10 13:52:34 +00:00
Aaron Crane
262309092c Delete experimental autoderef feature 2015-07-13 14:08:34 +01:00
Father Chrysostomos
5d01050abc Add string- and number-specific bitop types
and also implement the pp functions, though nothing compiles to
these ops yet.
2015-01-31 22:03:50 -08:00
Father Chrysostomos
b77472f98f Add :const anon sub attribute 2015-01-19 20:34:04 -08:00
David Mitchell
fedf30e1c3 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.

Overall,
        bench.pl --tests='/expr::(array|hash)/' ...
gives:
              PRE   POST
           ------ ------

        Ir 100.00 145.00
        Dr 100.00 165.30
        Dw 100.00 175.74
      COND 100.00 132.02
       IND 100.00 171.11

    COND_m 100.00 127.65
     IND_m 100.00 203.90

with cache misses unchanged at 100%.

In general, the more lookups done, the bigger the proportionate saving.
2014-12-07 09:24:55 +00:00
syber
810bd8b704 Speed up method calls like $o->Other::method() and $o->Other::SUPER::method().
It was done by adding new OP_METHOD_REDIR and OP_METHOD_REDIR_SUPER optypes.
Class name to redirect is saved into METHOP as a shared hash string.
Method name is changed (class name removed) an saved into op_meth_sv as
a shared string hash.

So there is no need now to scan for '::' and calculate class and method names
at runtime (in gv_fetchmethod_*) and searching cache HV without precomputed hash.

B::* modules are changed to support new op types.
method_redir is now printed by Concise like (for threaded perl)
$obj->AAA::meth
5        <.> method_redir[PACKAGE "AAA", PV "meth"] ->6
2014-12-02 17:56:48 -08:00
syber
7d6c333c75 speedup for SUPER::method() calls.
In ck_method:
Scan for '/::. If found SUPER::, create OP_METHOD_SUPER op
with precomputed hash value for method name.

In B::*, added support for method_super

In pp_hot.c, pp_method_*:
S_method_common removed, code related to getting stash is
moved to S_opmethod_stash, other code is moved to
pp_method_* functions.

As a result, SUPER::func() calls speeded up by 50%.
2014-11-28 18:10:58 -08:00
Father Chrysostomos
2882b3ff19 Add lvavref op type
This will be used for slurpy array ref assignments.  \(@a) = \(@b)
will make @a share the same elements as @b.
2014-10-11 00:10:13 -07:00
Father Chrysostomos
16b9941261 Add lvrefslice op type 2014-10-10 21:57:01 -07:00
Father Chrysostomos
4c5bab508c Add lvref op type 2014-10-10 21:54:18 -07:00