Mailing List Archive

adjacent defer blocks almost get skipped
This is a bug report for perl from zefram@fysh.org,
generated with the help of perlbug 1.44 running under perl 5.37.10.


-----------------------------------------------------------------
<!--[Please describe your issue here]-->

The peephole optimiser contains an erroneous optimisation for pushdefer
ops\: if multiple pushdefers are adjacent in the op\_next chain\,
separated only by null ops\, then the later ones get elided from the
op\_next chain and so will not be executed\. This is an application of
the shortcircuit threading optimisation that applies to cmpchain\_and
and a few other op types that perform some kind of \(associative except
for magic\) test to decide whether to chain their op\_next or
op\_other\. It is erroneous to apply this optimisation to pushdefer
ops\, because pushdefer doesn\'t perform any such test\, and always
chains its op\_next\. \(It seems to have been grouped with those logical
connectives merely because it shares the feature of having an op\_other
field\.\)

As far as I can see\, the erroneous optimisation can\'t actually be
triggered from pure Perl code\. But pure Perl can get very close\. In
\"do \{ defer \{\.\.\.\} \}\, do \{ defer \{\.\.\.\} \}\"\, on entry to
the peephole optimiser the two pushdefer ops are separated only by a
handful of null ops and one scope op\. The scope op has no runtime
effect\, and the peephole optimiser duly elides it from the op\_next
chain just as it elides the null ops\. So on exit from the peephole
optimiser the two pushdefer ops are adjacent\, with no intervening ops\.
If that \(correctly\) optimised sequence were to be sent through the
optimiser a second time \(with op\_opt cleared to make that meaningful\)
then the second pushdefer would be incorrectly elided\.

This is a fragile situation\. XS code that munges ops could easily cause
the erroneous optimisation to be triggered\, by innocent behaviour that
creates otherwise\-correct op trees that don\'t arise from pure Perl\.
One might legitimately put pushdefer ops in closer proximity than pure
Perl code does\, or null out a scope op prior to peephole optimisation\.

<!--[Please do not change anything below this line]-->
<!------------------------------------------------------------------- -->


---
**Flags**
- category=core
- severity=low
---
**Perl configuration**
```
This perlbug was built using Perl 5.32.1 - Fri Sep 24 16:10:58 UTC 2021
It is being executed now by Perl 5.37.10 - Tue Mar 21 14:35:23 GMT 2023.

Site configuration information for perl 5.37.10:

Configured by zefram at Tue Mar 21 14:35:23 GMT 2023.

Summary of my perl5 (revision 5 version 37 subversion 10) configuration:

Platform:
osname=linux
osvers=5.10.0-21-amd64
archname=x86_64-linux-thread-multi
uname='linux barba.rous.org 5.10.0-21-amd64 #1 smp debian 5.10.162-1 (2023-01-21) x86_64 gnulinux '
config_args='-des -Dprefix=/home/zefram/usr/perl/perl_install/perl-5.37.10-i64-f52 -Duselargefiles -Dusethreads -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dusedevel -Uversiononly -Ui_db'
hint=recommended
useposix=true
d_sigaction=define
useithreads=define
usemultiplicity=define
use64bitint=define
use64bitall=define
uselongdouble=undef
usemymalloc=n
default_inc_excludes_dot=define
Compiler:
cc='cc'
ccflags ='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2'
optimize='-O2'
cppflags='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
ccversion=''
gccversion='10.2.1 20210110'
gccosandvers=''
intsize=4
longsize=8
ptrsize=8
doublesize=8
byteorder=12345678
doublekind=3
d_longlong=define
longlongsize=8
d_longdbl=define
longdblsize=16
longdblkind=3
ivtype='long'
ivsize=8
nvtype='double'
nvsize=8
Off_t='off_t'
lseeksize=8
alignbytes=8
prototype=define
Linker and Libraries:
ld='cc'
ldflags =' -fstack-protector-strong -L/usr/local/lib'
libpth=/usr/local/lib /usr/lib/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib
libs=-lpthread -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc
perllibs=-lpthread -ldl -lm -lcrypt -lutil -lc
libc=libc-2.31.so
so=so
useshrplib=true
libperl=libperl.so
gnulibc_version='2.31'
Dynamic Linking:
dlsrc=dl_dlopen.xs
dlext=so
d_dlsymun=undef
ccdlflags='-Wl,-E -Wl,-rpath,/home/zefram/usr/perl/perl_install/perl-5.37.10-i64-f52/lib/5.37.10/x86_64-linux-thread-multi/CORE'
cccdlflags='-fPIC'
lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector-strong'


---
@INC for perl 5.37.10:
/home/zefram/usr/perl/perl_install/perl-5.37.10-i64-f52/lib/site_perl/5.37.10/x86_64-linux-thread-multi
/home/zefram/usr/perl/perl_install/perl-5.37.10-i64-f52/lib/site_perl/5.37.10
/home/zefram/usr/perl/perl_install/perl-5.37.10-i64-f52/lib/5.37.10/x86_64-linux-thread-multi
/home/zefram/usr/perl/perl_install/perl-5.37.10-i64-f52/lib/5.37.10

---
Environment for perl 5.37.10:
HOME=/home/zefram
LANG (unset)
LANGUAGE (unset)
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/home/zefram/usr/perl/perl_install/perl-5.37.10-i64-f52/bin:/home/zefram/usr/perl/util:/home/zefram/pub/x86_64-unknown-linux-gnu/bin:/home/zefram/pub/common/bin:/usr/bin:/bin:/usr/local/bin:/usr/games
PERL_BADLANG (unset)
SHELL=/usr/bin/zsh
```