Skip to content

Perl_newSLICEOP: Optimise '(caller)[0]' into 'scalar caller' #23369

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: blead
Choose a base branch
from

Conversation

richardleach
Copy link
Contributor

@richardleach richardleach commented Jun 12, 2025

A subroutine can obtain just the package of its caller in a couple of ways. Both seem somewhat common.

  • caller - in scaler context, as in my $x = caller;
  • (caller)[0], as in my $x = (caller)[0];

In the first, caller finds the package name, sticks it in a new SV, and puts that (or undef) on the stack:

<0> caller[t2] s

In the second, caller (a) finds the package name, filename, and line (b) creates three new SVs to hold them all (c) puts those SVs on the stack (d) does a list slice to leave just the package SV on the stack.

7        <2> lslice sK/2 ->8
-           <1> ex-list lK ->5
3              <0> pushmark s ->4
4              <$> const[IV 0] s ->5
-           <1> ex-list lK ->7
5              <0> pushmark s ->6
6              <0> caller[t2] l ->7

This commit checks for the second case inside Perl_newSLICEOP and instead of constructing a lslice OP, returns just the caller OP with scalar context applied.


  • This set of changes does not require a perldelta entry.

A subroutine can obtain just the package of its caller in a couple of ways.
Both seem somewhat common.

 * `caller` - in scaler context, as in `my $x = caller;`
 * `(caller)[0]`, as in `my $x = (caller)[0];`

In the first, `caller` finds the package name, sticks it in a new SV, and
puts that (or `undef`) on the stack:

    <0> caller[t2] s

In the second, `caller` (a) finds the package name, filename, and line
(b) creates three new SVs to hold them all (c) puts those SVs on the stack
(d) does a list slice to leave just the package SV on the stack.

    7        <2> lslice sK/2 ->8
    -           <1> ex-list lK ->5
    3              <0> pushmark s ->4
    4              <$> const[IV 0] s ->5
    -           <1> ex-list lK ->7
    5              <0> pushmark s ->6
    6              <0> caller[t2] l ->7

This commit checks for the second case inside `Perl_newSLICEOP` and
instead of constructing a `lslice` OP, returns just the `caller` OP
with scalar context applied.
@richardleach richardleach added the defer-next-dev This PR should not be merged yet, but await the next development cycle label Jun 12, 2025
@bulk88
Copy link
Contributor

bulk88 commented Jun 12, 2025

https://grep.metacpan.org/search?size=20&_bb=86025425&q=%5C%28caller%5C%29%5C%5B&qft=*.pm%2C+*.t&qd=&qifl=

Should've been done 30 years ago. Most PP devs think (caller())[\w] is constant folded as if Perl is identical to C++. The truth is list context PP context() is like writing a 100MB core dump to a SSD everytime you execute it. caller() shouldve never ever have become Perl best practices/cargo culted. There is nothing wrong with caller's public PP API IMO, but b/c of its horrible runtime internal implementation, it shouldve been sent to the landfill, by use strict; on day 1 of use strict;, just like this Perl 5 code was sent to the landfill by use strict;

C:\Users\Owner>perl -e" push( @a, THISS); push( @a, ISS); push( @a, PERL); $, =' '; print @a;"
THISS ISS PERL
C:\Users\Owner>

Rich, would you pretty please be able to tackle adding OP tree compile time next gen G_VOID propagation to the other 12-15 list context retval indexes/retval SV*s created by pp_caller?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
defer-next-dev This PR should not be merged yet, but await the next development cycle
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants