[perl-devel-nytprof] r1056 committed - Better test for RT#54600...

1 view
Skip to first unread message

codesite...@google.com

unread,
Feb 16, 2010, 10:44:52 AM2/16/10
to develnyt...@googlegroups.com
Revision: 1056
Author: ni...@ccl4.org
Date: Tue Feb 16 07:44:10 2010
Log: Better test for RT#54600

The problem is caused by S_call_body() in 5.8.8 and earlier making a direct
call to Perl_pp_entersub(), rather than indirecting via
PL_ppaddr[OP_ENTERSUB].
Hence any calls made through it (such as DESTROY) never reach our
pp_subcall_profiler, and subr_entry_setup() is never called to initialse
subr_entry_ix. Hence if if the DESTROY routine (or an AUTOLOAD called in
lieu
of it) executes goto \&subname; that does reach pp_subcall_profiler, which
assumes that it must (already) be inside a subroutine.

I don't (yet) know what the right fix (or work around) is.
http://code.google.com/p/perl-devel-nytprof/source/detail?r=1056

Modified:
/trunk/t/test82-version.t

=======================================
--- /trunk/t/test82-version.t Sun Feb 14 14:17:41 2010
+++ /trunk/t/test82-version.t Tue Feb 16 07:44:10 2010
@@ -34,7 +34,19 @@
});

__DATA__
-package X;
-require version;
-our $VERSION = '2';
-X->VERSION(1); # core dump
+#!perl -w
+{
+ package X;
+
+ sub warner {
+ print "# Hello world\n"
+ }
+
+ sub DESTROY {
+ goto \&warner;
+ }
+}
+
+my $a = bless [], 'X';
+
+undef $a;

Nicholas Clark

unread,
Feb 16, 2010, 11:12:00 AM2/16/10
to develnyt...@googlegroups.com
On Tue, Feb 16, 2010 at 03:44:52PM +0000, codesite...@google.com wrote:
> Revision: 1056
> Author: ni...@ccl4.org
> Date: Tue Feb 16 07:44:10 2010
> Log: Better test for RT#54600
>
> The problem is caused by S_call_body() in 5.8.8 and earlier making a direct
> call to Perl_pp_entersub(), rather than indirecting via
> PL_ppaddr[OP_ENTERSUB].
> Hence any calls made through it (such as DESTROY) never reach our
> pp_subcall_profiler, and subr_entry_setup() is never called to initialse
> subr_entry_ix. Hence if if the DESTROY routine (or an AUTOLOAD called in
> lieu
> of it) executes goto \&subname; that does reach pp_subcall_profiler, which
> assumes that it must (already) be inside a subroutine.
>
> I don't (yet) know what the right fix (or work around) is.
> http://code.google.com/p/perl-devel-nytprof/source/detail?r=1056

Specifically, I can see this comment:

/* goto &sub opcode acts like a return followed by a call all in one.
* When this op starts executing, the 'current' subr_entry that was
* pushed onto the savestack by pp_subcall_profiler will be 'already_counted'
* so the profiling of that call will be handled naturally for us.
* So far so good.
* Before it gets destroyed we'll take a copy of the subr_entry.
* Then tell subr_entry_setup() to use our copy as a template so it'll
* seem like the sub we goto'd was called by the same sub that called
* the one that executed the goto. Except that we do use the fid:line
* of the goto statement. That way the call graph makes sense and the
* 'calling location' make sense. Got all that?
*/

I assume that the work around is that if we arrive at a goto &sub
with subr_entry_ix 0, we skip the copy part, and treat it as an entersub
(possibly at the line of the goto, given that we can infer that it won't
be possible to merge the timing back to the location of the caller of
the original subroutine).

But I'm not sure of the right way to do that.

Nicholas Clark

Tim Bunce

unread,
Feb 16, 2010, 12:50:40 PM2/16/10
to develnyt...@googlegroups.com
Thanks for background detail and test Nick. Very helpful.
I'll give it some thought, hopefully tonight.

Tim.

> --
> You've received this message because you are subscribed to
> the Devel::NYTProf Development User group.
>
> Group hosted at: http://groups.google.com/group/develnytprof-dev
> Project hosted at: http://perl-devel-nytprof.googlecode.com
> CPAN distribution: http://search.cpan.org/dist/Devel-NYTProf
>
> To post, email: develnyt...@googlegroups.com
> To unsubscribe, email: develnytprof-d...@googlegroups.com
>

Nicholas Clark

unread,
Feb 16, 2010, 12:58:17 PM2/16/10
to develnyt...@googlegroups.com
On Tue, Feb 16, 2010 at 05:50:40PM +0000, Tim Bunce wrote:
> Thanks for background detail and test Nick. Very helpful.
> I'll give it some thought, hopefully tonight.

No problem.

I didn't like finding a failing test, so tried to fix it. I failed on that,
but at least figured out the cause, and ruled out and removed all the external
dependencies.

About the only thing I didn't have in my description was that at the point of
the SEGV, subr_entry_ix is 0. (Because it gets reset to that value.
Effectively the profiler thinks that it's still running at the top level of
the program, when actually its inside a method call.)

I suspect, but can't easily test from here, that a goto \&sub inside an
import called via use on 5.8.8 and earlier will fail similarly for the same
reason. And, I'd guess, tie invocations and overloading invocations.
Maybe even goto \&sub inside BEGIN, CHECK or INIT blocks. :-)

(I'm trying to remember all the places where the interpreter can make calls
out to user code from inside opcodes)

Nicholas Clark

PS It's only just occurred to me that it might be possible to jump sideways out
of BEGIN blocks. Does it work? Yes:

$ cat sick.pl
#!perl -w
use strict;

sub sick {
warn "Yuck!";
}

BEGIN {
goto \&sick;
}

__END__
$ perl sick.pl
Yuck! at sick.pl line 5.

Tim Bunce

unread,
Feb 20, 2010, 6:19:54 AM2/20/10
to develnyt...@googlegroups.com
On Tue, Feb 16, 2010 at 05:58:17PM +0000, Nicholas Clark wrote:
> On Tue, Feb 16, 2010 at 05:50:40PM +0000, Tim Bunce wrote:
> > Thanks for background detail and test Nick. Very helpful.
> > I'll give it some thought, hopefully tonight.
>
> No problem.
>
> I didn't like finding a failing test, so tried to fix it. I failed on that,
> but at least figured out the cause, and ruled out and removed all the external
> dependencies.

Which was a big help. It's what I'd stalled on finding the time to tackle.

> About the only thing I didn't have in my description was that at the point of
> the SEGV, subr_entry_ix is 0. (Because it gets reset to that value.
> Effectively the profiler thinks that it's still running at the top level of
> the program, when actually its inside a method call.)

r1064 is a pleasingly simple fix :)

I think there are cases where subr_entry_ix > 0 but I'm fairly sure
they'll "work" in a reasonably sane, though slightly inaccurate, fashion.

> I suspect, but can't easily test from here, that a goto \&sub inside an
> import called via use on 5.8.8 and earlier will fail similarly for the same
> reason. And, I'd guess, tie invocations and overloading invocations.
> Maybe even goto \&sub inside BEGIN, CHECK or INIT blocks. :-)

Very plausible. I don't feel any great need to improve the accuracy of
profiling on perl < 5.8.8 so I'm happy to ignore anything except crashers.

Tim.

Reply all
Reply to author
Forward
0 new messages