Devel-NYTProf
view release on metacpan or search on metacpan
if (trace_level >= 9)
logwarn("finding current_cv(%d,%p) - cx_type %d %s, si_type %d\n",
(int)ix, (void*)si, CxTYPE(cx), cx_block_type(cx), (int)si->si_type);
/* 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 && !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) /* 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 */
if (si->si_type != PERLSI_MAIN) {
return current_cv(aTHX_ si->si_prev->si_cxix, si->si_prev);
}
return Nullcv;
}
static SSize_t
subr_entry_setup(pTHX_ COP *prev_cop, subr_entry_t *clone_subr_entry, OPCODE op_type, SV *subr_sv)
{
int saved_errno = errno;
subr_entry_t *subr_entry;
SSize_t prev_subr_entry_ix;
subr_entry_t *caller_subr_entry;
const char *found_caller_by;
char *file;
/* allocate struct to save stack (very efficient) */
/* XXX "warning: cast from pointer to integer of different size" with use64bitall=define */
prev_subr_entry_ix = subr_entry_ix;
subr_entry_ix = SSNEWa(sizeof(*subr_entry), MEM_ALIGNBYTES);
if (subr_entry_ix <= prev_subr_entry_ix) {
/* one cause of this is running NYTProf with threads */
logwarn("NYTProf panic: stack is confused, giving up! (Try running with subs=0) ix=%" IVdf " prev_ix=%" IVdf "\n", (IV)subr_entry_ix, (IV)prev_subr_entry_ix);
/* limit the damage */
disable_profile(aTHX);
return prev_subr_entry_ix;
}
subr_entry = subr_entry_ix_ptr(subr_entry_ix);
Zero(subr_entry, 1, subr_entry_t);
subr_entry->prev_subr_entry_ix = prev_subr_entry_ix;
caller_subr_entry = subr_entry_ix_ptr(prev_subr_entry_ix);
subr_entry->subr_prof_depth = (caller_subr_entry)
? caller_subr_entry->subr_prof_depth+1 : 1;
get_time_of_day(subr_entry->initial_call_timeofday);
subr_entry->initial_overhead_ticks = cumulative_overhead_ticks;
subr_entry->initial_subr_ticks = cumulative_subr_ticks;
subr_entry->subr_call_seqn = (unsigned long)(++cumulative_subr_seqn);
/* try to work out what sub's being called in advance
* mainly for xsubs because otherwise they're transparent
* because xsub calls don't get a new context
*/
if (op_type == OP_ENTERSUB || op_type == OP_GOTO) {
GV *called_gv = Nullgv;
subr_entry->called_cv = resolve_sub_to_cv(aTHX_ subr_sv, &called_gv);
if (called_gv) {
char *p = HvNAME(GvSTASH(called_gv));
subr_entry->called_subpkg_pv = p;
subr_entry->called_subnam_sv = newSVpv(GvNAME(called_gv), 0);
/* detect calls to POSIX::_exit */
if ('P'==*p++ && 'O'==*p++ && 'S'==*p++ && 'I'==*p++ && 'X'==*p++ && 0==*p) {
char *s = GvNAME(called_gv);
if ('_'==*s++ && 'e'==*s++ && 'x'==*s++ && 'i'==*s++ && 't'==*s++ && 0==*s) {
finish_profile(aTHX);
}
}
}
else {
/* resolve_sub_to_cv couldn't work out what's being called,
* possibly because it's something that'll cause pp_entersub to croak
* anyway. So we mark the subr_entry in a particular way and hope that
* pp_subcall_profiler() can fill in the details.
* If there is an exception then we'll wind up in incr_sub_inclusive_time
* which will see this mark and ignore the call.
*/
subr_entry->called_subnam_sv = newSV(0);
}
subr_entry->called_is_xs = NULL; /* work it out later */
}
else { /* slowop */
/* pretend slowops (builtins) are xsubs */
const char *slowop_name = PL_op_name[op_type];
if (profile_slowops == 1) { /* 1 == put slowops into 1 package */
subr_entry->called_subpkg_pv = "CORE";
subr_entry->called_subnam_sv = newSVpv(slowop_name, 0);
}
else { /* 2 == put slowops into multiple packages */
SV **opname = NULL;
SV *sv;
if (!slowop_name_cache)
slowop_name_cache = newAV();
opname = av_fetch(slowop_name_cache, op_type, TRUE);
if (!opname)
croak("panic: opname cache read for '%s' (%d)\n", slowop_name, op_type);
sv = *opname;
if(!SvOK(sv)) {
const STRLEN len = strlen(slowop_name);
sv_grow(sv, 5 + len + 1);
memcpy(SvPVX(sv), "CORE:", 5);
memcpy(SvPVX(sv) + 5, slowop_name, len + 1);
SvCUR_set(sv, 5 + len);
SvPOK_on(sv);
}
subr_entry->called_subnam_sv = SvREFCNT_inc(sv);
subr_entry->called_subpkg_pv = CopSTASHPV(PL_curcop);
}
subr_entry->called_cv_depth = 1; /* an approximation for slowops */
( run in 1.924 second using v1.01-cache-2.11-cpan-800906f7e73 )