Paul "LeoNerd" Evans
2024-10-09 00:09:36 UTC
I have a (draft) PR in progress to implement a performance boost on
code of the form
foreach my ($idx, $val) (builtin::indexed @array) {
...
}
by using the same CXt_LOOP_ARY optimisation that regular
single-variable foreach on a single array uses. Since this keeps track
of the array index anyway, we get to use it "for free" by assigning it
into the $idx var, and thus avoid the need for an entire temporary
list. Seems good.
There's one problem with this PR currently which is why it's still in
draft. In order to make it work, the code that builds the optree for
a `for` loop (which lives in `op.c`) needs to be able to check that the
CV target of an `OP_ENTERSUB` that is its iteration-list expression
definitely points to the builtin::indexed function. That function lives
in `builtin.c`, a different C file. We don't currently give XSUB
functions a prototype in a .h file, so they can't be seen.
Hence, the horrible hack in the file that is this line:
https://github.com/Perl/perl5/pull/22641/files#diff-e70a9c5c0a9ba08a5e8ac7323e5f796732577f22a3845c573f1e347aaccfb755R174-R175
I'm not currently aware of any existing precedent for doing this
another nicer way. In various other places of code where (typically)
some opchecker in op.c needs to be aware of specific optree shapes, it
can use the opcodes of the individual ops. But builtin *functions* are
just that - functions. Regular functions called with regular
OP_ENTERSUB. So it can't check the opcode. It has to rely on the CV
address instead.
I could just declare the prototype for this function in some .h file
somewhere, and call it done. But it'd be a weird oddball of a case we
don't do anywhere else.
Before I undraft the PR, does anyone have any better ideas?
code of the form
foreach my ($idx, $val) (builtin::indexed @array) {
...
}
by using the same CXt_LOOP_ARY optimisation that regular
single-variable foreach on a single array uses. Since this keeps track
of the array index anyway, we get to use it "for free" by assigning it
into the $idx var, and thus avoid the need for an entire temporary
list. Seems good.
There's one problem with this PR currently which is why it's still in
draft. In order to make it work, the code that builds the optree for
a `for` loop (which lives in `op.c`) needs to be able to check that the
CV target of an `OP_ENTERSUB` that is its iteration-list expression
definitely points to the builtin::indexed function. That function lives
in `builtin.c`, a different C file. We don't currently give XSUB
functions a prototype in a .h file, so they can't be seen.
Hence, the horrible hack in the file that is this line:
https://github.com/Perl/perl5/pull/22641/files#diff-e70a9c5c0a9ba08a5e8ac7323e5f796732577f22a3845c573f1e347aaccfb755R174-R175
I'm not currently aware of any existing precedent for doing this
another nicer way. In various other places of code where (typically)
some opchecker in op.c needs to be aware of specific optree shapes, it
can use the opcodes of the individual ops. But builtin *functions* are
just that - functions. Regular functions called with regular
OP_ENTERSUB. So it can't check the opcode. It has to rely on the CV
address instead.
I could just declare the prototype for this function in some .h file
somewhere, and call it done. But it'd be a weird oddball of a case we
don't do anywhere else.
Before I undraft the PR, does anyone have any better ideas?
--
Paul "LeoNerd" Evans
***@leonerd.org.uk
http://www.leonerd.org.uk/ | https://metacpan.org/author/PEVANS
Paul "LeoNerd" Evans
***@leonerd.org.uk
http://www.leonerd.org.uk/ | https://metacpan.org/author/PEVANS