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

1k views Asked by At

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?

2

There are 2 answers

7
Chas. Owens On

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.

1
Schwern On

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.