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

[BUG 5.*] \@_ does not survive #515

Closed
p5pRT opened this issue Sep 13, 1999 · 5 comments
Closed

[BUG 5.*] \@_ does not survive #515

p5pRT opened this issue Sep 13, 1999 · 5 comments

Comments

@p5pRT
Copy link

@p5pRT p5pRT commented Sep 13, 1999

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

Searchable as RT1362$

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Sep 13, 1999

From @vanstyn

  crypt% perl -MData​::Dumper -we 'sub new { bless \@​_ } die :​:Dumper(new("x"))'
  $VAR1 = bless( [], 'main' );
  crypt%

Nor strict nor -w elicit any explanation. Should this not vivify (reify?)
an arrayref to return?

The problem is similarly apparent without the 'bless'.

Hugo


Summary of my perl5 (5.0 patchlevel 5 subversion 3) configuration​:
  Platform​:
  osname=linux, osvers=2.2.5-15, archname=i686-linux
  uname='linux work.crypt.org 2.2.5-15 #1 mon apr 19 23​:00​:46 edt 1999 i686 unknown '
  hint=recommended, useposix=true, d_sigaction=define
  usethreads=undef useperlio=undef d_sfio=undef
  Compiler​:
  cc='cc', optimize='-O6', gccversion=egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
  cppflags='-Dbool=char -DHAS_BOOL'
  ccflags ='-Dbool=char -DHAS_BOOL'
  stdchar='char', d_stdstdio=undef, usevfork=false
  intsize=4, longsize=4, ptrsize=4, doublesize=8
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
  alignbytes=4, usemymalloc=n, prototype=define
  Linker and Libraries​:
  ld='cc', ldflags =' -L/usr/local/lib'
  libpth=/usr/local/lib /lib /usr/lib
  libs=-lnsl -lndbm -lgdbm -ldb -ldl -lm -lc -lposix -lcrypt
  libc=, so=so, useshrplib=false, libperl=libperl.a
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic'
  cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'

Characteristics of this binary (from libperl)​:
  Built under linux
  Compiled at May 14 1999 22​:53​:10
  @​INC​:
  /opt/perl5.005_03/lib/5.00503/i686-linux
  /opt/perl5.005_03/lib/5.00503
  /opt/perl5.005_03/lib/site_perl/5.005/i686-linux
  /opt/perl5.005_03/lib/site_perl/5.005
  .

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 9, 2000

From @gsar

On Tue, 14 Sep 1999 01​:02​:23 BST, Hugo wrote​:

For perl in qw/ 5.004_05 5.005_03 5.005_57 5.005_61 / I get​:

crypt% perl -MData​::Dumper -we 'sub new { bless \@​_ } die :​:Dumper(new("x"))
'
$VAR1 = bless( [], 'main' );
crypt%

Nor strict nor -w elicit any explanation. Should this not vivify (reify?)
an arrayref to return?

The problem is similarly apparent without the 'bless'.

This ought to help.

Sarathy
gsar@​activestate.com

Inline Patch
-----------------------------------8<-----------------------------------
Change 4195 by gsar@auger on 1999/09/19 21:30:18

	avoid clearing @_ at all for faster subroutine calls; fix bugs
	in passing around references to @_, eg C<sub foo { \@_ }>; add
	tests for the same

Affected files ...

... //depot/perl/MANIFEST#193 edit
... //depot/perl/cop.h#29 edit
... //depot/perl/pp.c#144 edit
... //depot/perl/pp_ctl.c#147 edit
... //depot/perl/pp_hot.c#131 edit
... //depot/perl/t/op/args.t#1 add

Differences ...

==== //depot/perl/MANIFEST#193 (text) ====
Index: perl/MANIFEST
--- perl/MANIFEST.~1~	Sun Sep 19 14:30:23 1999
+++ perl/MANIFEST	Sun Sep 19 14:30:23 1999
@@ -1236,6 +1236,7 @@
 t/lib/trig.t		See if Math::Trig works
 t/op/64bit.t		See if 64 bitness works
 t/op/append.t		See if . works
+t/op/args.t		See if operations on @_ work
 t/op/arith.t		See if arithmetic works
 t/op/array.t		See if array operations work
 t/op/assignwarn.t	See if OP= operators warn correctly for undef targets

==== //depot/perl/cop.h#29 (text) ====
Index: perl/cop.h
--- perl/cop.h.~1~	Sun Sep 19 14:30:23 1999
+++ perl/cop.h	Sun Sep 19 14:30:23 1999
@@ -66,17 +66,22 @@
 #define POPSAVEARRAY()							\
     STMT_START {							\
 	SvREFCNT_dec(GvAV(PL_defgv));					\
-	GvAV(PL_defgv) = cxsub.savearray;					\
+	GvAV(PL_defgv) = cxsub.savearray;				\
     } STMT_END
 #endif /* USE_THREADS */
 
 #define POPSUB2()							\
 	if (cxsub.hasargs) {						\
 	    POPSAVEARRAY();						\
-	    /* destroy arg array */					\
-	    av_clear(cxsub.argarray);					\
-	    AvREAL_off(cxsub.argarray);					\
-	    AvREIFY_on(cxsub.argarray);					\
+	    /* abandon @_ if it got reified */				\
+	    if (AvREAL(cxsub.argarray)) {				\
+		SSize_t fill = AvFILLp(cxsub.argarray);			\
+		SvREFCNT_dec(cxsub.argarray);				\
+		cxsub.argarray = newAV();				\
+		av_extend(cxsub.argarray, fill);			\
+		AvFLAGS(cxsub.argarray) = AVf_REIFY;			\
+		PL_curpad[0] = (SV*)cxsub.argarray;			\
+	    }								\
 	}								\
 	if (cxsub.cv) {							\
 	    if (!(CvDEPTH(cxsub.cv) = cxsub.olddepth))			\

==== //depot/perl/pp.c#144 (text) ====
Index: perl/pp.c
--- perl/pp.c.~1~	Sun Sep 19 14:30:23 1999
+++ perl/pp.c	Sun Sep 19 14:30:23 1999
@@ -530,6 +530,12 @@
 	else
 	    (void)SvREFCNT_inc(sv);
     }
+    else if (SvTYPE(sv) == SVt_PVAV) {
+	if (!AvREAL((AV*)sv) && AvREIFY((AV*)sv))
+	    av_reify((AV*)sv);
+	SvTEMP_off(sv);
+	(void)SvREFCNT_inc(sv);
+    }
     else if (SvPADTMP(sv))
 	sv = newSVsv(sv);
     else {

==== //depot/perl/pp_ctl.c#147 (text) ====
Index: perl/pp_ctl.c
--- perl/pp_ctl.c.~1~	Sun Sep 19 14:30:23 1999
+++ perl/pp_ctl.c	Sun Sep 19 14:30:23 1999
@@ -1972,7 +1972,6 @@
 	    SV** mark;
 	    I32 items = 0;
 	    I32 oldsave;
-	    int arg_was_real = 0;
 
 	retry:
 	    if (!CvROOT(cv) && !CvXSUB(cv)) {
@@ -2004,8 +2003,8 @@
 	    if (CxTYPE(cx) == CXt_EVAL && cx->blk_eval.old_op_type == OP_ENTEREVAL) 
 		DIE(aTHX_ "Can't goto subroutine from an eval-string");
 	    mark = PL_stack_sp;
-	    if (CxTYPE(cx) == CXt_SUB &&
-		cx->blk_sub.hasargs) {   /* put @_ back onto stack */
+	    if (CxTYPE(cx) == CXt_SUB && cx->blk_sub.hasargs) {
+		/* put @_ back onto stack */
 		AV* av = cx->blk_sub.argarray;
 		
 		items = AvFILLp(av) + 1;
@@ -2017,11 +2016,14 @@
 		SvREFCNT_dec(GvAV(PL_defgv));
 		GvAV(PL_defgv) = cx->blk_sub.savearray;
 #endif /* USE_THREADS */
+		/* abandon @_ if it got reified */
 		if (AvREAL(av)) {
-		    arg_was_real = 1;
-		    AvREAL_off(av);	/* so av_clear() won't clobber elts */
+		    (void)sv_2mortal((SV*)av);	/* delay until return */
+		    av = newAV();
+		    av_extend(av, items-1);
+		    AvFLAGS(av) = AVf_REIFY;
+		    PL_curpad[0] = (SV*)(cx->blk_sub.argarray = av);
 		}
-		av_clear(av);
 	    }
 	    else if (CvXSUB(cv)) {	/* put GvAV(defgv) back onto stack */
 		AV* av;
@@ -2179,11 +2181,7 @@
 		    }
 		    Copy(mark,AvARRAY(av),items,SV*);
 		    AvFILLp(av) = items - 1;
-		    /* preserve @_ nature */
-		    if (arg_was_real) {
-			AvREIFY_off(av);
-			AvREAL_on(av);
-		    }
+		    assert(!AvREAL(av));
 		    while (items--) {
 			if (*mark)
 			    SvTEMP_off(*mark);

==== //depot/perl/pp_hot.c#131 (text) ====
Index: perl/pp_hot.c
--- perl/pp_hot.c.~1~	Sun Sep 19 14:30:23 1999
+++ perl/pp_hot.c	Sun Sep 19 14:30:23 1999
@@ -2522,11 +2522,7 @@
 	    			  "%p entersub preparing @_\n", thr));
 #endif
 	    av = (AV*)PL_curpad[0];
-	    if (AvREAL(av)) {
-		av_clear(av);
-		AvREAL_off(av);
-		AvREIFY_on(av);
-	    }
+	    assert(!AvREAL(av));
 #ifndef USE_THREADS
 	    cx->blk_sub.savearray = GvAV(PL_defgv);
 	    GvAV(PL_defgv) = (AV*)SvREFCNT_inc(av);

==== //depot/perl/t/op/args.t#1 (xtext) ====
Index: perl/t/op/args.t
--- perl/t/op/args.t.~1~	Sun Sep 19 14:30:23 1999
+++ perl/t/op/args.t	Sun Sep 19 14:30:23 1999
@@ -0,0 +1,54 @@
+#!./perl
+
+print "1..8\n";
+
+# test various operations on @_
+
+my $ord = 0;
+sub new1 { bless \@_ }
+{
+    my $x = new1("x");
+    my $y = new1("y");
+    ++$ord;
+    print "# got [@$y], expected [y]\nnot " unless "@$y" eq "y";
+    print "ok $ord\n";
+    ++$ord;
+    print "# got [@$x], expected [x]\nnot " unless "@$x" eq "x";
+    print "ok $ord\n";
+}
+
+sub new2 { splice @_, 0, 0, "a", "b", "c"; return \@_ }
+{
+    my $x = new2("x");
+    my $y = new2("y");
+    ++$ord;
+    print "# got [@$x], expected [a b c x]\nnot " unless "@$x" eq "a b c x";
+    print "ok $ord\n";
+    ++$ord;
+    print "# got [@$y], expected [a b c y]\nnot " unless "@$y" eq "a b c y";
+    print "ok $ord\n";
+}
+
+sub new3 { goto &new1 }
+{
+    my $x = new3("x");
+    my $y = new3("y");
+    ++$ord;
+    print "# got [@$y], expected [y]\nnot " unless "@$y" eq "y";
+    print "ok $ord\n";
+    ++$ord;
+    print "# got [@$x], expected [x]\nnot " unless "@$x" eq "x";
+    print "ok $ord\n";
+}
+
+sub new4 { goto &new2 }
+{
+    my $x = new4("x");
+    my $y = new4("y");
+    ++$ord;
+    print "# got [@$x], expected [a b c x]\nnot " unless "@$x" eq "a b c x";
+    print "ok $ord\n";
+    ++$ord;
+    print "# got [@$y], expected [a b c y]\nnot " unless "@$y" eq "a b c y";
+    print "ok $ord\n";
+}
End of Patch.
@p5pRT
Copy link
Author

@p5pRT p5pRT commented Dec 9, 2000

From @vanstyn

In <199909192148.OAA05451@​activestate.com>, Gurusamy Sarathy writes​:
:On Tue, 14 Sep 1999 01​:02​:23 BST, Hugo wrote​:
:>For perl in qw/ 5.004_05 5.005_03 5.005_57 5.005_61 / I get​:
:>
:> crypt% perl -MData​::Dumper -we 'sub new { bless \@​_ } die :​:Dumper(new("x")
:)
:>'
:> $VAR1 = bless( [], 'main' );
:> crypt%
:>
:>Nor strict nor -w elicit any explanation. Should this not vivify (reify?)
:>an arrayref to return?
:>
:>The problem is similarly apparent without the 'bless'.
:
:This ought to help.
[snip]

Confirmed​: passes all tests here except the usual two (known glibc and
DB_File problems), and the quoted testcase.

Hugo

@p5pRT p5pRT closed this Nov 28, 2003
@p5pRT
Copy link
Author

@p5pRT p5pRT commented Nov 28, 2003

From The RT System itself

seems to behave correctly in DEVEL7093 - output is​:
$VAR1 = bless( [
  'x'
  ], 'main' );

@p5pRT
Copy link
Author

@p5pRT p5pRT commented Nov 28, 2003

From The RT System itself

Actually fixed at least as early as 5.6.0.

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

Successfully merging a pull request may close this issue.

None yet
1 participant