| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The padrange optimisation was only happening if the op tree was laid
out in a way that would allow B::Deparse easily to restore the origi-
nal op_next pointers (via $B::overlay) for the sake of deparsing.
It turns out that B::Deparse doesn’t even use the op_next pointers
(except for deparsing ‘use’ statements, which are not affected here),
so there is no need for these restrictions.
In the case of my($a,$b)=@_, @_ was expected to be the sibling of the
preceding pushmark-cum-padrange. Removing that restriction doesn’t
allow the padrange optimisation to happen in any new cases as far as I
can tell. It just means there is less checking to do.
In the more general case of a list of lexicals with no =@_, this
allows padrange to be used for array and hash slices in conjunction
with a separate list-in-list-context optimisation, that formerly con-
flicted with padrange.
When we compile @a[$lex1,$lex2], we end up with a redundant list-in-
list-context:
7 aslice
1 pushmark
5 list
2 pushmark
3 padsv
4 padsv
6 padav (assuming the array is lexical
Pushmark pushes a mark on to the markstack, and list pops one, so
pushmark and list cancel each other out in list context.
In 5.18, when padrange was introduced, this was optimised like this:
5 aslice
1 pushmark
3 list
2 padrange
- padsv
- padsv
4 padav
Then a separate optimisation was added in 5.20 that allows a list
with a pushmark kid to turn into null ops, and this cancelled out
the padrange:
5 aslice
1 pushmark
- ex-list
- ex-pushmark
2 padsv
3 padsv
4 padav
Bunchmarks show that this is slightly faster than padrange with two
lexicals, but more lexicals would make padrange faster. This commit
brings us the goodness of both optimisations at once:
3 aslice
1 padrange
- ex-list
- ex-pushmark
- padsv
- padsv
2 padav
And it is faster than just one optimisation.
|
| |
|
|
|
|
|
|
| |
this TODO has been passing on my smoke testers for years, if it turns
out it isn't passing for someone, it should probably be skipped
instead of TODOed to prevent the noise.
|
|
|
|
|
|
| |
on Windows (cygwin) I was getting rare failures creating $copy1 with
an error complaining that it was a directory, possibly due to some
background process tracking directories.
|
| |
|
|
|
|
|
|
|
|
| |
srefgen is faster than refgen, since it doesn’t have to loop through
the arguments (there is only one) and there is no pushmark to execute.
OA_RETSCALAR causes scalar context to be applied to anoncode ops, but
it always returns one item anyway, so that causes no problems.
|
|
|
|
|
| |
Also correct the description of lvref magic. When it was first added,
it was for list assignments only, but that soon changed.
|
|
|
|
| |
The other experimental features already have nice warnings in feature.pm
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
After eliding the varop, the optimisation added in 5afbd733 repro-
cesses the previous op if it is a nextstate op. But it was doing this
by setting the current op to the one before the nextstate, so that the
o=o->op_next in the loop header would cause it to reprocess the next-
state in the next iteration. So, if that nextstate op were at the
beginning of a subroutine, the optimisation would be skipped, and this
would still execute two nextstate ops in a row:
sub foo {
our($a, $b);
die;
}
So, instead, just use ‘goto’ to reprocess the op, and we can do it
even if there is no op before the nextstate.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
our($foo) in void context has a compile-time affect but no run-item
effect, except to execute ops needlessly. There is no need to execute
those ops. We can simply remove them from the execution order.
‘our($foo,$fit,$far);’ still leaves a list and a pushmark, which I
plan to eliminate in the next commit.
‘our $foo; our $bar; our $baz;’ has no run-time cost now, because,
once the variables are eliminated, the nextstate ops in betwen them,
now adjacent, are also eliminated by another optimisation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I optimised join into stringify if it had a list of one scalar-
returning op.
$ ./perl -Ilib -MO=Deparse -e '$_ = join $foo, $bar'
$_ = "$bar";
-e syntax OK
The problem, though, is that we now create op trees that didn’t happen
before,* and B::Deparse can’t handle them correctly:
$ ./perl -Ilib -MO=Deparse -e '$_ = join $foo, pos'
$_ = "pos($_)";
-e syntax OK
So we need to turn that into:
$_ = join('???', pos);
* Actually, in 5.8 it was possible to interpolate arbitrary expres-
sions after ‘$_[0]->’:
$_ = "\n,rekcah lreP rehtona tsuJ"; sub a{chop}
print "${[bless[]]}[0]->a . reverse $_";
And that, consequently, did not deparse properly.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Executing two nextstate ops in a row is equivalent to executing just
the second, so the peephole optimiser eliminates one of them.
The double-nextstate optimisation seems to have been written under
the assumption that the current op cannot be elided from the op_next
change, which is untrue, as we have oldop (the previous op in
the chain).
If the current op and the one following it are both nextstate ops,
then the contents of the second are moved over to the first and the
second is nulled. Then current_op->op_next is adjusted to skip over
the newly-nulled op.
The the next op in the chain, the one that the first nextstate op now
points to, is processed.
The result is that every other nextstate in sequence of three or more
would be elided:
1 <;> nextstate(main 1 -e:1) v ->2
- <0> ex-const v ->-
- <0> null v ->-
- <0> ex-const v ->2
2 <;> nextstate(main 1 -e:1) v:{ ->3
- <0> ex-const v ->-
- <0> null v ->-
- <0> ex-const v ->3
3 <;> nextstate(main 1 -e:1) v:{ ->4
- <0> ex-const v ->-
- <0> null v ->-
- <0> ex-const v ->4
4 <;> nextstate(main 1 -e:1) v:{ ->5
We don’t need to go through the complication of making the first next-
state equivalent to the second. Just null the first one and adjust
the previous op’s pointer (oldop->op_next) to point to the second one.
Now all consecutive nextstates get nulled except the last:
- <0> ex-nextstate v ->-
- <0> ex-const v ->-
- <0> ex-nextstate v ->-
- <0> ex-const v ->-
- <0> ex-nextstate v ->-
- <0> ex-const v ->-
- <0> ex-nextstate v ->-
- <0> ex-const v ->-
- <0> ex-nextstate v ->1
- <0> ex-const v ->-
- <0> ex-nextstate v ->1
- <0> ex-const v ->1
1 <;> nextstate(main 1 -e:1) v:{ ->2
The only visible difference this makes is in B::Deparse output, but
this changed in 5.14 when the optimisation was first introduced, so I
think changing it again is acceptable:
$ perl5.12.4 -MO=Deparse -e 'use strict; 0; use warnings; 0'
use strict 'refs';
'???';
use warnings;
'???';
-e syntax OK
$ perl5.14.4 -MO=Deparse -e 'use strict; 0; use warnings; 0'
use warnings;
use strict 'refs';
'???';
;
'???';
-e syntax OK
$ ./perl -Ilib -MO=Deparse -e 'use strict; 0; use warnings; 0'
;
'???';
use warnings;
use strict;
'???';
-e syntax OK
|
|
|
|
|
|
|
|
|
|
| |
In Cwd.pm, dont search for pwd on Win32.
Also trim down the list of makefile suffixes on Win32 so it doesn't try
searching for av.pas and perl.f90 and hash.cbl on disk.
Add __END__ tokens to stop the last read() call on the handle which
returns 0 bytes at EOF.
|
|
|
|
|
|
| |
Some lines end with spaces, remove that, use tabs instead of spaces in code
so the perl code is less bytes to read from disk. This patch saved 183
bytes. Part of [perl #122955].
|
|
|
|
|
|
|
|
| |
warnings.pm is the hottest file/takes the most read() calls of any
module during a make all. By moving POD to the end, ~40KB of OS read()
IO was reduced to ~16KB of OS read() IO calls. Also the parser doesn't need
to search for Perl code in the POD further lessining load time because of
the __END__ token. Filed as [perl #122955].
|
|
|
|
| |
instead of stringify(join(...)).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Due to the exigencies of the implementation, "$_->$*" ends up with a
join op (join $", $$_), which is unnecessary. This gave me the idea
of folding it where possible (instead of trying to tackle it in
toke.c), which would also make explicit joins benefit, too.
If the arguments are a simple scalar or constant followed by a
single-item list, then the join can become a stringify, and the sepa-
rator can simply disappear.
Further (and this is unrelated to "$_->$*"), if all of join’s argu-
ments are constant, the whole thing can be folded to a const op.
|
|
|
|
|
|
|
| |
Even though we can’t optimise away the array op for my(@array),
local(@array), and @{foo()}, we can still optimise away the assign-
ment. Just have split pop the array off the stack and Bob’s
your Uncle.
|
|
|
|
|
|
|
|
|
|
|
|
| |
‘@pkgary = split //, $foo’ gets optimised such that the split writes
directly to the array and the assignment doesn’t have to happen.
This commit makes it work also with lexical arrays. It only works for
arrays declared previously; ‘my @a = split’ doesn’t get optimised,
just as ‘local @a = split’ doesn’t.
The pad offset is stored in the op_targ field of the pushre op, just
as the GV is stored in its op_pmreplrootu field.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Currently B::Deparse deparses ‘our @F;’ as ‘our @F;’, but ‘our @F =...’
as ‘our(@F) = ...’, adding parentheses. For split-to-array, it just
happens to omit the parentheses, because there is no list op for it
to process, and it is when processing a list op that it decides to put
them there. While it could be changed to omit the parentheses for the
list or add them for split-to-array, for now just make the test more
tolerant, as this is just a cosmetic difference.
|
| |
|
|
|
|
|
| |
Only \state(@_) was handling this correctly, as pp_lvavref
calls pp_padav.
|
|
|
|
|
| |
An lvalue reference used as an iterator variable will be implemented
using an lvref op with this flag set.
|
| |
|
|
|
|
|
| |
This will be used for slurpy array ref assignments. \(@a) = \(@b)
will make @a share the same elements as @b.
|
|
|
|
| |
to avoid conflicting with OPpPAD_STATE.
|
| |
|
| |
|
| |
|
|
|
|
| |
\($x,$y)=... does not work yet, but \(my $x) and (\$x, \$y) do.
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
$ ./perl -Ilib -MO=Deparse -e 'our @x = split //, $a'
@x = split(//, $a, 0);
The ‘our’ disappears because ‘split’ swallows up the assignment and
writes to @x directly. But the result is that no OUR_INTRO flag is
left in the op tree.
Fixing this based on the current op tree is very complicated. So
this commit sets the flag on the split op and makes B::Deparse
look for it.
|
|
|
|
|
| |
The ‘local’ was being omitted. I missed the list form of
‘local our’ in commit f351564117.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
B::Deparse was emitting ‘foreach my’ instead of ‘foreach state’.
This example prints 1:
use feature ':all'; no warnings experimental;
sub f {
my sub foo;
foo(), return if @_;
for state $x (1) {
f(1);
sub foo { print $x, "\n" }
}
}
f()
If you change ‘state’ to ‘my’, it prints nothing.
So there is a difference between ‘for my’ and ‘for state’. (At first
I thought there might not be.)
|
|
|
|
| |
It was identical to one 3 tests earlier.
|
|
|
|
|
|
|
|
| |
Commit 3188a8216 took care of the majority of cases making mostly gen-
eral changes.
This commit finishes up all the weird keywords that need spe-
cial handling.
|
|
|
|
|
|
|
|
|
|
|
| |
In commit a958cfbb8 I used eval{prototype "CORE::..."} to see whether
something is a keyword, not realising that we have a __DIE__ hand-
ler that squeaks every time. It is only installed when Deparse is
invoked via -MO.
Localising $SIG{__DIE__} does the trick. Localising $@ as well is a
good idea when using eval, though I haven’t checked whether that was
causing problems.
|
|
|
|
|
|
|
|
| |
If a lexical sub with the same name as a keyword is in scope, we need
to deparse the keyword with a CORE:: prefix.
This commit handles most of the cases, but there are a few exceptional
cases remaining.
|
|
|
|
|
|
| |
In a958cfbb8, I accidentally changed this to test ‘test::foo()’,
rather than ‘foo()’ deparsing as ‘test::foo()’, which was what I
had intended.
|
|
|
|
|
|
|
| |
While B::Deparse was correctly applying CORE:: as necessary to dis-
ambiguate between keywords and custom subroutines, it was not doing
likewise for subroutines whose names were keywords. main::foo()
should be deparsed as main::foo() if ‘foo’ is a keyword.
|
|
|
|
|
|
| |
This list is for keywords exempt from the checks that make sure all
keywords have been tested. __SUB__ *is* tested, so it does not
belong here.
|
|
|
|
|
|
| |
22584011 did not take the looks-like-a-function rule into account.
not ($1 || 2) ** 2 means (not ($1 || 2)) ** 2.
|
| |
|