[Perl/perl5] 939d20: Add OP_REF_CMP to optimize (ref $x eq/ne 'SCALAR')...
[email protected] (Richard Leach via perl5-changes) Mon, 27 Jul 2026 03:05:59 -0700
| Newsgroups | perl.perl5.changes |
|---|---|
| Message-ID | <Perl/perl5/push/refs/heads/blead/[email protected]> |
Branch: refs/heads/blead
Home: https://github.com/Perl/perl5
Commit: 939d200deae641b5f24bb5cc2d5e3731cd30f3c0
https://github.com/Perl/perl5/commit/939d200deae641b5f24bb5cc2d5e3731cd30f3c0
Author: Richard Leach <[email protected]>
Date: 2026-07-27 (Mon, 27 Jul 2026)
Changed paths:
M ext/B/t/b.t
M ext/Opcode/Opcode.pm
M lib/B/Deparse.pm
M lib/B/Deparse.t
M lib/B/Op_private.pm
M op.c
M opcode.h
M opnames.h
M peep.c
M pp.c
M pp_proto.h
M regen/embed.pl
M regen/op_private
M regen/opcodes
M sv.c
M t/op/ref.t
M t/perf/benchmarks
M t/perf/opcount.t
Log Message:
-----------
Add OP_REF_CMP to optimize (ref $x eq/ne 'SCALAR') patterns
Finding value of `ref`, comparing it to a specific one of Perl's
builtin types, and doing something with that boolean result is
currently a fair bit of work.
if (ref $x eq 'SCALAR) { # do something }
or
if (ref $x ne 'SCALAR) { # do something }
The type of `$x` has to be determined and the string value for it
pushed onto the stack, the value to compare it to is also pushed,
a string comparison is then performed, with `&PL_sv_yes` or
`&PL_sv_no` put on the stack to be consumed by a LOGOP in order to
determine the control flow.
The optree looks something like this:
4 <;> nextstate(main 2 -e:1) v:{ ->5
- <1> null vK/1 ->d
9 <|> and(other->a) vK/1 ->d
8 <2> seq sKP/2 ->9
6 <1> ref[t2] sK/1 ->7
5 <0> padsv[$x:1,2] s ->6
7 <$> const[PV "SCALAR"] s/BARE ->8
This commit instead adds an OP_REF_CMP optimization, generating
an optree like this instead:
4 <;> nextstate(main 2 -e:1) v:{ ->5
- <1> null vK/1 ->b
7 <|> and(other->8) vK/1 ->b
6 <1> ref_cmp sKP/SCALAR,SKIPLOGOP,AND ->7
5 <0> padsv[$x:1,2] s ->6
OP_REF_CMP determines the type of the operand, more efficiently
compares it to the desired type (baked into the OP's flags),
and directly calls the `op_other` or `op_next` of the LOGOP.
The existing classname handling behaviour is preserved.
$x = bless {}, "ARRAY";
if (ref $x eq "ARRAY") {} # This *is* still true.
This commit also optimizes the same sort of patterns that use `reftype`
instead of `ref`. The behaviour differences between the two are
preserved.
As there were spare bits available, some additional common comparators
have also been baked in:
* `Regexp` - for the `qr//` case with `ref`
* `''` - the empty string
Commit: f7504b2b932ed510a2d733413e7848d452cb840f
https://github.com/Perl/perl5/commit/f7504b2b932ed510a2d733413e7848d452cb840f
Author: Richard Leach <[email protected]>
Date: 2026-07-27 (Mon, 27 Jul 2026)
Changed paths:
M embed.fnc
M embed.h
M ext/B/Makefile.PL
M lib/B/Deparse.pm
M lib/B/Op_private.pm
M op.c
M opcode.h
M pp.c
M proto.h
M regen/embed.pl
M regen/op_private
M sv.c
M sv.h
Log Message:
-----------
Add PL_sv_reftype_lookup & Perl_sv_reftype_id
To avoid duplication of "what reference type is this?" logic across
`Perl_sv_reftype` and `pp_ref_cmp`, this commit:
* Renames `OPpREF_CMP_*` constants to `SVrt_*` equivalents
* Adds a `PL_sv_reftype_lookup` table ordered to match those constants
* Adds a `Perl_sv_reftype_id` function that takes the logic from
`Perl_sv_reftype` but returns only an index ID value
* `Perl_sv_reftype` uses that new function and table to return strings
* `pp_ref_cmp` uses the function and compares to the expected ID value
Commit: d97ad8ae554909fd88d9c2a84108c4aa446553f9
https://github.com/Perl/perl5/commit/d97ad8ae554909fd88d9c2a84108c4aa446553f9
Author: Richard Leach <[email protected]>
Date: 2026-07-27 (Mon, 27 Jul 2026)
Changed paths:
M pod/perldelta.pod
Log Message:
-----------
perldelta for OP_REF_CMP
Compare: https://github.com/Perl/perl5/compare/acdbee4511e9...d97ad8ae5549
To unsubscribe from these emails, change your notification settings at https://github.com/Perl/perl5/settings/notifications