How does O=Deparse work, and does Perl have and fold constant arrays?
Asked Answered
O

2

7

I'm wondering, does -MO=Deparse show you all of the Perl optimizations, and why doesn't this get folded in Perl 5.10?

$ perl -MO=Deparse -e'[qw/foo bar baz/]->[0]'
['foo', 'bar', 'baz']->[0];
-e syntax OK

Some on IRC thought that O=Deparse might not be showing it all, but it certainly shows some constant folding.

$ perl -MO=Deparse -e'use constant "foo" => "bar"; foo'
use constant ('foo', 'bar');
'???';
-e syntax OK

Same result if I explicitly write the constant sub. While predictable, it is also rather interesting that the documentation in constant.pm has you create a constant list rather than a constant array. I assume that not just is this not folded like scalar constants but it requires the overhead of creating a new array on every invocation.

$ perl -MO=Deparse -e'use constant foo => qw/foo bar baz/; (foo)[0]'
use constant ('foo', ('foo', 'bar', 'baz'));
(foo)[0];
-e syntax OK

The only conclusion that I can come to is -MO=Deparse is showing all of the folding, and constant arrays are just not optimized out in Perl? Is this so? Is there a technical reason for it?

Ocko answered 24/8, 2010 at 21:32 Comment(1)
I am still confused, why am I getting downvoted for this? Someone drop me a line. Is it because the question is too esoteric? You believe it will entail to much work for any gain? I was just asking if it could be done, and why it isn't done. The leading answer seems to go through the same questions I'm ask. (1) Presume it can't be done for technical reasons (2) then assume it simply isn't done, (3) then speculate it isn't done because it doesn't matter enough.Ocko
A
9

You can't create constant arrays because arrays are not data. Perl 5 has five types of data (things that can be stored in variables):

  • no value (undef)
  • numbers
  • strings
  • references
  • lists (made up of one or more of the previous types)

You can make a constant out of any of those. Perl 5 also has three containers:

  • Scalar
  • Array
  • Hash

Scalars can hold any of the first four types of data, arrays and hashes can hold lists. It is important not to confuse things that hold data and the data itself.

As for B::Deparse, it dumps the optree after it is built, so it will show the results of all constant folding.

I haven't thought about it enough yet, but I do not see any obvious reasons that it couldn't be folded.

Ahlgren answered 24/8, 2010 at 21:48 Comment(7)
Could you explain -MO=Deparse -e'use strict; print {}->[1] vs use strict; print {}->[1]. At some point, strict knows you're trying to get at an invalid reference for an Nth element (ie. that {} is a hash ref). I know we say proverbially that the state strict operates in is compile-time. How does strict know what type of reference this is? Could you possibly explain a little more down that direction?Ocko
@Evan Carroll The strict pragma doesn't catch that, it only cares about declaration of variables ("vars"), banning symbolic references ("refs"), and banning most bareword strings ("subs"). The -> operator dereferences at runtime, which is why we don't get an error until then. If we made -> do constant folding we could probably catch that specific error at compile time.Ahlgren
The rule of thumb has always been that strict doesn't slow down runtime. Things that did that were reserved for warnings.pm. So strict is making a pass over the op-tree at runtime during BEGIN{} and throwing the exception, or strict is asserting the reftype is valid at a speed cost during runtime? -- Or, am I still not getting it.Ocko
The strict pragma can't slow down runtime (unless your runtime contains a new compile time through string eval). All of its affects are at compile time. I believe strict runs as the optree is built, not afterward. You are also still not getting it about strict. This is a Perl 5 runtime error and has nothing to do with strict or warnings. It is analogous to perl -e '$x=$y=0; $x/$y'.Ahlgren
you're totally right, ekk perl -e'die; print {}->[1]' it is a runtime assertion that catches this.Ocko
I would like to note, I'm not yet ready to accept this answer because it seems from your update that you might be convinced it could be folded, but still isn't. I'd like to know yet why it can be in your opinion, and what reasons might prevent it from being.Ocko
@Evan Carroll I have thought about it for a while now and can see no reason it couldn't be folded. I assume the reason it hasn't been optimized yet is that it is rare to have code like [qw/a b c/]->[0], but common to have code like 24 * 60 * 60.Ahlgren
K
8

You can't make a constant array in Perl, there's nothing in the internals to indicate a constant array or hash or even a scalar. "use constant" takes advantage of Perl's ability to inline subroutines with a prototype of () and simple code. The best you can do is set the readonly flag, but that can be switched off at runtime.

Perl could use the readonly flag at compile time as a hint to indicate that the array really is readonly and then inline any access using a constant index. Such a heuristic would probably be safe as the readonly flag isn't supposed to be user-accessible and you probably shouldn't be flipping it off.

Kermis answered 24/8, 2010 at 22:51 Comment(1)
..and if you do, you deserve what you get :)Madai

© 2022 - 2024 — McMap. All rights reserved.