Revision: 909
Author: tim.bunce
Date: Mon Nov 16 02:48:55 2009
Log: Fixed tortuous "goto into own sub that's been deleted and replaced"  
use-case
used by Carp::Heavy. Thanks to ALEXMV for the bug report (RT#51149) and  
original
tests (which I've edited).

http://code.google.com/p/perl-devel-nytprof/source/detail?r=909

Added:
  /trunk/t/test18-goto2.p
  /trunk/t/test18-goto2.pm
  /trunk/t/test18-goto2.t
Modified:
  /trunk/MANIFEST
  /trunk/NYTProf.xs

=======================================
--- /dev/null
+++ /trunk/t/test18-goto2.p     Mon Nov 16 02:48:55 2009
@@ -0,0 +1,16 @@
+# Test Carp::Heavy's "swap subs out from under you with goto &sub"
+
+use lib 't';
+
+package Test18;
+
+sub longmess  { goto &longmess_jmp }
+
+sub longmess_jmp  {
+    # the required file deletes this longmess_jmp sub, while it's  
executing,
+    # and replaces it with longmess_real, which we then goto into!
+    require 'test18-goto2.pm'; # has to be require, not eval '...'
+    goto &longmess_real;
+}
+
+longmess("Oops");
=======================================
--- /dev/null
+++ /trunk/t/test18-goto2.pm    Mon Nov 16 02:48:55 2009
@@ -0,0 +1,8 @@
+package Test18;
+
+sub longmess_real { return "Heavy" }
+
+delete $Test18::{longmess_jmp};
+*longmess_jmp  = *longmess_real;
+
+1;
=======================================
--- /dev/null
+++ /trunk/t/test18-goto2.t     Mon Nov 16 02:48:55 2009
@@ -0,0 +1,6 @@
+use strict;
+use Test::More;
+use lib qw(t/lib);
+use NYTProfTest;
+
+run_test_group;
=======================================
--- /trunk/MANIFEST     Sat Nov 14 15:33:22 2009
+++ /trunk/MANIFEST     Mon Nov 16 02:48:55 2009
@@ -121,6 +121,9 @@
  t/test17-goto.p
  t/test17-goto.rdt
  t/test17-goto.t
+t/test18-goto2.t
+t/test18-goto2.pm
+t/test18-goto2.p
  t/test20-streval.p
  t/test20-streval.rdt
  t/test20-streval.t
=======================================
--- /trunk/NYTProf.xs   Sun Nov 15 13:42:01 2009
+++ /trunk/NYTProf.xs   Mon Nov 16 02:48:55 2009
@@ -2190,13 +2190,13 @@
          /* ignore the typical second (fallback) destroy */
          && !(subr_entry->prev_subr_entry_ix == subr_entry_ix &&  
subr_entry->already_counted==1)
      ) {
-        logwarn("%2d <<     %s::%s done (seix %d->%d, ac%u)\n",
+        logwarn("%2d <<     %s::%s done (seix %d<-%d, ac%u)\n",
              subr_entry->subr_prof_depth,
              subr_entry->called_subpkg_pv,
              (subr_entry->called_subnam_sv &&  
SvOK(subr_entry->called_subnam_sv))
                  ? SvPV_nolen(subr_entry->called_subnam_sv)
                  : "?",
-            (int)subr_entry_ix, (int)subr_entry->prev_subr_entry_ix,
+            (int)subr_entry->prev_subr_entry_ix, (int)subr_entry_ix,
              subr_entry->already_counted);
      }
      if (subr_entry->caller_subnam_sv) {
@@ -2750,7 +2750,7 @@
      else {

          /* goto &sub opcode acts like a return followed by a call all in  
one.
-         * When this op start executing, the 'current' subr_entry that was
+         * 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.
@@ -2758,8 +2758,11 @@
           * 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. Got all that?
+         * of the goto statement. That way the call graph makes sense and  
the
+         * 'calling location' make sense. Got all that?
           */
+        /* save a copy of prev_cop - see t/test18-goto2.p */
+        COP prev_cop_copy = *prev_cop;
          /* save a copy of the subr_entry of the sub we're goto'ing out of  
*/
          /* so we can reuse the caller _* info after it's destroyed */
          subr_entry_t goto_subr_entry;
@@ -2786,7 +2789,7 @@
          /* now we're in goto'd sub, mortalize the REFCNT_inc's done above  
*/
          sv_2mortal(goto_subr_entry.caller_subnam_sv);
          sv_2mortal(goto_subr_entry.called_subnam_sv);
-        this_subr_entry_ix = subr_entry_setup(aTHX_ prev_cop,  
&goto_subr_entry, op_type, sub_sv);
+        this_subr_entry_ix = subr_entry_setup(aTHX_ &prev_cop_copy,  
&goto_subr_entry, op_type, sub_sv);
          SvREFCNT_dec(sub_sv);
      }

-- 
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:  [email protected]
To unsubscribe, email:  [email protected]

Reply via email to