Skip to content
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

Bleadperl v5.19.4-10-g15a4d87 breaks PJCJ/Devel-Cover-1.08.tar.gz #13298

Closed
p5pRT opened this issue Sep 22, 2013 · 11 comments
Closed

Bleadperl v5.19.4-10-g15a4d87 breaks PJCJ/Devel-Cover-1.08.tar.gz #13298

p5pRT opened this issue Sep 22, 2013 · 11 comments

Comments

@p5pRT
Copy link

p5pRT commented Sep 22, 2013

Migrated from rt.perl.org#119939 (status was 'resolved')

Searchable as RT119939$

@p5pRT
Copy link
Author

p5pRT commented Sep 22, 2013

From @andk

git bisect


commit 15a4d87
Author​: Matthew Horsfall (alh) <wolfsage@​gmail.com>
Date​: Thu Sep 19 19​:18​:48 2013 -0400

  Optimise if/unless wrt OP_AND/OP_OR/OP_DOR. Also optimise OP_OR/OP_DOR chains.

diagnostics


Also affected​:
  SRI/Mojolicious-4.41.tar.gz

Mojolicious report already on cpantesters​:

http​://www.cpantesters.org/cpan/report/0182b0e0-231f-11e3-bf45-b0dda0a565e3

Devel​::Cover not yet there.

perl -V


Summary of my perl5 (revision 5 version 19 subversion 5) configuration​:
  Commit id​: 15a4d87
  Platform​:
  osname=linux, osvers=3.10-2-amd64, archname=x86_64-linux-ld
  uname='linux k83 3.10-2-amd64 #1 smp debian 3.10.7-1 (2013-08-17) x86_64 gnulinux '
  config_args='-Dprefix=/home/sand/src/perl/repoperls/installed-perls/perl/v5.19.4-10-g15a4d87/127e -Dmyhostname=k83 -Dinstallusrbinperl=n -Uversiononly -Dusedevel -des -Ui_db -Uuseithreads -Duselongdouble -DDEBUGGING=-g'
  hint=recommended, useposix=true, d_sigaction=define
  useithreads=undef, usemultiplicity=undef
  useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
  use64bitint=define, use64bitall=define, uselongdouble=define
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='cc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
  optimize='-O2 -g',
  cppflags='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
  ccversion='', gccversion='4.8.1', gccosandvers=''
  intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
  ivtype='long', ivsize=8, nvtype='long double', nvsize=16, Off_t='off_t', lseeksize=8
  alignbytes=16, prototype=define
  Linker and Libraries​:
  ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
  libpth=/usr/local/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib /usr/lib
  libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat
  perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
  libc=, so=so, useshrplib=false, libperl=libperl.a
  gnulibc_version='2.17'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
  cccdlflags='-fPIC', lddlflags='-shared -O2 -g -L/usr/local/lib -fstack-protector'

Characteristics of this binary (from libperl)​:
  Compile-time options​: HAS_TIMES PERLIO_LAYERS PERL_DONT_CREATE_GVSV
  PERL_HASH_FUNC_ONE_AT_A_TIME_HARD PERL_MALLOC_WRAP
  PERL_NEW_COPY_ON_WRITE PERL_PRESERVE_IVUV
  PERL_USE_DEVEL USE_64_BIT_ALL USE_64_BIT_INT
  USE_LARGE_FILES USE_LOCALE USE_LOCALE_COLLATE
  USE_LOCALE_CTYPE USE_LOCALE_NUMERIC USE_LONG_DOUBLE
  USE_PERLIO USE_PERL_ATOF
  Built under linux
  Compiled at Sep 20 2013 22​:06​:36
  @​INC​:
  /home/sand/src/perl/repoperls/installed-perls/perl/v5.19.4-10-g15a4d87/127e/lib/site_perl/5.19.5/x86_64-linux-ld
  /home/sand/src/perl/repoperls/installed-perls/perl/v5.19.4-10-g15a4d87/127e/lib/site_perl/5.19.5
  /home/sand/src/perl/repoperls/installed-perls/perl/v5.19.4-10-g15a4d87/127e/lib/5.19.5/x86_64-linux-ld
  /home/sand/src/perl/repoperls/installed-perls/perl/v5.19.4-10-g15a4d87/127e/lib/5.19.5
  .

--
andreas

@p5pRT
Copy link
Author

p5pRT commented Sep 22, 2013

From @wolfsage

I see what's wrong with the Mojolicious failure.

The line in question is​:

  return sub { $ignore // 1 and shift; $self->_step($id, @​_) };

My optimisation assumed OP_DOR behaved like OP_OR and returned truth.

Instead OP_DOR evaluates the left operand for definedness, and if
true, returns its underlying value which then needs to be evaluated by
the next op (OP_AND & OPf_WANT_VOID).

Attached is a patch to fix this.

The optree now would look like​:

  $ ./perl -Ilib/ -MO=Concise -e 'if ($z // $x || $x // $z || 1) {}'
  e <@​> leave[1 ref] vKP/REFC ->(end)
  1 <0> enter ->2
  2 <;> nextstate(main 3 -e​:1) v​:{ ->3
  - <1> null vK/1 ->e
  c <|> and(other->d) vK/1 ->e
  - <1> null sK/1 ->c
  a <|> or(other->b) sK/1 ->d
  <-- Full short circuit
  - <1> null sK/1 ->a
  8 <|> dor(other->9) sK/1 ->c
  <-- Follows to OP_AND
  - <1> null sK/1 ->8
  6 <|> or(other->7) sK/1 ->d
  <-- Full short circuit
  - <1> null sK/1 ->6
  4 <|> dor(other->5) sK/1 ->c
  <-- Follows to OP_AND
  - <1> ex-rv2sv sK/1 ->4
  3 <$> gvsv(*z) s ->4
  - <1> ex-rv2sv sK/1 ->-
  5 <$> gvsv(*x) s ->6
  - <1> ex-rv2sv sK/1 ->-
  7 <$> gvsv(*x) s ->8
  - <1> ex-rv2sv sK/1 ->-
  9 <$> gvsv(*z) s ->a
  b <$> const(IV 1) s ->c
  - <@​> scope vK ->-
  d <0> stub v ->e
-e syntax OK

Also, I believe the Devel​::Cover failure is because we're now skipping
an op that it's trying to count, so perhaps its test output just needs
to be updated (unless its smart enough to count skipped ops somehow,
then Devel​::Cover would have to account for these new ops?)

Cheers,

-- Matthew Horsfall (alh)

@p5pRT
Copy link
Author

p5pRT commented Sep 22, 2013

From @wolfsage

0001-OP_DOR-to-a-void-OP_AND-cannot-short-circuit.patch
From 18b0835101db19d0daf9e6b4d46b5834c7f62486 Mon Sep 17 00:00:00 2001
From: Matthew Horsfall (alh) <wolfsage@gmail.com>
Date: Sun, 22 Sep 2013 11:10:06 -0400
Subject: [PATCH] OP_DOR to a void OP_AND cannot short circuit.

OP_DOR returns the value of the underlying object on success, not
true, so it must be evaluated by the next op and cannot be skipped.

Also, wrap IS_AND_OP with parens to be safer for use in the future.
---
 op.c       |   14 +++++++++-----
 t/op/dor.t |   27 ++++++++++++++++++++++++++-
 2 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/op.c b/op.c
index 49de893..b87a55f 100644
--- a/op.c
+++ b/op.c
@@ -10949,7 +10949,8 @@ S_inplace_aassign(pTHX_ OP *o) {
     defer_queue[(defer_base + ++defer_ix) % MAX_DEFERRED] = o; \
   } STMT_END
 
-#define IS_AND_OP(o) o->op_type == OP_AND
+#define IS_AND_OP(o)   (o->op_type == OP_AND)
+#define IS_OR_OP(o)    (o->op_type == OP_OR)
 #define IS_ORISH_OP(o) (o->op_type == OP_OR || o->op_type == OP_DOR)
 
 /* A peephole optimizer.  We visit the ops in the order they're to execute.
@@ -11425,12 +11426,15 @@ Perl_rpeep(pTHX_ OP *o)
 	                          ||  o->op_next->op_type == OP_NULL))
 	           o->op_next = o->op_next->op_next;
 	    }
-	    /* if we're an OR/DOR and our next is a AND in void context, we'll
-	      follow it's op_other on short circuit, same for reverse */
+	    /* if we're an OR and our next is a AND in void context, we'll
+	       follow it's op_other on short circuit, same for reverse.
+	       We can't do this with OP_DOR since if it's true, its return
+	       value is the underlying value which must be evaluated
+	       by the next op */
 	    if (o->op_next &&
 	        (
-		    (IS_AND_OP(o) && IS_ORISH_OP(o->op_next))
-	         || (IS_ORISH_OP(o) && IS_AND_OP(o->op_next))
+		    (IS_AND_OP(o) && IS_OR_OP(o->op_next))
+	         || (IS_OR_OP(o) && IS_AND_OP(o->op_next))
 	        )
 	        && (o->op_next->op_flags & OPf_WANT) == OPf_WANT_VOID
 	    ) {
diff --git a/t/op/dor.t b/t/op/dor.t
index e2385f1..d14ad96 100644
--- a/t/op/dor.t
+++ b/t/op/dor.t
@@ -10,7 +10,7 @@ BEGIN {
 package main;
 require './test.pl';
 
-plan( tests => 31 );
+plan( tests => 34 );
 
 my($x);
 
@@ -74,3 +74,28 @@ like( $@, qr/^Search pattern not terminated/,
 is(0 // 2, 0, 		'	// : left-hand operand not optimized away');
 is('' // 2, '',		'	// : left-hand operand not optimized away');
 is(undef // 2, 2, 	'	// : left-hand operand optimized away');
+
+# Test that OP_DORs other branch isn't run when arg is defined
+# // returns the value if its defined, and we must test its
+# truthness after
+my $x = 0;
+my $y = 0;
+
+$x // 1 and $y = 1;
+is($y, 0, 'y is still 0 after "$x // 1 and $y = 1"');
+
+$y = 0;
+# $x is defined, so its value 0 is returned to the if block
+# and the block is skipped
+if ($x // 1) {
+    $y = 1;
+}
+is($y, 0, 'if ($x // 1) exited out early since $x is defined and 0');
+
+# Test or/dor chain doesn't break dor
+$y = 0;
+
+if ($z // $x || $x // $z || 1) {
+	$y = 1;
+}
+is($y, 0, 'Chained or/dor behaves correctly');
-- 
1.7.0.4

@p5pRT
Copy link
Author

p5pRT commented Sep 22, 2013

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Sep 30, 2013

From @wolfsage

On Sun, Sep 22, 2013 at 11​:32 AM, Matthew Horsfall (alh)
<wolfsage@​gmail.com> wrote​:

I see what's wrong with the Mojolicious failure.

The line in question is​:

return sub { $ignore // 1 and shift; $self->_step($id, @​_) };

My optimisation assumed OP_DOR behaved like OP_OR and returned truth.

Instead OP_DOR evaluates the left operand for definedness, and if
true, returns its underlying value which then needs to be evaluated by
the next op (OP_AND & OPf_WANT_VOID).

Attached is a patch to fix this.

The optree now would look like​:

$ ./perl -Ilib/ -MO=Concise -e 'if ($z // $x || $x // $z || 1) {}'
e <@​> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 3 -e​:1) v​:{ ->3
- <1> null vK/1 ->e
c <|> and(other->d) vK/1 ->e
- <1> null sK/1 ->c
a <|> or(other->b) sK/1 ->d
<-- Full short circuit
- <1> null sK/1 ->a
8 <|> dor(other->9) sK/1 ->c
<-- Follows to OP_AND
- <1> null sK/1 ->8
6 <|> or(other->7) sK/1 ->d
<-- Full short circuit
- <1> null sK/1 ->6
4 <|> dor(other->5) sK/1 ->c
<-- Follows to OP_AND
- <1> ex-rv2sv sK/1 ->4
3 <$> gvsv(*z) s ->4
- <1> ex-rv2sv sK/1 ->-
5 <$> gvsv(*x) s ->6
- <1> ex-rv2sv sK/1 ->-
7 <$> gvsv(*x) s ->8
- <1> ex-rv2sv sK/1 ->-
9 <$> gvsv(*z) s ->a
b <$> const(IV 1) s ->c
- <@​> scope vK ->-
d <0> stub v ->e
-e syntax OK

Also, I believe the Devel​::Cover failure is because we're now skipping
an op that it's trying to count, so perhaps its test output just needs
to be updated (unless its smart enough to count skipped ops somehow,
then Devel​::Cover would have to account for these new ops?)

Cheers,

-- Matthew Horsfall (alh)

I'm not sure of the normal policy here, but with my last patch
(15a4d87
2890b84815) blead is 'broken' a bit.

Should we remove 15a4d87
2890b84815 until the patch I've attached previously can be applied?

Thanks,

-- Matthew Horsfall (alh)

@p5pRT
Copy link
Author

p5pRT commented Sep 30, 2013

From @cpansprout

On Mon Sep 30 07​:12​:41 2013, alh wrote​:

I'm not sure of the normal policy here, but with my last patch
(15a4d87
2890b84815) blead is 'broken' a bit.

Should we remove 15a4d87
2890b84815 until the patch I've attached previously can be applied?

I’m not currently in a position to apply (or revert) anything, so if
some other committer could take over here, I would appreciate it.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Sep 30, 2013

From @khwilliamson

On 09/30/2013 09​:38 AM, Father Chrysostomos via RT wrote​:

On Mon Sep 30 07​:12​:41 2013, alh wrote​:

I'm not sure of the normal policy here, but with my last patch
(15a4d87
2890b84815) blead is 'broken' a bit.

Should we remove 15a4d87
2890b84815 until the patch I've attached previously can be applied?

I’m not currently in a position to apply (or revert) anything, so if
some other committer could take over here, I would appreciate it.

I'll do this; currently the reversion is testing on my machine

@p5pRT
Copy link
Author

p5pRT commented Sep 30, 2013

From @khwilliamson

On 09/30/2013 09​:58 AM, Karl Williamson wrote​:

On 09/30/2013 09​:38 AM, Father Chrysostomos via RT wrote​:

On Mon Sep 30 07​:12​:41 2013, alh wrote​:

I'm not sure of the normal policy here, but with my last patch
(15a4d87
2890b84815) blead is 'broken' a bit.

Should we remove 15a4d87
2890b84815 until the patch I've attached previously can be applied?

I’m not currently in a position to apply (or revert) anything, so if
some other committer could take over here, I would appreciate it.

I'll do this; currently the reversion is testing on my machine

  Now done with commit 79d51b8

@p5pRT
Copy link
Author

p5pRT commented Sep 30, 2013

From @wolfsage

On Mon, Sep 30, 2013 at 12​:08 PM, Karl Williamson
<public@​khwilliamson.com> wrote​:

On 09/30/2013 09​:58 AM, Karl Williamson wrote​:

On 09/30/2013 09​:38 AM, Father Chrysostomos via RT wrote​:

On Mon Sep 30 07​:12​:41 2013, alh wrote​:

I'm not sure of the normal policy here, but with my last patch
(15a4d87
2890b84815) blead is 'broken' a bit.

Should we remove 15a4d87
2890b84815 until the patch I've attached previously can be applied?

I’m not currently in a position to apply (or revert) anything, so if
some other committer could take over here, I would appreciate it.

I'll do this; currently the reversion is testing on my machine

Now done with commit 79d51b8

Thanks, I'd love to see these two patches make it in still, should we
create a new ticket to track that or leave it in here?

(If we do I'll squash the two commits)

-- Matthew Horsfall (alh)

@p5pRT
Copy link
Author

p5pRT commented Oct 8, 2013

From @wolfsage

On Mon Sep 30 10​:10​:04 2013, alh wrote​:

Thanks, I'd love to see these two patches make it in still, should we
create a new ticket to track that or leave it in here?

(If we do I'll squash the two commits)

-- Matthew Horsfall (alh)

I've done this and fixed another issue.

See https://rt-archive.perl.org/perl5/Ticket/Display.html?id=120128

Closing.

-- Matthew Horsfall (alh)

@p5pRT
Copy link
Author

p5pRT commented Oct 8, 2013

@wolfsage - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant