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

DProf breaks List::Util::shuffle #7587

Closed
p5pRT opened this issue Nov 9, 2004 · 20 comments
Closed

DProf breaks List::Util::shuffle #7587

p5pRT opened this issue Nov 9, 2004 · 20 comments

Comments

@p5pRT
Copy link

p5pRT commented Nov 9, 2004

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

Searchable as RT32383$

@p5pRT
Copy link
Author

p5pRT commented Nov 9, 2004

From @jhi

Created by @jhi

(Resubmitting since my original attempt seems to have
been eaten by a grue.)

This report is made with 5.8.1, but also 5.8.3 and 5.8.4 seem
to have it, I don't have 5.8.5 installed.

$ cat sd.pl
use List​::Util qw(shuffle);
shuffle;
$ perl sd.pl
$ perl -d​:DProf sd.pl
Modification of a read-only value attempted at sd.pl line 2.
$

The above is the smallest possible test case. You can do e.g.
@​a = 0..9; shuffle(@​a);
but that doesn't change the result.

Actually, originally I got a rather different error, from
the @​a = shuffle(@​a) kind of code​:

Can't coerce ARRAY to number in null at xxx.pm line yyy.

Unfortunately the xxx.pm is rather large and has large dependencies,
I lack the enthusiasm to start cutting it down. But "luckily" it seems
that shuffle() and DProf do not seem to like each other even with much
simpler test cases.

Perl Info

Flags:
    category=core
    severity=high

This perlbug was built using Perl v5.8.1 - Sat Sep 27 21:34:21 EEST 2003
It is being executed now by  Perl v5.8.1 - Sat Sep 27 20:29:29 EEST 2003.

Site configuration information for perl v5.8.1:

Configured by aet at Sat Sep 27 20:29:29 EEST 2003.

Summary of my perl5 (revision 5.0 version 8 subversion 1) configuration:
  Platform:
    osname=dec_osf, osvers=5.1a, archname=alpha-dec_osf-thread-multi
    uname='osf1 narya.hut.fi v5.1 1885 alpha '
    config_args='-deO -Dcc=cc -Dccname=cc -Dld=cc -Dlocincpth=/p/sys/db/include -Dloclibpth=/m/fs/work/work/lk/aet/perl-5.8.1/ccdb/lib -Dlibperl=libperl.a -Duseshrplib=false -Dusethreads=define -Duseithreads=define -Dbin=/v/dunix51_alpha/lang/perl/5.8.1/bin -Dbinexp=/v/dunix51_alpha/lang/perl/5.8.1/bin -Dinstallbin=/v/dunix51_alpha/lang/perl/5.8.1/bin -Dperlpath=/v/dunix51_alpha/lang/perl/5.8.1/bin/perl -Dinstallscript=/v/gen/lang/perl/5.8.1/bin -Dscriptdir=/v/gen/lang/perl/5.8.1/bin -Dscriptdirexp=/v/gen/lang/perl/5.8.1/bin -Darchlib=/v/dunix51_alpha/lang/perl/5.8.1/lib/public -Darchlibexp=/v/dunix51_alpha/lang/perl/5.8.1/lib/public -Dcf_email=aet@cc.hut.fi -Dinstallarchlib=/v/dunix51_alpha/lang/perl/5.8.1/lib/public -Dinstallman1dir=/v/gen/lang/perl/5.8.1/man/man1 -Dinstallman3dir=/v/gen/lang/perl/5.8.1/man/man3 -Dinstallprefix=/v/gen/lang/perl/5.8.1 -Dinstallprefixexp=/v/gen/lang/perl/5.8.1 -Dinstallprivlib=/v/gen/lang/perl/5.8.1/lib -Dinstallsitearch=/p/lang/perl-mod/sit!
 e_perl -Dinstallsitebin=/p/lang/perl-mod/bin -Dinstallsitelib=/p/lang/perl-mod/site_perl -Dinstallusrbinperl=undef -Dmydomain=.hut.fi -Dpager=/p/bin/less -Dperladmin=aet@cc.hut.fi -Dprefix=/v/gen/lang/perl/5.8.1 -Dprefixexp=/v/gen/lang/perl/5.8.1 -Dprivlib=/v/gen/lang/perl/5.8.1/lib -Dprivlibexp=/v/gen/lang/perl/5.8.1/lib -Dsitearch=/p/lang/perl-mod/site_perl -Dsitearchexp=/p/lang/perl-mod/site_perl -Dsitebin=/p/lang/perl-mod/bin -Dsitebinexp=/p/lang/perl-mod/bin -Dsitelib=/p/lang/perl-mod/site_perl -Dsitelib_stem=/p/lang/perl-mod/site_perl -Dsitelibexp=/p/lang/perl-mod/site_perl -Dsiteprefix=/p/lang/perl-mod -Dsiteprefixexp=/p/lang/perl-mod -Dstartperl=#!/p/bin/perl'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=define use5005threads=undef useithreads=define usemultiplicity=define
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=define use64bitall=define uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-pthread -std -D_INTRINSICS -fprm d -ieee -I/p/sys/db/include -DLANGUAGE_C',
    optimize='-O4',
    cppflags='-pthread -std -D_INTRINSICS -fprm d -ieee -I/p/sys/db/include -DLANGUAGE_C'
    ccversion='V6.4-014', gccversion='', 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='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -L/m/fs/work/work/lk/aet/perl-5.8.1/ccdb/lib'
    libpth=/m/fs/work/work/lk/aet/perl-5.8.1/ccdb/lib /usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib
    libs=-lccdb -lm -lutil -lpthread -lexc
    perllibs=-lm -lutil -lpthread -lexc
    libc=/usr/shlib/libc.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags='-shared -expect_unresolved "*" -O4 -msym -std -s -L/m/fs/work/work/lk/aet/perl-5.8.1/ccdb/lib'

Locally applied patches:
    


@INC for perl v5.8.1:
    /v/dunix51_alpha/lang/perl/5.8.1/lib/public
    /v/gen/lang/perl/5.8.1/lib
    /p/lang/perl-mod/site_perl
    /p/lang/perl-mod/site_perl
    /p/lang/perl-mod/site_perl
    .


Environment for perl v5.8.1:
    HOME=/u/vieraat/vieraat/jhi
    LANG=C
    LANGUAGE (unset)
    LC_ALL=fi_FI.ISO8859-1
    LC_CTYPE=fi_FI.ISO8859-1
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/u/vieraat/vieraat/jhi/.bin:/u/vieraat/vieraat/jhi/.s:/c/bin:/p/bin:/p/adm/bin:/usr/bin:/usr/sbin:/sbin:/bin:/usr/ccs/bin:/usr/lib:/etc:/lib:/usr/bin/X11:/usr/lbin:/usr/sbin/acct:/usr/tcb/bin:/tcb/bin:/usr/field:/u/vieraat/vieraat/jhi
    PERL_BADLANG (unset)
    SHELL=/bin/zsh

@p5pRT
Copy link
Author

p5pRT commented Dec 14, 2004

From @rgs

Jarkko Hietaniemi (via RT) wrote​:

$ cat sd.pl
use List​::Util qw(shuffle);
shuffle;
$ perl sd.pl
$ perl -d​:DProf sd.pl
Modification of a read-only value attempted at sd.pl line 2.

With blead, you get a more, er, porter-friendly error :

  $ bleadperl -d​:DProf -e 'use List​::Util qw/shuffle/;shuffle'
  panic​: pad_sv po at -e line 1.

@p5pRT
Copy link
Author

p5pRT commented Dec 14, 2004

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

@p5pRT
Copy link
Author

p5pRT commented Dec 14, 2004

From @demerphq

Jarkko Hietaniemi (via RT) wrote​:

$ cat sd.pl
use List​::Util qw(shuffle);
shuffle;
$ perl sd.pl
$ perl -d​:DProf sd.pl
Modification of a read-only value attempted at sd.pl line 2.

With blead, you get a more, er, porter-friendly error :

$ bleadperl -d​:DProf -e 'use List​::Util qw/shuffle/;shuffle'
panic​: pad_sv po at -e line 1.

As far as I know DProf goes poof when you try to use it with almost anything
XS.

Ive tried using it with code that uses Inline or XS and it always fails. I
ended up writing my own profiler to deal with it.

Yves

@p5pRT
Copy link
Author

p5pRT commented Dec 14, 2004

From @demerphq

Ive tried using it with code that uses Inline or XS and it
always fails. I ended up writing my own profiler to deal with it.

Gah. I just retested it and the problem has gone away. The only difference
was we currently use AS 638 and when I had the problems with Dprof we were
using AS 635. (5.6.2 vs 5.6.1 I think).

Sorry for the noise, whatever it was appears to be fixed.

Yves

@p5pRT
Copy link
Author

p5pRT commented Nov 7, 2005

From @rgs

Jarkko Hietaniemi (via RT) wrote​:

This report is made with 5.8.1, but also 5.8.3 and 5.8.4 seem
to have it, I don't have 5.8.5 installed.

$ cat sd.pl
use List​::Util qw(shuffle);
shuffle;
$ perl sd.pl
$ perl -d​:DProf sd.pl
Modification of a read-only value attempted at sd.pl line 2.
$

The above is the smallest possible test case. You can do e.g.
@​a = 0..9; shuffle(@​a);
but that doesn't change the result.

With current bleadperl, the error has changed :

  $ bleadperl -d​:DProf sd.pl
  panic​: pad_sv po at sd.pl line 2.

Actually, originally I got a rather different error, from
the @​a = shuffle(@​a) kind of code​:

Can't coerce ARRAY to number in null at xxx.pm line yyy.

Unfortunately the xxx.pm is rather large and has large dependencies,
I lack the enthusiasm to start cutting it down. But "luckily" it seems
that shuffle() and DProf do not seem to like each other even with much
simpler test cases.

@p5pRT
Copy link
Author

p5pRT commented Nov 7, 2005

From robin@cpan.org

The problem is that List​::Util​::shuffle() assumes that PL_op
has a usable op_targ. That's usually true, but when a debugger
has called the xsub with call_sv(), PL_op is a bogus op that
doesn't have much of anything.

Is there anything wrong with just calling seedDrand01() directly?

Robin

Inline Patch
--- ext/List/Util/Util.xs.orig	2005-11-07 14:09:27.000000000 +0000
+++ ext/List/Util/Util.xs	2005-11-07 14:31:32.000000000 +0000
@@ -308,15 +308,14 @@
     struct op dmy_op;
     struct op *old_op = PL_op;
 
-    /* We call pp_rand here so that Drand01 get initialized if rand()
-       or srand() has not already been called
+    /* Initialize Drand01 if rand() or srand() has
+       not already been called
     */
-    memzero((char*)(&dmy_op), sizeof(struct op));
-    /* we let pp_rand() borrow the TARG allocated for this XS sub */
-    dmy_op.op_targ = PL_op->op_targ;
-    PL_op = &dmy_op;
-    (void)*(PL_ppaddr[OP_RAND])(aTHX);
-    PL_op = old_op;
+    if (!PL_srand_called) {
+        (void)seedDrand01((Rand_seed_t)Perl_seed(aTHX));
+        PL_srand_called = TRUE;
+    }
+
     for (index = items ; index > 1 ; ) {
 	int swap = (int)(Drand01() * (double)(index--));
 	SV *tmp = ST(swap);

@p5pRT
Copy link
Author

p5pRT commented Nov 7, 2005

From @jhi

Rafael Garcia-Suarez via RT wrote​:

Jarkko Hietaniemi (via RT) wrote​:

This report is made with 5.8.1, but also 5.8.3 and 5.8.4 seem
to have it, I don't have 5.8.5 installed.

$ cat sd.pl
use List​::Util qw(shuffle);
shuffle;
$ perl sd.pl
$ perl -d​:DProf sd.pl
Modification of a read-only value attempted at sd.pl line 2.
$

The above is the smallest possible test case. You can do e.g.
@​a = 0..9; shuffle(@​a);
but that doesn't change the result.

With current bleadperl, the error has changed :

$ bleadperl \-d​:DProf sd\.pl
panic​: pad\_sv po at sd\.pl line 2\.

A change but I would not quite call it an improvement :-)

Actually, originally I got a rather different error, from
the @​a = shuffle(@​a) kind of code​:

@p5pRT
Copy link
Author

p5pRT commented Nov 7, 2005

From @gbarr

On Nov 7, 2005, at 08​:34 AM, Robin Houston wrote​:

The problem is that List​::Util​::shuffle() assumes that PL_op
has a usable op_targ. That's usually true, but when a debugger
has called the xsub with call_sv(), PL_op is a bogus op that
doesn't have much of anything.

Is there anything wrong with just calling seedDrand01() directly?

Perl_seed was not factored out until 5.8.1, so this code will not work
with any Perl prior to that.

Graham.

@p5pRT
Copy link
Author

p5pRT commented Nov 7, 2005

From robin@cpan.org

On Mon, Nov 07, 2005 at 04​:44​:07PM -0600, Graham Barr wrote​:

Perl_seed was not factored out until 5.8.1, so this code will not work
with any Perl prior to that.

Ah, okay.

How about we switch between the two, using a #ifdef based on
the version? Then it continues to work in older perls most
of the time, and post-5.8.1 it also works with the profiler?

Robin

@p5pRT
Copy link
Author

p5pRT commented Nov 7, 2005

From @smpeters

On Mon, Nov 07, 2005 at 10​:52​:29PM +0000, Robin Houston wrote​:

On Mon, Nov 07, 2005 at 04​:44​:07PM -0600, Graham Barr wrote​:

Perl_seed was not factored out until 5.8.1, so this code will not work
with any Perl prior to that.

Ah, okay.

How about we switch between the two, using a #ifdef based on
the version? Then it continues to work in older perls most
of the time, and post-5.8.1 it also works with the profiler?

Would it be possible to patch Perl_seed() into Devel​::PPPort?

Steve Peters
steve@​fisharerojo.org

@p5pRT
Copy link
Author

p5pRT commented Nov 8, 2005

From @gbarr

On Mon, November 7, 2005 4​:52 pm, Robin Houston wrote​:

On Mon, Nov 07, 2005 at 04​:44​:07PM -0600, Graham Barr wrote​:

Perl_seed was not factored out until 5.8.1, so this code will not work
with any Perl prior to that.

Ah, okay.

How about we switch between the two, using a #ifdef based on
the version? Then it continues to work in older perls most
of the time, and post-5.8.1 it also works with the profiler?

Sure, I have made this change in my svn repository.

Graham.

@p5pRT
Copy link
Author

p5pRT commented Nov 8, 2005

From @rgs

I'm thus marking this as fixed in the next version of List​::Util.

@p5pRT
Copy link
Author

p5pRT commented Nov 8, 2005

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

@p5pRT p5pRT closed this as completed Nov 8, 2005
@p5pRT
Copy link
Author

p5pRT commented Nov 8, 2005

From robin@cpan.org

On Tue, Nov 08, 2005 at 06​:32​:13AM -0600, Graham Barr wrote​:

Sure, I have made this change in my svn repository.

Great!

The patch below brings the core List​::Util in line with Graham's
repository, and changes PUSH_MULTICALL to take the cv as an argument
as we've discussed.

Robin

Inline Patch
--- ext/List/Util/lib/List/Util.pm.orig	2005-11-08 18:49:19.000000000 +0000
+++ ext/List/Util/lib/List/Util.pm	2005-11-08 18:50:38.000000000 +0000
@@ -6,6 +6,8 @@
 
 package List::Util;
 
+use strict;
+use vars qw(@ISA @EXPORT_OK $VERSION $XS_VERSION $TESTING_PERL_ONLY);
 require Exporter;
 
 @ISA        = qw(Exporter);
@@ -18,23 +20,32 @@
   # PERL_DL_NONLAZY must be false, or any errors in loading will just
   # cause the perl code to be tested
   local $ENV{PERL_DL_NONLAZY} = 0 if $ENV{PERL_DL_NONLAZY};
-  require DynaLoader;
-  local @ISA = qw(DynaLoader);
-  bootstrap List::Util $XS_VERSION;
-  1
-};
+  eval {
+    require XSLoader;
+    XSLoader::load('List::Util', $XS_VERSION);
+    1;
+  } or do {
+    require DynaLoader;
+    local @ISA = qw(DynaLoader);
+    bootstrap List::Util $XS_VERSION;
+  };
+} unless $TESTING_PERL_ONLY;
 
-eval <<'ESQ' unless defined &reduce;
 
 # This code is only compiled if the XS did not load
+# of for perl < 5.6.0
 
-use vars qw($a $b);
+if (!defined &reduce) {
+eval <<'ESQ' 
 
 sub reduce (&@) {
   my $code = shift;
+  no strict 'refs';
 
   return shift unless @_ > 1;
 
+  use vars qw($a $b);
+
   my $caller = caller;
   local(*{$caller."::a"}) = \my $a;
   local(*{$caller."::b"}) = \my $b;
@@ -48,16 +59,6 @@
   $a;
 }
 
-sub sum (@) { reduce { $a + $b } @_ }
-
-sub min (@) { reduce { $a < $b ? $a : $b } @_ }
-
-sub max (@) { reduce { $a > $b ? $a : $b } @_ }
-
-sub minstr (@) { reduce { $a lt $b ? $a : $b } @_ }
-
-sub maxstr (@) { reduce { $a gt $b ? $a : $b } @_ }
-
 sub first (&@) {
   my $code = shift;
 
@@ -68,6 +69,24 @@
   undef;
 }
 
+ESQ
+}
+
+# This code is only compiled if the XS did not load
+eval <<'ESQ' if !defined &sum;
+
+use vars qw($a $b);
+
+sub sum (@) { reduce { $a + $b } @_ }
+
+sub min (@) { reduce { $a < $b ? $a : $b } @_ }
+
+sub max (@) { reduce { $a > $b ? $a : $b } @_ }
+
+sub minstr (@) { reduce { $a lt $b ? $a : $b } @_ }
+
+sub maxstr (@) { reduce { $a gt $b ? $a : $b } @_ }
+
 sub shuffle (@) {
   my @a=\(@_);
   my $n;
@@ -201,7 +220,8 @@
 
 =item sum LIST
 
-Returns the sum of all the elements in LIST.
+Returns the sum of all the elements in LIST. If LIST is empty then
+C<undef> is returned.
 
     $foo = sum 1..10                # 55
     $foo = sum 3,9,12               # 24
--- ext/List/Util/t/first.t.orig	2005-11-08 18:48:39.000000000 +0000
+++ ext/List/Util/t/first.t	2005-11-08 18:50:38.000000000 +0000
@@ -100,6 +100,7 @@
 # (and more flexibly) in a way that we can't emulate from XS.
 if (!$::PERL_ONLY) { SKIP: {
 
+    $List::Util::REAL_MULTICALL ||= 0; # Avoid use only once
     skip("Poor man's MULTICALL can't cope", 2)
       if !$List::Util::REAL_MULTICALL;
 
--- ext/List/Util/t/reduce.t.orig	2005-11-08 18:48:49.000000000 +0000
+++ ext/List/Util/t/reduce.t	2005-11-08 18:50:38.000000000 +0000
@@ -127,6 +127,7 @@
 # (and more flexibly) in a way that we can't emulate from XS.
 if (!$::PERL_ONLY) { SKIP: {
 
+    $List::Util::REAL_MULTICALL ||= 0; # Avoid use only once
     skip("Poor man's MULTICALL can't cope", 2)
       if !$List::Util::REAL_MULTICALL;
 
--- ext/List/Util/Util.xs.orig	2005-11-08 18:48:54.000000000 +0000
+++ ext/List/Util/Util.xs	2005-11-08 18:50:38.000000000 +0000
@@ -7,8 +7,6 @@
 #include <perl.h>
 #include <XSUB.h>
 
-#include "multicall.h"
-
 #ifndef PERL_VERSION
 #    include <patchlevel.h>
 #    if !(defined(PERL_VERSION) || (SUBVERSION > 0 && defined(PATCHLEVEL)))
@@ -19,11 +17,14 @@
 #    define PERL_SUBVERSION	SUBVERSION
 #endif
 
+#if PERL_VERSION >= 6
+#  include "multicall.h"
+#endif
+
 #ifndef aTHX
 #  define aTHX
 #  define pTHX
 #endif
-
 /* Some platforms have strict exports. And before 5.7.3 cxinc (or Perl_cxinc)
    was not exported. Therefore platforms like win32, VMS etc have problems
    so we redefine it here -- GMB
@@ -230,6 +231,8 @@
 
 
 
+#ifdef dMULTICALL
+
 void
 reduce(block,...)
     SV * block
@@ -243,12 +246,13 @@
     HV *stash;
     I32 gimme = G_SCALAR;
     SV **args = &PL_stack_base[ax];
+    CV *cv;
 
     if(items <= 1) {
 	XSRETURN_UNDEF;
     }
     cv = sv_2cv(block, &stash, &gv, 0);
-    PUSH_MULTICALL;
+    PUSH_MULTICALL(cv);
     agv = gv_fetchpv("a", TRUE, SVt_PV);
     bgv = gv_fetchpv("b", TRUE, SVt_PV);
     SAVESPTR(GvSV(agv));
@@ -277,12 +281,13 @@
     HV *stash;
     I32 gimme = G_SCALAR;
     SV **args = &PL_stack_base[ax];
+    CV *cv;
 
     if(items <= 1) {
 	XSRETURN_UNDEF;
     }
     cv = sv_2cv(block, &stash, &gv, 0);
-    PUSH_MULTICALL;
+    PUSH_MULTICALL(cv);
     SAVESPTR(GvSV(PL_defgv));
 
     for(index = 1 ; index < items ; index++) {
@@ -298,6 +303,8 @@
     XSRETURN_UNDEF;
 }
 
+#endif
+
 void
 shuffle(...)
 PROTOTYPE: @
@@ -305,6 +312,7 @@
 {
     dVAR;
     int index;
+#if (PERL_VERSION < 8) || (PERL_VERSION == 8 && PERL_SUBVERSION <1)
     struct op dmy_op;
     struct op *old_op = PL_op;
 
@@ -317,6 +325,16 @@
     PL_op = &dmy_op;
     (void)*(PL_ppaddr[OP_RAND])(aTHX);
     PL_op = old_op;
+#else
+    /* Initialize Drand01 if rand() or srand() has
+       not already been called
+    */
+    if (!PL_srand_called) {
+        (void)seedDrand01((Rand_seed_t)Perl_seed(aTHX));
+        PL_srand_called = TRUE;
+    }
+#endif
+
     for (index = items ; index > 1 ; ) {
 	int swap = (int)(Drand01() * (double)(index--));
 	SV *tmp = ST(swap);
--- ext/List/Util/multicall.h.orig	2005-11-08 18:49:29.000000000 +0000
+++ ext/List/Util/multicall.h	2005-11-08 18:50:38.000000000 +0000
@@ -86,7 +86,7 @@
 #define dMULTICALL \
     SV **newsp;			/* set by POPBLOCK */			\
     PERL_CONTEXT *cx;							\
-    CV *cv;								\
+    CV *multicall_cv;							\
     OP *multicall_cop;							\
     bool multicall_oldcatch;						\
     U8 hasargs = 0
@@ -109,40 +109,41 @@
 #else
 #  define PUSHSUB_RETSTACK(cx) cx->blk_sub.retop = Nullop;
 #endif
-#undef PUSHSUB
-#define PUSHSUB(cx)                                                     \
-        cx->blk_sub.cv = cv;                                            \
-        cx->blk_sub.olddepth = CvDEPTH(cv);                             \
-        cx->blk_sub.hasargs = hasargs;                                  \
-        cx->blk_sub.lval = PL_op->op_private &                          \
+#define MULTICALL_PUSHSUB(cx, the_cv) \
+        cx->blk_sub.cv = the_cv;					\
+        cx->blk_sub.olddepth = CvDEPTH(the_cv);				\
+        cx->blk_sub.hasargs = hasargs;					\
+        cx->blk_sub.lval = PL_op->op_private &				\
                               (OPpLVAL_INTRO|OPpENTERSUB_INARGS);	\
 	PUSHSUB_RETSTACK(cx)						\
-        if (!CvDEPTH(cv)) {                                             \
-            (void)SvREFCNT_inc(cv);                                     \
-            (void)SvREFCNT_inc(cv);                                     \
-            SAVEFREESV(cv);                                             \
+        if (!CvDEPTH(the_cv)) {						\
+            (void)SvREFCNT_inc(the_cv);					\
+            (void)SvREFCNT_inc(the_cv);					\
+            SAVEFREESV(the_cv);						\
         }
 
-#define PUSH_MULTICALL \
+#define PUSH_MULTICALL(the_cv) \
     STMT_START {							\
-	AV* padlist = CvPADLIST(cv);					\
+	CV *_nOnclAshIngNamE_ = the_cv;					\
+	AV* padlist = CvPADLIST(_nOnclAshIngNamE_);			\
+	multicall_cv = _nOnclAshIngNamE_;				\
 	ENTER;								\
  	multicall_oldcatch = CATCH_GET;					\
-	SAVESPTR(CvROOT(cv)->op_ppaddr);				\
-	CvROOT(cv)->op_ppaddr = PL_ppaddr[OP_NULL];			\
+	SAVESPTR(CvROOT(multicall_cv)->op_ppaddr);			\
+	CvROOT(multicall_cv)->op_ppaddr = PL_ppaddr[OP_NULL];		\
 	SAVETMPS; SAVEVPTR(PL_op);					\
 	CATCH_SET(TRUE);						\
 	PUSHSTACKi(PERLSI_SORT);					\
 	PUSHBLOCK(cx, CXt_SUB, PL_stack_sp);				\
-	PUSHSUB(cx);							\
-	if (++CvDEPTH(cv) >= 2) {					\
+	MULTICALL_PUSHSUB(cx, multicall_cv);				\
+	if (++CvDEPTH(multicall_cv) >= 2) {				\
 	    PERL_STACK_OVERFLOW_CHECK();				\
-	    multicall_pad_push(aTHX_ padlist, CvDEPTH(cv));		\
+	    multicall_pad_push(aTHX_ padlist, CvDEPTH(multicall_cv));	\
 	}								\
 	SAVECOMPPAD();							\
-	PL_comppad = (AV*) (AvARRAY(padlist)[CvDEPTH(cv)]);		\
+	PL_comppad = (AV*) (AvARRAY(padlist)[CvDEPTH(multicall_cv)]);	\
 	PL_curpad = AvARRAY(PL_comppad);				\
-	multicall_cop = CvSTART(cv);					\
+	multicall_cop = CvSTART(multicall_cv);				\
     } STMT_END
 
 #define MULTICALL \
@@ -153,8 +154,8 @@
 
 #define POP_MULTICALL \
     STMT_START {							\
-	CvDEPTH(cv)--;							\
-	LEAVESUB(cv);							\
+	CvDEPTH(multicall_cv)--;					\
+	LEAVESUB(multicall_cv);						\
 	POPBLOCK(cx,PL_curpm);						\
 	POPSTACK;							\
 	CATCH_SET(multicall_oldcatch);					\
--- cop.h.orig	2005-11-05 12:05:18.000000000 +0000
+++ cop.h	2005-11-05 12:14:59.000000000 +0000
@@ -729,13 +729,15 @@
 #define dMULTICALL \
     SV **newsp;			/* set by POPBLOCK */			\
     PERL_CONTEXT *cx;							\
-    CV *cv;								\
+    CV *multicall_cv;							\
     OP *multicall_cop;							\
     bool multicall_oldcatch; 						\
     U8 hasargs = 0		/* used by PUSHSUB */
 
-#define PUSH_MULTICALL \
+#define PUSH_MULTICALL(the_cv) \
     STMT_START {							\
+	CV *_nOnclAshIngNamE_ = the_cv;					\
+	CV *cv = _nOnclAshIngNamE_;					\
 	AV* padlist = CvPADLIST(cv);					\
 	ENTER;								\
  	multicall_oldcatch = CATCH_GET;					\
@@ -749,6 +751,7 @@
 	}								\
 	SAVECOMPPAD();							\
 	PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv));			\
+	multicall_cv = cv;						\
 	multicall_cop = CvSTART(cv);					\
     } STMT_END
 
@@ -760,8 +763,8 @@
 
 #define POP_MULTICALL \
     STMT_START {							\
-	LEAVESUB(cv);							\
-	CvDEPTH(cv)--;							\
+	LEAVESUB(multicall_cv);						\
+	CvDEPTH(multicall_cv)--;					\
 	POPBLOCK(cx,PL_curpm);						\
 	CATCH_SET(multicall_oldcatch);					\
 	LEAVE;								\
--- pod/perlcall.pod.orig	2005-11-05 12:15:13.000000000 +0000
+++ pod/perlcall.pod	2005-11-05 12:16:32.000000000 +0000
@@ -1899,14 +1899,12 @@
 
 The pattern of macro calls is like this:
 
-    dMULTICALL;			/* Declare variables (including 'CV* cv') */
+    dMULTICALL;			/* Declare local variables */
     I32 gimme = G_SCALAR;	/* context of the call: G_SCALAR,
 				 * G_LIST, or G_VOID */
 
-    /* Here you must arrange for 'cv' to be set to the CV of
-     * the sub you want to call. */
-
-    PUSH_MULTICALL;		/* Set up the calling context */
+    PUSH_MULTICALL(cv);		/* Set up the context for calling cv,
+				   and set local vars appropriately */
 
     /* loop */ {
         /* set the value(s) af your parameter variables */

@p5pRT
Copy link
Author

p5pRT commented Nov 8, 2005

From @jhi

Robin Houston via RT wrote​:

On Tue, Nov 08, 2005 at 06​:32​:13AM -0600, Graham Barr wrote​:

Sure, I have made this change in my svn repository.

Great!

The patch below brings the core List​::Util in line with Graham's
repository, and changes PUSH_MULTICALL to take the cv as an argument
as we've discussed.

Robin

Could some sort of test case be whittled from my original bug report?

@p5pRT
Copy link
Author

p5pRT commented Nov 9, 2005

From @rgs

Robin Houston wrote​:

On Tue, Nov 08, 2005 at 06​:32​:13AM -0600, Graham Barr wrote​:

Sure, I have made this change in my svn repository.

Great!

The patch below brings the core List​::Util in line with Graham's
repository, and changes PUSH_MULTICALL to take the cv as an argument
as we've discussed.

Thanks, applied as change #26054.

@p5pRT
Copy link
Author

p5pRT commented Nov 9, 2005

From @gbarr

On Nov 9, 2005, at 03​:43 AM, Rafael Garcia-Suarez wrote​:

Robin Houston wrote​:

On Tue, Nov 08, 2005 at 06​:32​:13AM -0600, Graham Barr wrote​:

Sure, I have made this change in my svn repository.

Great!

The patch below brings the core List​::Util in line with Graham's
repository, and changes PUSH_MULTICALL to take the cv as an argument
as we've discussed.

Thanks, applied as change #26054.

Actually that patch was not quite complete. I think Robin had missed
some other changes I had made to the repository. Attached is a patch
that will bring them into line

Graham.

@p5pRT
Copy link
Author

p5pRT commented Nov 9, 2005

From @gbarr

Inline Patch
diff -ur perl/ext/List/Util/Util.xs Scalar-List-Utils-1.18/Util.xs
--- perl/ext/List/Util/Util.xs	2005-11-09 05:55:27.000000000 -0600
+++ Scalar-List-Utils-1.18/Util.xs	2005-11-09 05:56:33.000000000 -0600
@@ -485,7 +485,16 @@
 	SV *sv
 PROTOTYPE: $
 CODE:
+#if (PERL_VERSION < 8) || (PERL_VERSION == 8 && PERL_SUBVERSION <5)
+  if (SvPOK(sv) || SvPOKp(sv)) {
+    RETVAL = looks_like_number(sv);
+  }
+  else {
+    RETVAL = SvFLAGS(sv) & (SVf_NOK|SVp_NOK|SVf_IOK|SVp_IOK);
+  }
+#else
   RETVAL = looks_like_number(sv);
+#endif
 OUTPUT:
   RETVAL
 
diff -ur perl/ext/List/Util/lib/Scalar/Util.pm Scalar-List-Utils-1.18lib/Scalar/Util.pm
--- perl/ext/List/Util/lib/Scalar/Util.pm	2005-11-09 05:55:27.000000000 -0600
+++ Scalar-List-Utils-1.18lib/Scalar/Util.pm	2005-11-06 09:30:09.000000000 -0600
@@ -6,6 +6,8 @@
 
 package Scalar::Util;
 
+use strict;
+use vars qw(@ISA @EXPORT_OK $VERSION);
 require Exporter;
 require List::Util; # List::Util loads the XS
 
@@ -51,6 +53,7 @@
 
 eval <<'ESQ' unless defined &dualvar;
 
+use vars qw(@EXPORT_FAIL);
 push @EXPORT_FAIL, qw(weaken isweak dualvar isvstring set_prototype);
 
 # The code beyond here is only used if the XS is not installed
@@ -128,7 +131,7 @@
   local $_ = shift;
 
   # checks from perlfaq4
-  return $] < 5.008005 unless defined;
+  return 0 if !defined($_) or ref($_);
   return 1 if (/^[+-]?\d+$/); # is a +/- integer
   return 1 if (/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/); # a C float
   return 1 if ($] >= 5.008 and /^(Inf(inity)?|NaN)$/i) or ($] >= 5.006001 and /^Inf$/i);
@@ -148,7 +151,8 @@
 
 =head1 SYNOPSIS
 
-    use Scalar::Util qw(blessed dualvar isweak readonly refaddr reftype tainted weaken isvstring looks_like_number set_prototype);
+    use Scalar::Util qw(blessed dualvar isweak readonly refaddr reftype tainted
+                        weaken isvstring looks_like_number set_prototype);
 
 =head1 DESCRIPTION
 
@@ -202,6 +206,11 @@
     weaken($ref);
     $weak = isweak($ref);               # true
 
+B<NOTE>: Copying a weak reference creates a normal, strong, reference.
+
+    $copy = $ref;
+    $weak = isweak($ref);               # false
+
 =item looks_like_number EXPR
 
 Returns true if perl thinks EXPR is a number. See
diff -ur perl/ext/List/Util/t/lln.t Scalar-List-Utils-1.18t/lln.t
--- perl/ext/List/Util/t/lln.t	2005-05-23 09:04:26.000000000 -0500
+++ Scalar-List-Utils-1.18t/lln.t	2005-11-06 09:30:09.000000000 -0600
@@ -14,7 +14,7 @@
 }
 
 use strict;
-use Test::More tests => 12;
+use Test::More tests => 16;
 use Scalar::Util qw(looks_like_number);
 
 foreach my $num (qw(1 -1 +1 1.0 +1.0 -1.0 -1.0e-12)) {
@@ -25,6 +25,13 @@
 is(!!looks_like_number("Infinity"), $] >= 5.008,	'Infinity');
 is(!!looks_like_number("NaN"),	    $] >= 5.008,	'NaN');
 is(!!looks_like_number("foo"),	    '',			'foo');
-is(!!looks_like_number(undef),	    $] < 5.008005,	'undef');
+is(!!looks_like_number(undef),	    '',           	'undef');
+is(!!looks_like_number({}),	    '',			'HASH Ref');
+is(!!looks_like_number([]),	    '',			'ARRAY Ref');
+
+use Math::BigInt;
+my $bi = Math::BigInt->new('1234567890');
+is(!!looks_like_number($bi),	    '',			'Math::BigInt');
+is(!!looks_like_number("$bi"),	    1,			'Stringified Math::BigInt');
 
 # We should copy some of perl core tests like t/base/num.t here
diff -ur perl/ext/List/Util/t/p_blessed.t Scalar-List-Utils-1.18t/p_blessed.t
--- perl/ext/List/Util/t/p_blessed.t	2005-05-23 09:04:26.000000000 -0500
+++ Scalar-List-Utils-1.18t/p_blessed.t	2005-11-06 09:30:09.000000000 -0600
@@ -1,7 +1,7 @@
 #!./perl
 
 # force perl-only version to be tested
-sub List::Util::bootstrap {}
+$List::Util::TESTING_PERL_ONLY = $List::Util::TESTING_PERL_ONLY = 1;
 
 (my $f = __FILE__) =~ s/p_//;
 do $f;
diff -ur perl/ext/List/Util/t/p_first.t Scalar-List-Utils-1.18t/p_first.t
--- perl/ext/List/Util/t/p_first.t	2005-11-09 05:55:28.000000000 -0600
+++ Scalar-List-Utils-1.18t/p_first.t	2005-11-06 09:30:09.000000000 -0600
@@ -1,7 +1,7 @@
 #!./perl
 
 # force perl-only version to be tested
-sub List::Util::bootstrap {}
+$List::Util::TESTING_PERL_ONLY = $List::Util::TESTING_PERL_ONLY = 1;
 
 (my $f = __FILE__) =~ s/p_//;
 $::PERL_ONLY = $::PERL_ONLY = 1; # Mustn't use it only once!
diff -ur perl/ext/List/Util/t/p_lln.t Scalar-List-Utils-1.18t/p_lln.t
--- perl/ext/List/Util/t/p_lln.t	2005-05-23 09:04:26.000000000 -0500
+++ Scalar-List-Utils-1.18t/p_lln.t	2005-11-06 09:30:09.000000000 -0600
@@ -1,7 +1,7 @@
 #!./perl
 
 # force perl-only version to be tested
-sub List::Util::bootstrap {}
+$List::Util::TESTING_PERL_ONLY = $List::Util::TESTING_PERL_ONLY = 1;
 
 (my $f = __FILE__) =~ s/p_//;
 do $f;
diff -ur perl/ext/List/Util/t/p_max.t Scalar-List-Utils-1.18t/p_max.t
--- perl/ext/List/Util/t/p_max.t	2005-05-23 09:04:26.000000000 -0500
+++ Scalar-List-Utils-1.18t/p_max.t	2005-11-06 09:30:09.000000000 -0600
@@ -1,7 +1,7 @@
 #!./perl
 
 # force perl-only version to be tested
-sub List::Util::bootstrap {}
+$List::Util::TESTING_PERL_ONLY = $List::Util::TESTING_PERL_ONLY = 1;
 
 (my $f = __FILE__) =~ s/p_//;
 do $f;
diff -ur perl/ext/List/Util/t/p_maxstr.t Scalar-List-Utils-1.18t/p_maxstr.t
--- perl/ext/List/Util/t/p_maxstr.t	2005-05-23 09:04:26.000000000 -0500
+++ Scalar-List-Utils-1.18t/p_maxstr.t	2005-11-06 09:30:09.000000000 -0600
@@ -1,7 +1,7 @@
 #!./perl
 
 # force perl-only version to be tested
-sub List::Util::bootstrap {}
+$List::Util::TESTING_PERL_ONLY = $List::Util::TESTING_PERL_ONLY = 1;
 
 (my $f = __FILE__) =~ s/p_//;
 do $f;
diff -ur perl/ext/List/Util/t/p_min.t Scalar-List-Utils-1.18t/p_min.t
--- perl/ext/List/Util/t/p_min.t	2005-05-23 09:04:26.000000000 -0500
+++ Scalar-List-Utils-1.18t/p_min.t	2005-11-06 09:30:09.000000000 -0600
@@ -1,7 +1,7 @@
 #!./perl
 
 # force perl-only version to be tested
-sub List::Util::bootstrap {}
+$List::Util::TESTING_PERL_ONLY = $List::Util::TESTING_PERL_ONLY = 1;
 
 (my $f = __FILE__) =~ s/p_//;
 do $f;
diff -ur perl/ext/List/Util/t/p_minstr.t Scalar-List-Utils-1.18t/p_minstr.t
--- perl/ext/List/Util/t/p_minstr.t	2005-05-23 09:04:26.000000000 -0500
+++ Scalar-List-Utils-1.18t/p_minstr.t	2005-11-06 09:30:09.000000000 -0600
@@ -1,7 +1,7 @@
 #!./perl
 
 # force perl-only version to be tested
-sub List::Util::bootstrap {}
+$List::Util::TESTING_PERL_ONLY = $List::Util::TESTING_PERL_ONLY = 1;
 
 (my $f = __FILE__) =~ s/p_//;
 do $f;
diff -ur perl/ext/List/Util/t/p_openhan.t Scalar-List-Utils-1.18t/p_openhan.t
--- perl/ext/List/Util/t/p_openhan.t	2005-05-23 09:04:26.000000000 -0500
+++ Scalar-List-Utils-1.18t/p_openhan.t	2005-11-06 09:30:09.000000000 -0600
@@ -1,7 +1,7 @@
 #!./perl
 
 # force perl-only version to be tested
-sub List::Util::bootstrap {}
+$List::Util::TESTING_PERL_ONLY = $List::Util::TESTING_PERL_ONLY = 1;
 
 (my $f = __FILE__) =~ s/p_//;
 do $f;
diff -ur perl/ext/List/Util/t/p_readonly.t Scalar-List-Utils-1.18t/p_readonly.t
--- perl/ext/List/Util/t/p_readonly.t	2005-05-23 09:04:26.000000000 -0500
+++ Scalar-List-Utils-1.18t/p_readonly.t	2005-11-06 09:30:09.000000000 -0600
@@ -1,7 +1,7 @@
 #!./perl
 
 # force perl-only version to be tested
-sub List::Util::bootstrap {}
+$List::Util::TESTING_PERL_ONLY = $List::Util::TESTING_PERL_ONLY = 1;
 
 (my $f = __FILE__) =~ s/p_//;
 do $f;
diff -ur perl/ext/List/Util/t/p_reduce.t Scalar-List-Utils-1.18t/p_reduce.t
--- perl/ext/List/Util/t/p_reduce.t	2005-11-09 05:55:28.000000000 -0600
+++ Scalar-List-Utils-1.18t/p_reduce.t	2005-11-06 09:30:09.000000000 -0600
@@ -1,7 +1,7 @@
 #!./perl
 
 # force perl-only version to be tested
-sub List::Util::bootstrap {}
+$List::Util::TESTING_PERL_ONLY = $List::Util::TESTING_PERL_ONLY = 1;
 
 (my $f = __FILE__) =~ s/p_//;
 $::PERL_ONLY = $::PERL_ONLY = 1; # Mustn't use it only once!
diff -ur perl/ext/List/Util/t/p_refaddr.t Scalar-List-Utils-1.18t/p_refaddr.t
--- perl/ext/List/Util/t/p_refaddr.t	2005-05-23 09:04:26.000000000 -0500
+++ Scalar-List-Utils-1.18t/p_refaddr.t	2005-11-06 09:30:09.000000000 -0600
@@ -1,7 +1,7 @@
 #!./perl
 
 # force perl-only version to be tested
-sub List::Util::bootstrap {}
+$List::Util::TESTING_PERL_ONLY = $List::Util::TESTING_PERL_ONLY = 1;
 
 (my $f = __FILE__) =~ s/p_//;
 do $f;
diff -ur perl/ext/List/Util/t/p_reftype.t Scalar-List-Utils-1.18t/p_reftype.t
--- perl/ext/List/Util/t/p_reftype.t	2005-05-23 09:04:26.000000000 -0500
+++ Scalar-List-Utils-1.18t/p_reftype.t	2005-11-06 09:30:09.000000000 -0600
@@ -1,7 +1,7 @@
 #!./perl
 
 # force perl-only version to be tested
-sub List::Util::bootstrap {}
+$List::Util::TESTING_PERL_ONLY = $List::Util::TESTING_PERL_ONLY = 1;
 
 (my $f = __FILE__) =~ s/p_//;
 do $f;
diff -ur perl/ext/List/Util/t/p_shuffle.t Scalar-List-Utils-1.18t/p_shuffle.t
--- perl/ext/List/Util/t/p_shuffle.t	2005-05-23 09:04:26.000000000 -0500
+++ Scalar-List-Utils-1.18t/p_shuffle.t	2005-11-06 09:30:09.000000000 -0600
@@ -1,7 +1,7 @@
 #!./perl
 
 # force perl-only version to be tested
-sub List::Util::bootstrap {}
+$List::Util::TESTING_PERL_ONLY = $List::Util::TESTING_PERL_ONLY = 1;
 
 (my $f = __FILE__) =~ s/p_//;
 do $f;
diff -ur perl/ext/List/Util/t/p_sum.t Scalar-List-Utils-1.18t/p_sum.t
--- perl/ext/List/Util/t/p_sum.t	2005-05-23 09:04:26.000000000 -0500
+++ Scalar-List-Utils-1.18t/p_sum.t	2005-11-06 09:30:09.000000000 -0600
@@ -1,7 +1,7 @@
 #!./perl
 
 # force perl-only version to be tested
-sub List::Util::bootstrap {}
+$List::Util::TESTING_PERL_ONLY = $List::Util::TESTING_PERL_ONLY = 1;
 
 (my $f = __FILE__) =~ s/p_//;
 do $f;
diff -ur perl/ext/List/Util/t/p_tainted.t Scalar-List-Utils-1.18t/p_tainted.t
--- perl/ext/List/Util/t/p_tainted.t	2005-11-09 05:55:28.000000000 -0600
+++ Scalar-List-Utils-1.18t/p_tainted.t	2005-11-06 09:30:09.000000000 -0600
@@ -1,7 +1,7 @@
 #!./perl -T
 
 # force perl-only version to be tested
-sub List::Util::bootstrap {}
+$List::Util::TESTING_PERL_ONLY = $List::Util::TESTING_PERL_ONLY = 1;
 
 (my $f = __FILE__) =~ s/p_//;
 do "./$f";

@p5pRT
Copy link
Author

p5pRT commented Nov 9, 2005

From @rgs

Graham Barr wrote​:

Actually that patch was not quite complete. I think Robin had missed
some other changes I had made to the repository. Attached is a patch
that will bring them into line

Thanks, other changes applied as #26062.

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