Author: tim.bunce
Date: Sun Jul 12 14:11:20 2009
New Revision: 823
Modified:
trunk/NYTProf.xs
Log:
Keep separate entries in subr_entry for called pkg name and called subnam
(eithout pkg)
Return a gv from resolve_sub as a fallback, instead of formatted sub name.
Added a trace_level 1 note about a edge case not covered by test suite.
resolve_sub also doesn't need to bother with sv == &PL_sv_yes for
missing "import" subs
as we hide those earlier on now.
Removed explicit creation of <package>::BEGIN for caller name as the code
does
that naturally now (perhaps it always did).
Modified: trunk/NYTProf.xs
==============================================================================
--- trunk/NYTProf.xs (original)
+++ trunk/NYTProf.xs Sun Jul 12 14:11:20 2009
@@ -143,7 +143,6 @@
#define NYTP_SCi_CALLING_SUB 7 /* name of calling sub */
#define NYTP_SCi_elements 8 /* highest index, plus 1 */
-/* Hash table definitions */
#define MAX_HASH_SIZE 512
static int next_fid = 1; /* 0 is reserved */
@@ -2076,10 +2075,13 @@
typedef struct subr_entry_st subr_entry_t;
struct subr_entry_st {
- int completed;
+ int completed;
+ UV subr_call_seqn;
+
time_of_day_t initial_call_time;
NV initial_overhead_ticks;
NV initial_subr_secs;
+
unsigned int caller_fid;
int caller_line;
CV *caller_cv;
@@ -2088,10 +2090,8 @@
CV *called_cv;
int called_cv_depth;
char *called_is_xs; /* NULL, "xsub", or "syop" */
- SV *called_subname_sv;
- CV *sub_cv;
- UV subr_call_seqn;
- char *stash_name;
+ SV *called_subnam_sv;
+ char *called_subpkg_pv;
/* ensure all items are initialized in first phase of
pp_subcall_profiler */
};
@@ -2103,9 +2103,9 @@
sv_free(subr_entry->caller_subname_sv);
subr_entry->caller_subname_sv = Nullsv;
}
- if (subr_entry->called_subname_sv) {
- sv_free(subr_entry->called_subname_sv);
- subr_entry->called_subname_sv = Nullsv;
+ if (subr_entry->called_subnam_sv) {
+ sv_free(subr_entry->called_subnam_sv);
+ subr_entry->called_subnam_sv = Nullsv;
}
}
@@ -2114,6 +2114,7 @@
incr_sub_inclusive_time(pTHX_ subr_entry_t *subr_entry)
{
int saved_errno = errno;
+ char called_subname_pv[500]; /* XXX */
char subr_call_key[500]; /* XXX */
int subr_call_key_len;
NV overhead_ticks, called_sub_secs;
@@ -2121,7 +2122,7 @@
NV incl_subr_sec, excl_subr_sec;
SV *sv_tmp;
- if (subr_entry->called_subname_sv == &PL_sv_undef) {
+ if (subr_entry->called_subnam_sv == &PL_sv_undef) {
logwarn("xsub/builtin exited via an exception (which isn't handled
yet)\n");
subr_entry->completed = 1;
}
@@ -2165,9 +2166,12 @@
if (subr_call_key_len >= sizeof(subr_call_key))
croak("panic: NYTProf buffer overflow on %s\n", subr_call_key);
+ if ( (sprintf(called_subname_pv, "%s::%s",
subr_entry->called_subpkg_pv,
+ SvPV_nolen(subr_entry->called_subnam_sv)) >=
sizeof(called_subname_pv)) )
+ croak("NYTProf called_subname_pv buffer overflow on '%s'\n",
called_subname_pv);
+
/* { called_subname => { "caller_subname[fid:line]" => [ count,
incl_time, ... ] } } */
- sv_tmp = *hv_fetch(sub_callers_hv,
SvPV_nolen(subr_entry->called_subname_sv),
- (I32)SvCUR(subr_entry->called_subname_sv), 1);
+ sv_tmp = *hv_fetch(sub_callers_hv, called_subname_pv,
strlen(called_subname_pv), 1);
if (!SvROK(sv_tmp)) { /* autoviv hash ref - is first call of this
subname from anywhere */
HV *hv = newHV();
@@ -2188,10 +2192,10 @@
* The reader can try to associate the xsubs with the
* corresonding .pm file using the package part of the
subname.
*/
- SV *sv = *hv_fetch(GvHV(PL_DBsub),
SvPV_nolen(subr_entry->called_subname_sv),
(I32)SvCUR(subr_entry->called_subname_sv), 1);
+ SV *sv = *hv_fetch(GvHV(PL_DBsub), called_subname_pv,
strlen(called_subname_pv), 1);
sv_setpv(sv, ":0-0"); /* empty file name */
if (trace_level >= 2)
- logwarn("Adding fake DBsub entry for '%s' xsub\n",
SvPV_nolen(subr_entry->called_subname_sv));
+ logwarn("Adding fake DBsub entry for '%s' xsub\n",
called_subname_pv);
}
}
}
@@ -2204,12 +2208,12 @@
sv_setsv(sv_tmp, newRV_noinc((SV *)subr_call_av));
- if (subr_entry->stash_name) { /* note that a sub in this package
was called */
- SV *pf_sv = *hv_fetch(pkg_fids_hv, subr_entry->stash_name,
(I32)strlen(subr_entry->stash_name), 1);
+ if (subr_entry->called_subpkg_pv) { /* note that a sub in this
package was called */
+ SV *pf_sv = *hv_fetch(pkg_fids_hv,
subr_entry->called_subpkg_pv, (I32)strlen(subr_entry->called_subpkg_pv), 1);
if (!SvOK(pf_sv)) { /* log when first created */
if (trace_level >= 5)
logwarn("Noting that subs in package '%s' were
called\n",
- subr_entry->stash_name);
+ subr_entry->called_subpkg_pv);
sv_setsv(pf_sv, &PL_sv_no);
}
}
@@ -2221,7 +2225,7 @@
if (trace_level >= 3)
logwarn(" <- %s %"NVff"s excl = %"NVff"s incl - %"NVff"s
(%g-%g), oh %g-%g=%gt, d%d @%d:%d #%lu\n",
- SvPV_nolen(subr_entry->called_subname_sv),
+ called_subname_pv,
excl_subr_sec, incl_subr_sec, called_sub_secs,
cumulative_subr_secs, subr_entry->initial_subr_secs,
cumulative_overhead_ticks, subr_entry->initial_overhead_ticks,
overhead_ticks,
@@ -2263,14 +2267,14 @@
static SV *
-resolve_sub(pTHX_ SV *sv, SV *subname_out_sv)
+resolve_sub(pTHX_ SV *sv, GV **subname_gv_ptr)
{
GV *gv;
HV *stash;
CV *cv;
/* copied from top of perl's pp_entersub */
- /* modified to return either CV or else a PV containing string to use
*/
+ /* modified to return either CV or else a GV */
/* or a NULL in cases that pp_entersub would croak */
switch (SvTYPE(sv)) {
default:
@@ -2278,8 +2282,6 @@
char *sym;
if (sv == &PL_sv_yes) { /* unfound import,
ignore */
- if (subname_out_sv)
- sv_setpvn(subname_out_sv, "import", 6);
return NULL;
}
if (SvGMAGICAL(sv)) {
@@ -2316,8 +2318,8 @@
if (!(cv = GvCVu((GV*)sv)))
cv = sv_2cv(sv, &stash, &gv, FALSE);
if (!cv) { /* would autoload in
this situation */
- if (subname_out_sv)
- gv_efullname3(subname_out_sv, gv, Nullch);
+ if (subname_gv_ptr)
+ *subname_gv_ptr = gv;
return NULL;
}
break;
@@ -2341,14 +2343,11 @@
/* the common case of finding the caller on the same stack */
if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT)
return cx->blk_sub.cv;
- else if (CxTYPE(cx) == CXt_EVAL && cx->blk_eval.old_namesv) {
- return (CV*)&PL_sv_yes; /* indicates a require */
- }
else if (CxTYPE(cx) == CXt_EVAL && !CxTRYBLOCK(cx))
return current_cv(aTHX_ ix - 1, si); /* recurse up stack */
else if (ix == 0 && si->si_type == PERLSI_MAIN)
return PL_main_cv;
- else if (ix > 0)
+ else if (ix > 0) /* more on this stack? */
return current_cv(aTHX_ ix - 1, si); /* recurse up stack */
/* caller isn't on the same stack so we'll walk the stacks as well */
@@ -2426,9 +2425,6 @@
if (subr_entry->caller_cv == PL_main_cv) {
sv_setpvf(subr_entry->caller_subname_sv, "main::BEGIN");
}
- else if (subr_entry->caller_cv == (CV*)&PL_sv_yes) { /* require */
- sv_setpvf(subr_entry->caller_subname_sv, "%s::%s",
CopSTASHPV(PL_curcop), "BEGIN");
- }
else {
GV *gv = CvGV(subr_entry->caller_cv);
if (gv) {
@@ -2443,8 +2439,7 @@
}
/* initialize items we'll set later */
- subr_entry->sub_cv = NULL;
- subr_entry->called_subname_sv = &PL_sv_undef; /* see
incr_sub_inclusive_time */
+ subr_entry->called_subnam_sv = &PL_sv_undef; /* see
incr_sub_inclusive_time */
subr_entry->called_is_xs = "?"; /* we don't know yet */
subr_entry->called_cv_depth = 0;
@@ -2465,7 +2460,7 @@
if (profile_sub_call) {
int saved_errno = errno;
- SV *called_subname_sv;
+ SV *called_subnam_sv;
char *stash_name = NULL;
CV *called_cv;
char *is_xs;
@@ -2476,7 +2471,7 @@
save_destructor_x(incr_sub_inclusive_time_ix, INT2PTR(void *,
(IV)save_ix));
- called_subname_sv = newSV(0);
+ called_subnam_sv = newSV(0);
if (is_sysop) {
/* pretend builtins are xsubs in the same package
* but with "CORE:" (one colon) prepended to the name.
@@ -2486,11 +2481,11 @@
is_xs = "sop";
if (profile_sysops == 1) { /* 1 == put sysops into 1 package */
stash_name = "CORE";
- sv_setpvf(called_subname_sv, "%s::%s", stash_name,
sysop_name);
+ sv_setpv(called_subnam_sv, sysop_name);
}
else { /* 2 == put sysops into multiple
packages */
stash_name = CopSTASHPV(PL_curcop);
- sv_setpvf(called_subname_sv, "%s::CORE:%s", stash_name,
sysop_name);
+ sv_setpvf(called_subnam_sv, "CORE:%s", sysop_name);
}
subr_entry->called_cv_depth = 1; /* an approximation for
sysops */
}
@@ -2503,7 +2498,17 @@
else { /* have returned from XS so use sub_sv
for name */
/* determine the original fully qualified name for sub */
/* CV or NULL */
- called_cv = (CV *)resolve_sub(aTHX_ sub_sv,
called_subname_sv);
+ GV *gv = NULL;
+ called_cv = (CV *)resolve_sub(aTHX_ sub_sv, &gv);
+
+ if (!called_cv && gv) { /* XXX no test case for this */
+ stash_name = HvNAME(GvSTASH(gv));
+ sv_setpv(called_subnam_sv, GvNAME(gv));
+ if (trace_level >= 1)
+ logwarn("Assuming called sub is named %s::%s at %s
line %d\n",
+ stash_name, SvPV_nolen(called_subnam_sv),
+ OutCopFILE(prev_cop), CopLINE(prev_cop));
+ }
is_xs = "xsub";
}
@@ -2515,7 +2520,7 @@
* package, so we dig to find the original package
*/
stash_name = HvNAME(GvSTASH(gv));
- sv_setpvf(called_subname_sv, "%s::%s", stash_name,
GvNAME(gv));
+ sv_setpv(called_subnam_sv, GvNAME(gv));
}
else if (trace_level) {
logwarn("I'm confused about CV %p\n", called_cv);
@@ -2525,7 +2530,8 @@
}
}
- if (!SvOK(called_subname_sv)) {
+ /* called_subnam_sv should have been set by now - else we're
getting desperate */
+ if (!SvOK(called_subnam_sv)) {
if (!called_cv) {
/* should never get here as pp_entersub would have
croaked */
@@ -2533,13 +2539,13 @@
logwarn("unknown entersub %s '%s'\n", what,
SvPV_nolen(sub_sv));
if (trace_level)
sv_dump(sub_sv);
- sv_setpvf(called_subname_sv, "(unknown %s %s)", what,
SvPV_nolen(sub_sv));
+ stash_name = CopSTASHPV(PL_curcop);
+ sv_setpvf(called_subnam_sv, "(unknown %s %s)", what,
SvPV_nolen(sub_sv));
}
else {
/* unnamed CV, e.g. seen in mod_perl/Class::MOP. XXX
do better? */
stash_name = HvNAME(CvSTASH(called_cv));
- sv_setpvf(called_subname_sv, "%s::__UNKNOWN__[0x%p]",
- (stash_name)?stash_name:"__UNKNOWN__", called_cv);
+ sv_setpvf(called_subnam_sv, "__UNKNOWN__[0x%p]",
called_cv);
if (trace_level) {
logwarn("unknown entersub %s assumed to be anon
called_cv '%s'\n",
(is_xs) ? is_xs : "sub", SvPV_nolen(sub_sv));
@@ -2547,16 +2553,17 @@
}
}
}
+
/* if called was xsub then we've already left it, so use
depth+1 */
subr_entry->called_cv_depth = (called_cv) ?
CvDEPTH(called_cv)+(is_xs?1:0) : 0;
}
- subr_entry->stash_name = stash_name;
+ subr_entry->called_subpkg_pv = stash_name;
+ subr_entry->called_subnam_sv = called_subnam_sv;
subr_entry->called_cv = called_cv;
- subr_entry->called_subname_sv = called_subname_sv;
subr_entry->called_is_xs = is_xs;
/* ignore our own DB::_INIT sub - only shows up with 5.8.9+ &
5.10.1+ */
- if (is_xs && SvCUR(called_subname_sv) == 9 &&
*SvPV_nolen(called_subname_sv) == 'D' &&
strEQ(SvPV_nolen(called_subname_sv), "DB::_INIT")) {
+ if (is_xs && *stash_name == 'D' && strEQ(stash_name,"DB") &&
strEQ(SvPV_nolen(called_subnam_sv), "_INIT")) {
subr_entry->completed = 1;
goto skip_sub_profile;
}
@@ -2565,8 +2572,8 @@
subr_entry->completed = 1;
if (trace_level >= 2) {
- logwarn(" ->%4s %s from %s (d%d, oh %"NVff"t, sub %"NVff"s)
#%lu\n",
- (is_xs) ? is_xs : "sub",
SvPV_nolen(subr_entry->called_subname_sv),
+ logwarn(" ->%4s %s::%s from %s (d%d, oh %"NVff"t,
sub %"NVff"s) #%lu\n",
+ (is_xs) ? is_xs : "sub", stash_name,
SvPV_nolen(called_subnam_sv),
SvPV_nolen(subr_entry->caller_subname_sv),
subr_entry->called_cv_depth,
subr_entry->initial_overhead_ticks,
--~--~---------~--~----~------------~-------~--~----~
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]
-~----------~----~----~----~------~----~------~--~---