| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
| |
From the added code comments:
XXX DAPM 12/2014: ExtUtils::Embed doesn't seem to provide API access
to $Config{optimize} and so compiles the test code without
optimisation on optimised perls. This causes the compiler to warn
when -D_FORTIFY_SOURCE is in force without -O. For now, just strip
the fortify on optimised builds to avoid the warning.
|
|
|
|
|
|
| |
Subs like sub f () { 42 } stopped being emitted, probably in
v5.21.3-638-g2eaf799, when such subs started being stored as simple
scalar refs in the stash.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Unlike most handle ops, readline does not implicitly add an rv2gv op.
In fact, there is a difference in behaviour, depending on whether
there is an rv2gv op present. An explicit * (rv2gv) will force vivi-
fication of the typeglob, but ‘readline’ alone won’t vivify it.
So B::Deparse should not ignore the rv2gv kid of readline.
Previously, readline(*$foo) (vivifying) would deparse as <$foo> (non-
ivifying), and readline *{$foo} would deparse as readline do { $foo }
(same behavioural difference again).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This fixes #123435 (I hope).
Before v5.21.6-485-gf2279a6, B::Deparse, when deparsing sub calls,
would look in the stash for a sub with a prototype, and use that
prototype for deparsing. (It would only do this for subs that it
itself is not going to deparse.) That caused this to deparse
incorrectly:
BEGIN {
require Test::More;
is("foo", "foo");
}
Because of the presence of the prototyped &main::is by the time
B::Deparse is invoked, it would deparse the is() sub call without
parentheses, resulting in invalid code.
So I changed it to trust only those subs that it has already deparsed.
Now, with coderef2text, B::Deparse doesn’t deparse any subs except the
one passed to it. So *all* prototype sub calls turn into &foo, break-
ing CPAN tests that expect otherwise. While such tests could be con-
sidered too sensitive, I don’t think that this is necessarily a sane
default for coderef2text.
Ideally we should provide the option to tell coderef2text which
subs to trust, the default being to trust all of them. But for
now I will just implement that default, which means reverting
v5.21.6-485-gf2279a6 *for coderef2text*, but not when deparsing the
main program.
|
|
|
|
|
|
|
|
|
| |
Knowing that object fields were globals is no longer useful, unless
one is intimately familiar with a very old version of B::Deparse and
wants to find his way around the new one. (Good luck!)
Furthermore, several of these ‘former globals’ were never globals,
because they came after this comment.
|
| |
|
|
|
|
| |
This is *highly* important. :-)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Same with exec. Don’t put ‘do’ before the block.
This was accomplished by running it through the same code path
(indirop) that print and sort already go through.
There was a slight discrepancy between listop and indirop in the way
they handled no arguments. Before we would get:
() = system;
() = exec;
() = sort();
Instead of making the first two get the redundant parentheses, I
changed indirop, so sort lost them.
|
|
|
|
|
|
|
|
|
|
|
| |
because \my(@a) is different, and produces a list of element refs,
rather than a single reference to the array.
No good:
$ ./perl -Ilib -MO=Deparse -e '\my @x'
\my(@x);
-e syntax OK
|
|
|
|
|
| |
I just broke that in 0175f038c5. I did not realise that OPf_SPECIAL
means two different things on chdir. (See the previous commit.)
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
This does not do the same thing as ‘use v5.16’:
no feature;
use feature ":5.16";
because ‘no feature’ restores the default bundle, and does not disa-
ble array_base, whereas ‘use v5.16’ does. What you need is ‘no fea-
ture ":all"’.
|
| |
|
|
|
|
| |
See the previous commit’s explanation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This reverts commit 1d38190f803f2a83884e9591276436394df55dd4.
$ ./perl -Ilib -MO=-q,Deparse -e 'BEGIN { require "t/test.pl"; is("foo","foo") }'
sub BEGIN {
require 't/test.pl';
is 'foo', 'foo';
}
-e syntax OK
The resulting code doesn’t even compile, because it lacks parentheses
around the arguments to ‘is’, and the function does not exist yet when
that statement is compiled.
The logic that makes ‘is’ lose its parentheses was added by
this commit:
commit 1d38190f803f2a83884e9591276436394df55dd4
Author: Rafael Garcia-Suarez <rgarciasuarez@gmail.com>
Date: Tue Jan 1 23:45:21 2002 +0100
alternate way to figure out prototypes
Message-ID: <20020101224521.A691@rafael>
p4raw-id: //depot/perl@14007
Previously, B::Deparse would put & on any prototyped sub call if it
were not deparsing the sub itself, because it is not possible to tell
exactly when the sub will be defined when the program loads. (That is
still true.)
That meant is(@foo, @bar) would be deparsed as &is(@foo, @bar), which
is wrong, because the arrays are not evaluated in scalar context.
(test.pl and Test::More both have prototypes beginning with $$ for
‘is’.) 1d38190f8 was meant to fix that, and did so by respecting the
prototype if the sub exists and B::Deparse is not going to emit it
(e.g., because it’s in another file than the main program).
As of v5.21.6-321-gc65b7c4, & calls include ‘scalar’ where necessary,
so the fix from 1d38190f8 is no longer necessary.
|
|
|
|
|
|
| |
It was added by perl-5.6.0-8936-g7821065. The corresponding comment
in pp_sort.c that it refers to, also added by the same commit, was
removed in perl-5.8.0-5345-g5fe61d9.
|
|
|
|
|
| |
require(v5.16) does not work. I broke this by adding the parens in
917a8f4f52.
|
|
|
|
| |
$#1 is a syntax error.
|
|
|
|
| |
@- and @+ do not interpolate in regular expressions.
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is no good:
$ ./perl -Ilib -MO=Deparse -e '/@a/'
@a;
-e syntax OK
This was probably broken in 5.18 when arrays interpolated into regular
expressions stopped getting a ‘join’ op and started being handled by
the regexp parser directly.
|
|
|
|
|
| |
These typemaps (which are ancient; mostly going back to 1994 or so)
each leaked a GV and an RV.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is wrong:
$ perl -MO=Deparse -e 'foo(); sub foo { foo() } foo()'
foo();
sub foo {
foo ;
}
foo ;
-e syntax OK
You need foo() inside sub foo{}. The parentheses are not optional.
The sub was being introduced (Deparse was recording is as declared)
just before the definition was emitted.
|
|
|
|
|
| |
-1 less asm op for every very rarely executed branch on threaded perl
-add a build product to ignore on the rarely tested Win32 static perl build
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Prior to commit c310a5abf, ‘use’ statements in packages other than
main were emitted as BEGIN blocks, because the code that decides
whether BEGIN is actually ‘use’ was looking for "BEGIN", not
"Foo::BEGIN":
$ perl -MO=Deparse -e 'package foo; use overload'
package foo;
sub BEGIN {
require overload;
do {
'overload'->import
};
}
-e syntax OK
That changed inadvertently in v5.21.6-397-gc310a5a (Don’t deparse
BEGIN blocks as __ANON__), because B::Deparse now remembers the name
"BEGIN" for all BEGIN blocks, regardless of package.
That caused an existing bug to occur more often:
$ perl5.20.1 -MO=Deparse -e 'package foo; die; package main; use overload qr=>sub{die}'
package foo;
die;
use overload ('qr', sub {
die;
}
);
-e syntax OK
Notice that there is no ‘package main’ anywhere. (Just before c310a5a
the ‘package main’ would have appeared inside the anonymous sub.)
In c310a5a this started applying to packages other than main, with a
‘use’ statement just after the package declaration.
This commit fixes that by returning the ‘use’ statement only *after*
doing the check to see whether there was a package declaration, and by
including the package declaration in what is returned.
|
|
|
|
|
|
|
|
|
|
| |
Otherwise code like this:
use utf8;
my $e = qr"BöckĀ";
deparses in Latin-1 and running the output results in malforma-
tion errors.
|
|
|
|
|
| |
B::Deparse depends on this to get the BEGIN blocks in the right place
if they occur inside predeclared subs.
|
|
|
|
|
|
|
|
|
|
|
| |
There are various ways in which the *BEGIN glob could be freed, caus-
ing the BEGIN block to become anonymised. E.g., it can happen if a
*BEGIN rv2gv op is created and freed at compile time. (This commit
deletes it more explicitly in Deparse.t, to make the test robust.)
And the BEGIN block’s relationship to the typeglob it started out in
is only incidental once it has been detached. So for special blocks
we should be deciding the name based on which array (beginav, etc.) we
got it from, and not using the name of the glob the sub points to.
|
|
|
|
|
| |
This was broken in v5.21.5-289-g12cea2f. We were trying to check the
kid op of an ex-const, but an ex-const has no children.
|
|
|
|
|
|
|
|
|
|
| |
B::Deparse was taking special care to preserve whitespace for /x pat-
terns, and avoid changing newlines to \n, etc. But it was not tak-
ing (?x) into account. Parsing regular expressions to apply the
right escapes to different parts of the regexp is too compli-
cated, so this commit changes it to treat all regular expres-
sions the way it was treating /x expressions. This causes
‘cd t; ./perl TEST -deparse run/switchM.t’ to pass.
|
|
|
|
|
|
|
| |
Entersub gets the LVINTRO flag, but it does *not* represent local().
It’s an exception to the general rule.
This was probably broken in 12cea2fa65.
|
| |
|
| |
|
|
|
|
|
| |
See the previous commit. The same applies to loop controls and similar
keywords.
|
|
|
|
|
|
|
|
|
|
| |
require(foo()) deparses as require foo(). But require’s parsing is
eccentric, and does not allow require foo(), because ‘foo’ is treated
as a bareword there, and ‘require WORD’ does not allow () fol-
lowing it.
The same problem happens with do-file, which is fixed also by this
commit, since it follows the same code path.
|
|
|
|
| |
unop calls $self->keyword, so we don’t need to.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is wrong:
$ ./perl -Ilib -mO=Deparse,-P -e 'sub foo($$){}; foo(bar(), baz())'
sub foo ($$) {
}
&foo(bar(), baz());
-e syntax OK
The resulting code calls bar and baz in list context.
|
|
|
|
|
| |
I’m about to modify this code, and having two copies of the join(...)
is not so helpful.
|
|
|
|
|
|
|
|
|
|
| |
Before this, we were escaping all non-ASCII chars if the string con-
tained any non-printable chars. So ".\x{100}" would come out exactly
like that, but "\x{100}" would be deparsed as "Ā", causing problems if
the script has no ‘use utf8’ in scope.
(It was also misbehaving on EBCDIC, causing the existing \x
test to fail.)
|
|
|
|
|
| |
(LIST)[INDEX] is neat, but it doesn’t short-circuit, so it should not
be used if LIST contains method calls.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Formats need the same logic applied in 34b54951568, to avoid this:
Input:
{
my $x;
format STDOUT =
@
$x
.
}
__END__
$ pbpaste|./perl -Ilib -MO=Deparse
{
my $x;
}
format STDOUT =
@
$x
.
__DATA__
- syntax OK
That $x in the format is now global, not lexical.
Also, we need to make sure the sequence numbers are correct. The
statement after the format stopped having a higher sequence number
than CvOUTSIDE_SEQ(format) in 8635e3c238f, because the ‘pending’
sequence number set aside for the nextstate op created just after com-
pile-time block exit (which nextstate op comes before the block) was
not actually being used by newFORM (unlike newATTRSUB), so the follow-
ing statement was using that number.
|
|
|
|
|
|
|
|
| |
34b54951 caused a program that is empty apart from sub definitions to
be deparsed with ‘();’ for the main sub. Previously it was omitted.
This commit removes it, not only for the sake of backward-compatibil-
ity, but also because ‘();’ is not a particularly sane way of dumping
an empty program.
|
|
|
|
|
|
|
| |
Creating a weak reference to a stash entry will cause it to be of type
PVMG, if it was not a GV already. B::Deparse was trying to determine,
based on the internal SV type, whether it had a sub stub. It should
be checking flags instead, otherwise valid stubs get omitted.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A predeclared sub without a prototype works fine:
$ ./perl -Ilib -MO=Deparse -e 'sub f; sub f{}; foo()'
sub f {
}
foo();
-e syntax OK
A prototyped sub with no predeclaration is fine:
$ ./perl -Ilib -MO=Deparse -e ' sub f($){}; foo()'
sub f ($) {
}
foo();
-e syntax OK
A prototyped stub is fine:
$ ./perl -Ilib -MO=Deparse -e 'sub f($); foo()'
sub f ($);
foo();
-e syntax OK
Only a predeclared prototyped sub seems to have trouble appear-
ing properly:
$ ./perl -Ilib -MO=Deparse -e 'sub f($); sub f($){}; foo()'
sub f;
foo();
-e syntax OK
The code that searches the stashes (stash_subs) was assuming that any-
thing of type B::PV was a prototype. In this case, the stash entry
started as a string and then got ‘downgraded’ to a reference, so
internally it is of type PV (which can hold a ref), which B represents
as B::PV, so the assumption that a PV is a prototyped stub is wrong.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
$ perl5.20.1 -mO=Deparse,-l -e 'format =' -e\@ -e'$foo' -e.
format STDOUT =
@
$foo
.
-e syntax OK
$ ./perl -Ilib -mO=Deparse,-l -e 'format =' -e\@ -e'$foo' -e.
format STDOUT =
@
#line 3 "-e"
; $foo
.
-e syntax OK
The second is not valid syntax.
I probably broke that when fixing BEGIN blocks.
|
|
|
|
|
|
|
|
|
|
| |
Instead of sometimes appending ; to statements and then removing it
later, to avoid doubling it up, *only* append ; to a statement when
actually joining them together or emitting them. That fixes bugs with
do{$;} becoming do {$} and ‘$_=$;; $;=7;’ becoming ‘$_=$; $;=7;’.
I also removed the boilerplate from pp_stub, since it was redundant
(and slow) and also partially wrong. The $name var was bogus.
|
|
|
|
| |
added in d4f1bfe749f, which got merged before the PADNAME changes.
|
|
|
|
|
| |
In 4b1385ee6 I did not realise we already had \cK, which served almost
the same purpose.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This code deparses incorrectly under taint mode:
$ ./perl -Ilib -mO=Deparse -e '$x =~ (1?/$a/:0)'
$x =~ ($_ =~ /$a/);
-e syntax OK
$ ./perl -Ilib -mO=Deparse -T -e '$x =~ (1?/$a/:0)'
$x =~ /$a/;
-e syntax OK
The branch folding makes it deparse as ‘$x =~ /$a/’, whereas the /$a/
on the rhs, since it was not the argument to =~, is bound to $_, not
to $x. That’s why B::Deparse adds the $_ =~, but it fails to do so
under taint mode.
It was broken by:
commit 7fb31b92fa6bf56dff7d4240b7051b9158f7df43
Author: David Mitchell <davem@iabyn.com>
Date: Sun Apr 1 10:21:22 2012 +0100
make OP_REGCRESET only for taint handling
The OP_REGCRESET op, which is sometimes prepended to the chain of ops
leading to OP_REGCOMP, currently serves two purposes; first to reset the
taint flag, and second to initialise PL_reginterp_cnt. The second purpose
is no longer needed, and the first has a bug, in that the op isn't
prepended when "use re 'eval'" is in scope.
Fix this by prepending the op solely when PL_tainting is in effect.
This also makes run-time regexes slightly more efficient in the
non-tainting case.
which has a typo in it.
|
|
|
|
|
|
|
|
|
|
| |
Before, s/$a(?{die})// would deparse like this:
s/${a}do {
die
}(?{die})//;
Now it deparses correctly.
|