File Coverage

NYTProf.xs
Criterion Covered Total %
statement 1645 2129 77.2
branch 998 2028 49.2
condition n/a
subroutine n/a
pod n/a
total 2643 4157 63.5


line stmt bran cond sub pod time code
1             /* vim: ts=8 sw=4 expandtab:
2             * ************************************************************************
3             * This file is part of the Devel::NYTProf package.
4             * Copyright 2008 Adam J. Kaplan, The New York Times Company.
5             * Copyright 2009-2010 Tim Bunce, Ireland.
6             * Released under the same terms as Perl 5.8
7             * See http://metacpan.org/release/Devel-NYTProf/
8             *
9             * Contributors:
10             * Tim Bunce, http://blog.timbunce.org
11             * Nicholas Clark,
12             * Adam Kaplan, akaplan at nytimes.com
13             * Steve Peters, steve at fisharerojo.org
14             *
15             * ************************************************************************
16             */
17             #define PERL_NO_GET_CONTEXT /* we want efficiency */
18              
19             #include "EXTERN.h"
20             #include "perl.h"
21             #include "XSUB.h"
22              
23             #include "FileHandle.h"
24             #include "NYTProf.h"
25              
26             #ifndef NO_PPPORT_H
27             #define NEED_my_snprintf_GLOBAL
28             #define NEED_newRV_noinc_GLOBAL
29             #define NEED_sv_2pv_flags
30             #define NEED_newSVpvn_flags
31             #define NEED_my_strlcat
32             # include "ppport.h"
33             #endif
34              
35             /* Until ppport.h gets this: */
36             #ifndef memEQs
37             # define memEQs(s1, l, s2) \
38             (sizeof(s2)-1 == l && memEQ(s1, ("" s2 ""), (sizeof(s2)-1)))
39             #endif
40              
41             #ifdef USE_HARD_ASSERT
42             #undef NDEBUG
43             #include
44             #endif
45              
46             #if !defined(OutCopFILE)
47             # define OutCopFILE CopFILE
48             #endif
49              
50             #ifndef gv_fetchfile_flags /* added in perl 5.009005 */
51             /* we know our uses don't contain embedded nulls, so we just need to copy to a
52             * buffer so we can add a trailing null byte */
53             #define gv_fetchfile_flags(a,b,c) gv_fetchfile_flags(a,b,c)
54             static GV *
55             gv_fetchfile_flags(pTHX_ const char *const name, const STRLEN namelen, const U32 flags) {
56             char buf[2000];
57             if (namelen >= sizeof(buf)-1)
58             croak("panic: gv_fetchfile_flags overflow");
59             memcpy(buf, name, namelen);
60             buf[namelen] = '\0'; /* null-terminate */
61             return gv_fetchfile(buf);
62             }
63             #endif
64              
65             #ifndef OP_SETSTATE
66             #define OP_SETSTATE OP_NEXTSTATE
67             #endif
68             #ifndef PERLDBf_SAVESRC
69             #define PERLDBf_SAVESRC PERLDBf_SUBLINE
70             #endif
71             #ifndef PERLDBf_SAVESRC_NOSUBS
72             #define PERLDBf_SAVESRC_NOSUBS 0
73             #endif
74             #ifndef CvISXSUB
75             #define CvISXSUB CvXSUB
76             #endif
77              
78             #if (PERL_VERSION < 8) || ((PERL_VERSION == 8) && (PERL_SUBVERSION < 8))
79             /* If we're using DB::DB() instead of opcode redirection with an old perl
80             * then PL_curcop in DB() will refer to the DB() wrapper in Devel/NYTProf.pm
81             * so we'd have to crawl the stack to find the right cop. However, for some
82             * reason that I don't pretend to understand the following expression works:
83             */
84             #define PL_curcop_nytprof (opt_use_db_sub ? ((cxstack + cxstack_ix)->blk_oldcop) : PL_curcop)
85             #else
86             #define PL_curcop_nytprof PL_curcop
87             #endif
88              
89             #define OP_NAME_safe(op) ((op) ? OP_NAME(op) : "NULL")
90              
91             #ifdef I_SYS_TIME
92             #include
93             #endif
94             #include
95              
96             #ifdef HAS_ZLIB
97             #include
98             #define default_compression_level 6
99             #else
100             #define default_compression_level 0
101             #endif
102             #ifndef ZLIB_VERSION
103             #define ZLIB_VERSION "0"
104             #endif
105              
106             #ifndef NYTP_MAX_SUB_NAME_LEN
107             #define NYTP_MAX_SUB_NAME_LEN 500
108             #endif
109              
110             #define NYTP_FILE_MAJOR_VERSION 5
111             #define NYTP_FILE_MINOR_VERSION 0
112              
113             #define NYTP_START_NO 0
114             #define NYTP_START_BEGIN 1
115             #define NYTP_START_CHECK_unused 2 /* not used */
116             #define NYTP_START_INIT 3
117             #define NYTP_START_END 4
118              
119             #define NYTP_OPTf_ADDPID 0x0001 /* append .pid to output filename */
120             #define NYTP_OPTf_OPTIMIZE 0x0002 /* affect $^P & 0x04 */
121             #define NYTP_OPTf_SAVESRC 0x0004 /* copy source code lines into profile data */
122             #define NYTP_OPTf_ADDTIMESTAMP 0x0008 /* append timestamp to output filename */
123              
124             #define NYTP_FIDf_IS_PMC 0x0001 /* .pm probably really loaded as .pmc */
125             #define NYTP_FIDf_VIA_STMT 0x0002 /* fid first seen by stmt profiler */
126             #define NYTP_FIDf_VIA_SUB 0x0004 /* fid first seen by sub profiler */
127             #define NYTP_FIDf_IS_AUTOSPLIT 0x0008 /* fid is an autosplit (see AutoLoader) */
128             #define NYTP_FIDf_HAS_SRC 0x0010 /* src is available to profiler */
129             #define NYTP_FIDf_SAVE_SRC 0x0020 /* src will be saved by profiler, if NYTP_FIDf_HAS_SRC also set */
130             #define NYTP_FIDf_IS_ALIAS 0x0040 /* fid is clone of the 'parent' fid it was autosplit from */
131             #define NYTP_FIDf_IS_FAKE 0x0080 /* eg dummy caller of a string eval that doesn't have a filename */
132             #define NYTP_FIDf_IS_EVAL 0x0100 /* is an eval */
133              
134             /* indices to elements of the file info array */
135             #define NYTP_FIDi_FILENAME 0
136             #define NYTP_FIDi_EVAL_FID 1
137             #define NYTP_FIDi_EVAL_LINE 2
138             #define NYTP_FIDi_FID 3
139             #define NYTP_FIDi_FLAGS 4
140             #define NYTP_FIDi_FILESIZE 5
141             #define NYTP_FIDi_FILEMTIME 6
142             #define NYTP_FIDi_PROFILE 7
143             #define NYTP_FIDi_EVAL_FI 8
144             #define NYTP_FIDi_HAS_EVALS 9
145             #define NYTP_FIDi_SUBS_DEFINED 10
146             #define NYTP_FIDi_SUBS_CALLED 11
147             #define NYTP_FIDi_elements 12 /* highest index, plus 1 */
148              
149             /* indices to elements of the sub info array (report-side only) */
150             #define NYTP_SIi_FID 0 /* fid of file sub was defined in */
151             #define NYTP_SIi_FIRST_LINE 1 /* line number of first line of sub */
152             #define NYTP_SIi_LAST_LINE 2 /* line number of last line of sub */
153             #define NYTP_SIi_CALL_COUNT 3 /* number of times sub was called */
154             #define NYTP_SIi_INCL_RTIME 4 /* incl real time in sub */
155             #define NYTP_SIi_EXCL_RTIME 5 /* excl real time in sub */
156             #define NYTP_SIi_SUB_NAME 6 /* sub name */
157             #define NYTP_SIi_PROFILE 7 /* ref to profile object */
158             #define NYTP_SIi_REC_DEPTH 8 /* max recursion call depth */
159             #define NYTP_SIi_RECI_RTIME 9 /* recursive incl real time in sub */
160             #define NYTP_SIi_CALLED_BY 10 /* { fid => { line => [...] } } */
161             #define NYTP_SIi_elements 11 /* highest index, plus 1 */
162              
163             /* indices to elements of the sub call info array */
164             /* XXX currently ticks are accumulated into NYTP_SCi_*_TICKS during profiling
165             * and then NYTP_SCi_*_RTIME are calculated and output. This avoids float noise
166             * during profiling but we should really output ticks so the reporting side
167             * can also be more accurate when merging subs, for example.
168             * That'll probably need a file format bump and thus also a major version bump.
169             * Will need coresponding changes to NYTP_SIi_* as well.
170             */
171             #define NYTP_SCi_CALL_COUNT 0 /* count of calls to sub */
172             #define NYTP_SCi_INCL_RTIME 1 /* inclusive real time in sub (set from NYTP_SCi_INCL_TICKS) */
173             #define NYTP_SCi_EXCL_RTIME 2 /* exclusive real time in sub (set from NYTP_SCi_EXCL_TICKS) */
174             #define NYTP_SCi_INCL_TICKS 3 /* inclusive ticks in sub */
175             #define NYTP_SCi_EXCL_TICKS 4 /* exclusive ticks in sub */
176             #define NYTP_SCi_RECI_RTIME 5 /* recursive incl real time in sub */
177             #define NYTP_SCi_REC_DEPTH 6 /* max recursion call depth */
178             #define NYTP_SCi_CALLING_SUB 7 /* name of calling sub */
179             #define NYTP_SCi_elements 8 /* highest index, plus 1 */
180              
181              
182             /* we're not thread-safe (or even multiplicity safe) yet, so detect and bail */
183             #ifdef MULTIPLICITY
184             static PerlInterpreter *orig_my_perl;
185             #endif
186              
187              
188             #define MAX_HASH_SIZE 512
189              
190             typedef struct hash_entry Hash_entry;
191              
192             struct hash_entry {
193             unsigned int id;
194             char* key;
195             int key_len;
196             Hash_entry* next_entry;
197             Hash_entry* next_inserted; /* linked list in insertion order */
198             };
199              
200             typedef struct hash_table {
201             Hash_entry** table;
202             char *name;
203             unsigned int size;
204             unsigned int entry_struct_size;
205             Hash_entry* first_inserted;
206             Hash_entry* prior_inserted; /* = last_inserted before the last insertion */
207             Hash_entry* last_inserted;
208             unsigned int next_id; /* starts at 1, 0 is reserved */
209             } Hash_table;
210              
211             typedef struct {
212             Hash_entry he;
213             unsigned int eval_fid;
214             unsigned int eval_line_num;
215             unsigned int file_size;
216             unsigned int file_mtime;
217             unsigned int fid_flags;
218             char *key_abs;
219             /* update autosplit logic in get_file_id if fields are added or changed */
220             } fid_hash_entry;
221              
222             static Hash_table fidhash = { NULL, "fid", MAX_HASH_SIZE, sizeof(fid_hash_entry), NULL, NULL, NULL, 1 };
223              
224             typedef struct {
225             Hash_entry he;
226             } str_hash_entry;
227             static Hash_table strhash = { NULL, "str", MAX_HASH_SIZE, sizeof(str_hash_entry), NULL, NULL, NULL, 1 };
228             /* END Hash table definitions */
229              
230              
231             /* defaults */
232             static NYTP_file out;
233              
234             /* options and overrides */
235             static char PROF_output_file[MAXPATHLEN+1] = "nytprof.out";
236             static unsigned int profile_opts = NYTP_OPTf_OPTIMIZE | NYTP_OPTf_SAVESRC;
237             static int profile_start = NYTP_START_BEGIN; /* when to start profiling */
238              
239             static char const *nytp_panic_overflow_msg_fmt = "panic: buffer overflow of %s on '%s' (see TROUBLESHOOTING section of the NYTProf documentation)";
240              
241             struct NYTP_options_t {
242             const char *option_name;
243             IV option_iv;
244             char *option_pv; /* strdup'd */
245             };
246              
247             /* XXX boolean options should be moved into profile_opts */
248             static struct NYTP_options_t options[] = {
249             #define profile_usecputime options[0].option_iv
250             { "usecputime", 0, NULL },
251             #define profile_subs options[1].option_iv
252             { "subs", 1, NULL }, /* subroutine times */
253             #define profile_blocks options[2].option_iv
254             { "blocks", 0, NULL }, /* block and sub *exclusive* times */
255             #define profile_leave options[3].option_iv
256             { "leave", 1, NULL }, /* correct block end timing */
257             #define embed_fid_line options[4].option_iv
258             { "expand", 0, NULL },
259             #define trace_level options[5].option_iv
260             { "trace", 0, NULL },
261             #define opt_use_db_sub options[6].option_iv
262             { "use_db_sub", 0, NULL },
263             #define compression_level options[7].option_iv
264             { "compress", default_compression_level, NULL },
265             #define profile_clock options[8].option_iv
266             { "clock", -1, NULL },
267             #define profile_stmts options[9].option_iv
268             { "stmts", 1, NULL }, /* statement exclusive times */
269             #define profile_slowops options[10].option_iv
270             { "slowops", 2, NULL }, /* slow opcodes, typically system calls */
271             #define profile_findcaller options[11].option_iv
272             { "findcaller", 0, NULL }, /* find sub caller instead of trusting outer */
273             #define profile_forkdepth options[12].option_iv
274             { "forkdepth", -1, NULL }, /* how many generations of kids to profile */
275             #define opt_perldb options[13].option_iv
276             { "perldb", 0, NULL }, /* force certain PL_perldb value */
277             #define opt_nameevals options[14].option_iv
278             { "nameevals", 1, NULL }, /* change $^P 0x100 bit */
279             #define opt_nameanonsubs options[15].option_iv
280             { "nameanonsubs", 1, NULL }, /* change $^P 0x200 bit */
281             #define opt_calls options[16].option_iv
282             { "calls", 1, NULL }, /* output call/return event stream */
283             #define opt_evals options[17].option_iv
284             { "evals", 0, NULL } /* handling of string evals - TBD XXX */
285             };
286             /* XXX TODO: add these to options:
287             if (strEQ(option, "file")) {
288             strncpy(PROF_output_file, value, MAXPATHLEN);
289             else if (strEQ(option, "log")) {
290             else if (strEQ(option, "start")) {
291             else if (strEQ(option, "addpid")) {
292             else if (strEQ(option, "optimize") || strEQ(option, "optimise")) {
293             else if (strEQ(option, "savesrc")) {
294             else if (strEQ(option, "endatexit")) {
295             else if (strEQ(option, "libcexit")) {
296             and write the options to the stream when profiling starts.
297             */
298              
299              
300             /* time tracking */
301             #ifdef WIN32
302             /* win32_gettimeofday has ~15 ms resolution on Win32, so use
303             * QueryPerformanceCounter which has us or ns resolution depending on
304             * motherboard and OS. Comment this out to use the old clock.
305             */
306             # define HAS_QPC
307             #endif /* WIN32 */
308              
309             #ifdef HAS_CLOCK_GETTIME
310              
311             /* http://www.freebsd.org/cgi/man.cgi?query=clock_gettime
312             * http://webnews.giga.net.tw/article//mailing.freebsd.performance/710
313             * http://sean.chittenden.org/news/2008/06/01/
314             * Explanation of why gettimeofday() (and presumably CLOCK_REALTIME) may go backwards:
315             * https://groups.google.com/forum/#!topic/comp.os.linux.development.apps/3CkHHyQX918
316             */
317             typedef struct timespec time_of_day_t;
318             # define CLOCK_GETTIME(ts) clock_gettime(profile_clock, ts)
319             # define TICKS_PER_SEC 10000000 /* 10 million - 100ns */
320             # define get_time_of_day(into) CLOCK_GETTIME(&into)
321             # define get_ticks_between(typ, s, e, ticks, overflow) STMT_START { \
322             overflow = 0; \
323             ticks = ((e.tv_sec - s.tv_sec) * TICKS_PER_SEC + (e.tv_nsec / (typ)100) - (s.tv_nsec / (typ)100)); \
324             } STMT_END
325              
326             #else /* !HAS_CLOCK_GETTIME */
327              
328             #ifdef HAS_MACH_TIME
329              
330             #include
331             #include
332             mach_timebase_info_data_t our_timebase;
333             typedef uint64_t time_of_day_t;
334             # define TICKS_PER_SEC 10000000 /* 10 million - 100ns */
335             # define get_time_of_day(into) into = mach_absolute_time()
336             # define get_ticks_between(typ, s, e, ticks, overflow) STMT_START { \
337             overflow = 0; \
338             if( our_timebase.denom == 0 ) mach_timebase_info(&our_timebase); \
339             ticks = (e-s) * our_timebase.numer / our_timebase.denom / (typ)100; \
340             } STMT_END
341              
342             #else /* !HAS_MACH_TIME */
343              
344             #ifdef HAS_QPC
345              
346             # ifndef U64_CONST
347             # ifdef _MSC_VER
348             # define U64_CONST(x) x##UI64
349             # else
350             # define U64_CONST(x) x##ULL
351             # endif
352             # endif
353              
354             unsigned __int64 time_frequency = U64_CONST(0);
355             typedef unsigned __int64 time_of_day_t;
356             # define TICKS_PER_SEC time_frequency
357             # define get_time_of_day(into) QueryPerformanceCounter((LARGE_INTEGER*)&into)
358             # define get_ticks_between(typ, s, e, ticks, overflow) STMT_START { \
359             overflow = 0; /* XXX whats this? */ \
360             ticks = (typ)(e-s); \
361             } STMT_END
362              
363             /* workaround for "error C2520: conversion from unsigned __int64 to double not
364             implemented, use signed __int64" on VC 6 */
365             # if defined(_MSC_VER) && _MSC_VER < 1300 /* < VC 7/2003*/
366             # define NYTPIuint642NV(x) \
367             ((NV)(__int64)((x) & U64_CONST(0x7FFFFFFFFFFFFFFF)) \
368             + -(NV)(__int64)((x) & U64_CONST(0x8000000000000000)))
369             # define get_NV_ticks_between(s, e, ticks, overflow) STMT_START { \
370             overflow = 0; /* XXX whats this? */ \
371             ticks = NYTPIuint642NV(e-s); \
372             } STMT_END
373              
374             # endif
375              
376             #elif defined(HAS_GETTIMEOFDAY)
377             /* on Win32 gettimeofday is always implemented in Perl, not the MS C lib, so
378             either we use PerlProc_gettimeofday or win32_gettimeofday, depending on the
379             Perl defines about NO_XSLOCKS and PERL_IMPLICIT_SYS, to simplify logic,
380             we don't check the defines, just the macro symbol to see if it forwards to
381             presumably the iperlsys.h vtable call or not.
382             See https://github.com/timbunce/devel-nytprof/pull/27#issuecomment-46102026
383             for more details.
384             */
385             #if defined(WIN32) && !defined(gettimeofday)
386             # define gettimeofday win32_gettimeofday
387             #endif
388              
389             typedef struct timeval time_of_day_t;
390             # define TICKS_PER_SEC 1000000 /* 1 million */
391             # define get_time_of_day(into) gettimeofday(&into, NULL)
392             # define get_ticks_between(typ, s, e, ticks, overflow) STMT_START { \
393             overflow = 0; \
394             ticks = ((e.tv_sec - s.tv_sec) * TICKS_PER_SEC + e.tv_usec - s.tv_usec); \
395             } STMT_END
396              
397             #else /* !HAS_GETTIMEOFDAY */
398              
399             /* worst-case fallback - use Time::HiRes which is expensive to call */
400             #define WANT_TIME_HIRES
401             typedef UV time_of_day_t[2];
402             # define TICKS_PER_SEC 1000000 /* 1 million */
403             # define get_time_of_day(into) (*time_hires_u2time_hook)(aTHX_ into)
404             # define get_ticks_between(typ, s, e, ticks, overflow) STMT_START { \
405             overflow = 0; \
406             ticks = ((e[0] - s[0]) * (typ)TICKS_PER_SEC + e[1] - s[1]); \
407             } STMT_END
408              
409             static int (*time_hires_u2time_hook)(pTHX_ UV *) = 0;
410              
411             #endif /* HAS_GETTIMEOFDAY else */
412             #endif /* HAS_MACH_TIME else */
413             #endif /* HAS_CLOCK_GETTIME else */
414              
415             #ifndef get_NV_ticks_between
416             # define get_NV_ticks_between(s, e, ticks, overflow) get_ticks_between(NV, s, e, ticks, overflow)
417             #endif
418              
419             #ifndef NYTPIuint642NV
420             # define NYTPIuint642NV(x) ((NV)(x))
421             #endif
422              
423             static time_of_day_t start_time;
424             static time_of_day_t end_time;
425              
426             static unsigned int last_executed_line;
427             static unsigned int last_executed_fid;
428             static char *last_executed_fileptr;
429             static unsigned int last_block_line;
430             static unsigned int last_sub_line;
431             static unsigned int is_profiling; /* disable_profile() & enable_profile() */
432             static Pid_t last_pid = 0;
433             static NV cumulative_overhead_ticks = 0.0;
434             static NV cumulative_subr_ticks = 0.0;
435             static UV cumulative_subr_seqn = 0;
436             static int main_runtime_used = 0;
437             static SV *DB_CHECK_cv;
438             static SV *DB_INIT_cv;
439             static SV *DB_END_cv;
440             static SV *DB_fin_cv;
441             static const char *class_mop_evaltag = " defined at ";
442             static int class_mop_evaltag_len = 12;
443              
444             static unsigned int ticks_per_sec = 0; /* 0 forces error if not set */
445              
446             static AV *slowop_name_cache;
447              
448             /* prototypes */
449             static void output_header(pTHX);
450             static SV *read_str(pTHX_ NYTP_file ifile, SV *sv);
451             static unsigned int get_file_id(pTHX_ char*, STRLEN, int created_via);
452             static void DB_stmt(pTHX_ COP *cop, OP *op);
453             static void set_option(pTHX_ const char*, const char*);
454             static int enable_profile(pTHX_ char *file);
455             static int disable_profile(pTHX);
456             static void finish_profile(pTHX);
457             static void finish_profile_nocontext(void);
458             static void open_output_file(pTHX_ char *);
459             static int reinit_if_forked(pTHX);
460             static int parse_DBsub_value(pTHX_ SV *sv, STRLEN *filename_len_p, UV *first_line_p, UV *last_line_p, char *sub_name);
461             static void write_cached_fids(void);
462             static void write_src_of_files(pTHX);
463             static void write_sub_line_ranges(pTHX);
464             static void write_sub_callers(pTHX);
465             static AV *store_profile_line_entry(pTHX_ SV *rvav, unsigned int line_num,
466             NV time, int count, unsigned int fid);
467              
468             /* copy of original contents of PL_ppaddr */
469             typedef OP * (CPERLscope(*orig_ppaddr_t))(pTHX);
470             orig_ppaddr_t *PL_ppaddr_orig;
471             #define run_original_op(type) CALL_FPTR(PL_ppaddr_orig[type])(aTHX)
472             static OP *pp_entersub_profiler(pTHX);
473             static OP *pp_subcall_profiler(pTHX_ int type);
474             static OP *pp_leave_profiler(pTHX);
475             static HV *sub_callers_hv;
476             static HV *pkg_fids_hv; /* currently just package names */
477              
478             /* PL_sawampersand is disabled in 5.17.7+ 1a904fc */
479             #if (PERL_VERSION < 17) || ((PERL_VERSION == 17) && (PERL_SUBVERSION < 7)) || defined(PERL_SAWAMPERSAND)
480             static U8 last_sawampersand;
481             #define CHECK_SAWAMPERSAND(fid,line) STMT_START { \
482             if (PL_sawampersand != last_sawampersand) { \
483             if (trace_level >= 1) \
484             logwarn("Slow regex match variable seen (0x%x->0x%x at %u:%u)\n", PL_sawampersand, last_sawampersand, fid, line); \
485             /* XXX this is a hack used by test14 to avoid different behaviour \
486             * pre/post perl 5.17.7 since it's not relevant to the test, which is really \
487             * about AutoSplit */ \
488             if (!getenv("DISABLE_NYTPROF_SAWAMPERSAND")) \
489             NYTP_write_sawampersand(out, fid, line); \
490             last_sawampersand = (U8)PL_sawampersand; \
491             } \
492             } STMT_END
493             #else
494             #define CHECK_SAWAMPERSAND(fid,line) (void)0
495             #endif
496              
497             /* macros for outputing profile data */
498             #ifndef HAS_GETPPID
499             #define getppid() 0
500             #endif
501              
502             static FILE *logfh;
503              
504             /* predeclare to set attribute */
505             static void logwarn(const char *pat, ...) __attribute__format__(__printf__,1,2);
506             static void
507 0           logwarn(const char *pat, ...)
508             {
509             /* we avoid using any perl mechanisms here */
510             va_list args;
511             NYTP_IO_dTHX;
512 0           va_start(args, pat);
513 0 0         if (!logfh)
514 0           logfh = stderr;
515 0           vfprintf(logfh, pat, args);
516             /* Flush to ensure the log message gets pushed out to the kernel.
517             * This flush will be expensive but is needed to ensure the log has recent info
518             * if there's a core dump. Could add an option to disable flushing if needed.
519             */
520 0           fflush(logfh);
521 0           va_end(args);
522 0           }
523              
524              
525             /***********************************
526             * Devel::NYTProf Functions *
527             ***********************************/
528              
529             static NV
530 1380           gettimeofday_nv(void)
531             {
532             #ifdef HAS_GETTIMEOFDAY
533              
534             NYTP_IO_dTHX;
535             struct timeval when;
536 1380           gettimeofday(&when, (struct timezone *) 0);
537 1380           return when.tv_sec + (when.tv_usec / 1000000.0);
538              
539             #else
540             #ifdef WANT_TIME_HIRES
541              
542             NYTP_IO_dTHX;
543             UV time_of_day[2];
544             (*time_hires_u2time_hook)(aTHX_ &time_of_day);
545             return time_of_day[0] + (time_of_day[1] / 1000000.0);
546              
547             #else
548              
549             return (NV)time(); /* practically useless */
550              
551             #endif /* WANT_TIME_HIRES else */
552             #endif /* HAS_GETTIMEOFDAY else */
553             }
554              
555              
556             /**
557             * output file header
558             */
559             static void
560 705           output_header(pTHX)
561             {
562             /* $0 - application name */
563 705           SV *const sv = get_sv("0",GV_ADDWARN);
564 705           time_t basetime = PL_basetime;
565             /* This comes back with a terminating \n, and we don't want that. */
566 705           const char *const basetime_str = ctime(&basetime);
567 705           const STRLEN basetime_str_len = strlen(basetime_str);
568 705           const char version[] = STRINGIFY(PERL_REVISION) "."
569             STRINGIFY(PERL_VERSION) "." STRINGIFY(PERL_SUBVERSION);
570             STRLEN len;
571 705 50         const char *argv0 = SvPV(sv, len);
572              
573 705 50         assert(out != NULL);
574             /* File header with "magic" string, with file major and minor version */
575 705           NYTP_write_header(out, NYTP_FILE_MAJOR_VERSION, NYTP_FILE_MINOR_VERSION);
576             /* Human readable comments and attributes follow
577             * comments start with '#', end with '\n', and are discarded
578             * attributes start with ':', a word, '=', then the value, then '\n'
579             */
580 705           NYTP_write_comment(out, "Perl profile database. Generated by Devel::NYTProf on %.*s",
581 705           (int)basetime_str_len - 1, basetime_str);
582              
583             /* XXX add options, $0, etc, but beware of embedded newlines */
584             /* XXX would be good to adopt a proper charset & escaping for these */
585 705           NYTP_write_attribute_unsigned(out, STR_WITH_LEN("basetime"), (unsigned long)PL_basetime); /* $^T */
586 705           NYTP_write_attribute_string(out, STR_WITH_LEN("application"), argv0, len);
587             /* perl constants: */
588 705           NYTP_write_attribute_string(out, STR_WITH_LEN("perl_version"), version, sizeof(version) - 1);
589 705           NYTP_write_attribute_unsigned(out, STR_WITH_LEN("nv_size"), sizeof(NV));
590             /* sanity checks: */
591 705           NYTP_write_attribute_string(out, STR_WITH_LEN("xs_version"), STR_WITH_LEN(XS_VERSION));
592 705           NYTP_write_attribute_unsigned(out, STR_WITH_LEN("PL_perldb"), PL_perldb);
593             /* these are really options: */
594 705           NYTP_write_attribute_signed(out, STR_WITH_LEN("clock_id"), profile_clock);
595 705           NYTP_write_attribute_unsigned(out, STR_WITH_LEN("ticks_per_sec"), ticks_per_sec);
596              
597             if (1) {
598 705           struct NYTP_options_t *opt_p = options;
599 705           const struct NYTP_options_t *const opt_end
600             = options + sizeof(options) / sizeof (struct NYTP_options_t);
601             do {
602 12690           NYTP_write_option_iv(out, opt_p->option_name, opt_p->option_iv);
603 12690 100         } while (++opt_p < opt_end);
604             }
605              
606              
607             #ifdef HAS_ZLIB
608 705 100         if (compression_level) {
609 385           NYTP_start_deflate_write_tag_comment(out, compression_level);
610             }
611             #endif
612              
613 705           NYTP_write_process_start(out, getpid(), getppid(), gettimeofday_nv());
614              
615 705           write_cached_fids(); /* empty initially, non-empty after fork */
616              
617 705           NYTP_flush(out);
618 705           }
619              
620             static SV *
621 99080           read_str(pTHX_ NYTP_file ifile, SV *sv) {
622             STRLEN len;
623             char *buf;
624             unsigned char tag;
625              
626 99080           NYTP_read(ifile, &tag, sizeof(tag), "string prefix");
627              
628 99080 50         if (NYTP_TAG_STRING != tag && NYTP_TAG_STRING_UTF8 != tag)
    0          
629 0           croak("Profile format error at offset %ld%s, expected string tag but found %d ('%c') (see TROUBLESHOOTING in NYTProf docs)",
630 0           NYTP_tell(ifile)-1, NYTP_type_of_offset(ifile), tag, tag);
631              
632 99080           len = read_u32(ifile);
633 99080 100         if (sv) {
634 57830 50         SvGROW(sv, len+1); /* forces SVt_PV */
    100          
635             }
636             else {
637 41250           sv = newSV(len+1); /* +1 to force SVt_PV even for 0 length string */
638             }
639 99080           SvPOK_on(sv);
640              
641 99080 50         buf = SvPV_nolen(sv);
642 99080           NYTP_read(ifile, buf, len, "string");
643 99080 50         SvCUR_set(sv, len);
    0          
    50          
    0          
    0          
    50          
    0          
644 99080           *SvEND(sv) = '\0';
645              
646 99080 50         if (NYTP_TAG_STRING_UTF8 == tag)
647 0           SvUTF8_on(sv);
648              
649 99080 50         if (trace_level >= 19) {
650 0           STRLEN len2 = len;
651 0           const char *newline = "";
652 0 0         if (buf[len2-1] == '\n') {
653 0           --len2;
654 0           newline = "\\n";
655             }
656 0 0         logwarn(" read string '%.*s%s'%s\n", (int)len2, SvPV_nolen(sv),
    0          
657 0           newline, (SvUTF8(sv)) ? " (utf8)" : "");
658             }
659              
660 99080           return sv;
661             }
662              
663              
664             /**
665             * An implementation of the djb2 hash function by Dan Bernstein.
666             */
667             static unsigned long
668 42511           hash (char* _str, unsigned int len)
669             {
670 42511           char* str = _str;
671 42511           unsigned long hash = 5381;
672              
673 1670254 100         while (len--) {
674             /* hash * 33 + c */
675 1627743           hash = ((hash << 5) + hash) + *str++;
676             }
677 42511           return hash;
678             }
679              
680             /**
681             * Returns a pointer to the ')' after the digits in the (?:re_)?eval prefix.
682             * As the prefix length is known, this gives the length of the digits.
683             */
684             static const char *
685 210           eval_prefix(const char *filename, const char *prefix, STRLEN prefix_len) {
686 210 100         if (memEQ(filename, prefix, prefix_len)
687 150 50         && isdigit((int)filename[prefix_len])) {
688 150           const char *s = filename + prefix_len + 1;
689              
690 206 100         while (isdigit((int)*s))
691 56           ++s;
692 150 50         if (s[0] == ')')
693 150           return s;
694             }
695 60           return NULL;
696             }
697              
698             /**
699             * Return true if filename looks like an eval
700             */
701             static int
702 4044           filename_is_eval(const char *filename, STRLEN filename_len)
703             {
704 4044 100         if (filename_len < 6)
705 157           return 0;
706             /* typically "(eval N)[...]" sometimes just "(eval N)" */
707 3887 100         if (filename[filename_len - 1] != ']' && filename[filename_len - 1] != ')')
    100          
708 3707           return 0;
709 180 100         if (eval_prefix(filename, "(eval ", 6))
710 150           return 1;
711 30 50         if (eval_prefix(filename, "(re_eval ", 9))
712 0           return 1;
713 30           return 0;
714             }
715              
716              
717             /**
718             * Fetch/Store on hash table. entry must always be defined.
719             * hash_op will find hash_entry in the hash table.
720             * hash_entry not in table, insert is false: returns NULL
721             * hash_entry not in table, insert is true: inserts hash_entry and returns hash_entry
722             * hash_entry in table, insert IGNORED: returns pointer to the actual hash entry
723             */
724             static char
725 42511           hash_op(Hash_table *hashtable, char *key, int key_len, Hash_entry** retval, bool insert)
726             {
727 42511           unsigned long h = hash(key, key_len) % hashtable->size;
728              
729 42511           Hash_entry* found = hashtable->table[h];
730 42696 100         while(NULL != found) {
731              
732 11848 100         if (found->key_len == key_len
733 11373 50         && memEQ(found->key, key, key_len)
734             ) {
735 11373           *retval = found;
736 11373           return 0;
737             }
738              
739 475 100         if (NULL == found->next_entry) {
740 290 100         if (insert) {
741              
742             Hash_entry* e;
743 2           Newc(0, e, hashtable->entry_struct_size, char, Hash_entry);
744 2           memzero(e, hashtable->entry_struct_size);
745 2           e->id = hashtable->next_id++;
746 2           e->next_entry = NULL;
747 2           e->key_len = key_len;
748 2           e->key = (char*)safemalloc(sizeof(char) * key_len + 1);
749 2           e->key[key_len] = '\0';
750 2           memcpy(e->key, key, key_len);
751 2           found->next_entry = e;
752 2           *retval = found->next_entry;
753 2           hashtable->prior_inserted = hashtable->last_inserted;
754 2           hashtable->last_inserted = e;
755 2           return 1;
756             }
757             else {
758 288           *retval = NULL;
759 288           return -1;
760             }
761             }
762 185           found = found->next_entry;
763             }
764              
765 30848 100         if (insert) {
766             Hash_entry* e;
767 1622           Newc(0, e, hashtable->entry_struct_size, char, Hash_entry);
768 1622           memzero(e, hashtable->entry_struct_size);
769 1622           e->id = hashtable->next_id++;
770 1622           e->next_entry = NULL;
771 1622           e->key_len = key_len;
772 1622           e->key = (char*)safemalloc(sizeof(char) * e->key_len + 1);
773 1622           e->key[e->key_len] = '\0';
774 1622           memcpy(e->key, key, key_len);
775              
776 1622           *retval = hashtable->table[h] = e;
777              
778 1622 100         if (!hashtable->first_inserted)
779 630           hashtable->first_inserted = e;
780 1622           hashtable->prior_inserted = hashtable->last_inserted;
781 1622           hashtable->last_inserted = e;
782              
783 1622           return 1;
784             }
785              
786 29226           *retval = NULL;
787 29226           return -1;
788             }
789              
790             static void
791 0           hash_stats(Hash_table *hashtable, int verbosity)
792             {
793 0           int idx = 0;
794 0           int max_chain_len = 0;
795 0           int buckets = 0;
796 0           int items = 0;
797              
798 0 0         if (verbosity)
799 0           warn("%s hash: size %d\n", hashtable->name, hashtable->size);
800 0 0         if (!hashtable->table)
801 0           return;
802              
803 0 0         for (idx=0; idx < hashtable->size; ++idx) {
804 0           int chain_len = 0;
805              
806 0           Hash_entry *found = hashtable->table[idx];
807 0 0         if (!found)
808 0           continue;
809              
810 0           ++buckets;
811 0 0         while (NULL != found) {
812 0           ++chain_len;
813 0           ++items;
814 0           found = found->next_entry;
815             }
816 0 0         if (verbosity)
817 0           warn("%s hash[%3d]: %d items\n", hashtable->name, idx, chain_len);
818 0 0         if (chain_len > max_chain_len)
819 0           max_chain_len = chain_len;
820             }
821             /* XXX would be nice to show a histogram of chain lenths */
822 0           warn("%s hash: %d of %d buckets used, %d items, max chain %d\n",
823             hashtable->name, buckets, hashtable->size, items, max_chain_len);
824             }
825              
826              
827             static void
828 1667           emit_fid (fid_hash_entry *fid_info)
829             {
830 1667           char *file_name = fid_info->he.key;
831 1667           STRLEN file_name_len = fid_info->he.key_len;
832 1667           char *file_name_copy = NULL;
833              
834 1667 100         if (fid_info->key_abs) {
835 580           file_name = fid_info->key_abs;
836 580           file_name_len = strlen(file_name);
837             }
838              
839             #ifdef WIN32
840             /* Make sure we only use forward slashes in filenames */
841             if (memchr(file_name, '\\', file_name_len)) {
842             STRLEN i;
843             file_name_copy = (char*)safemalloc(file_name_len);
844             for (i=0; i
845             char ch = file_name[i];
846             file_name_copy[i] = ch == '\\' ? '/' : ch;
847             }
848             file_name = file_name_copy;
849             }
850             #endif
851              
852 1667           NYTP_write_new_fid(out, fid_info->he.id, fid_info->eval_fid,
853             fid_info->eval_line_num, fid_info->fid_flags,
854             fid_info->file_size, fid_info->file_mtime,
855             file_name, (I32)file_name_len);
856              
857 1667 50         if (file_name_copy)
858 0           Safefree(file_name_copy);
859 1667           }
860              
861              
862             /* return true if file is a .pm that was actually loaded as a .pmc */
863             static int
864 1592           fid_is_pmc(pTHX_ fid_hash_entry *fid_info)
865             {
866 1592           int is_pmc = 0;
867 1592           char *file_name = fid_info->he.key;
868 1592           STRLEN len = fid_info->he.key_len;
869 1592 100         if (fid_info->key_abs) {
870 516           file_name = fid_info->key_abs;
871 516           len = strlen(file_name);
872             }
873              
874 1592 100         if (len > 3 && memEQs(file_name + len - 3, 3, ".pm")) {
    100          
875             /* ends in .pm, ok, does a newer .pmc exist? */
876             /* based on doopen_pm() in perl's pp_ctl.c */
877 251           SV *const pmcsv = newSV(len + 2);
878 251           char *const pmc = SvPVX(pmcsv);
879             Stat_t pmstat;
880             Stat_t pmcstat;
881              
882 251           memcpy(pmc, file_name, len);
883 251           pmc[len] = 'c';
884 251           pmc[len + 1] = '\0';
885              
886 251 100         if (PerlLIO_lstat(pmc, &pmcstat) == 0) {
887             /* .pmc exists, is it newer than the .pm (if that exists) */
888              
889             /* Keys in the fid_info are explicitly written with a terminating
890             '\0', so it is safe to pass file_name to a system call. */
891 16 50         if (PerlLIO_lstat(file_name, &pmstat) < 0 ||
    50          
892 16           pmstat.st_mtime < pmcstat.st_mtime) {
893 16           is_pmc = 1; /* hey, maybe it's Larry working on the perl6 comiler */
894             }
895             }
896 251           SvREFCNT_dec(pmcsv);
897             }
898              
899 1592           return is_pmc;
900             }
901              
902              
903             static char *
904 0           fmt_fid_flags(pTHX_ int fid_flags, char *buf, Size_t len) {
905 0           *buf = '\0';
906 0 0         if (fid_flags & NYTP_FIDf_IS_EVAL) my_strlcat(buf, "eval,", len);
907 0 0         if (fid_flags & NYTP_FIDf_IS_FAKE) my_strlcat(buf, "fake,", len);
908 0 0         if (fid_flags & NYTP_FIDf_IS_AUTOSPLIT) my_strlcat(buf, "autosplit,", len);
909 0 0         if (fid_flags & NYTP_FIDf_IS_ALIAS) my_strlcat(buf, "alias,", len);
910 0 0         if (fid_flags & NYTP_FIDf_IS_PMC) my_strlcat(buf, "pmc,", len);
911 0 0         if (fid_flags & NYTP_FIDf_VIA_STMT) my_strlcat(buf, "viastmt,", len);
912 0 0         if (fid_flags & NYTP_FIDf_VIA_SUB) my_strlcat(buf, "viasub,", len);
913 0 0         if (fid_flags & NYTP_FIDf_HAS_SRC) my_strlcat(buf, "hassrc,", len);
914 0 0         if (fid_flags & NYTP_FIDf_SAVE_SRC) my_strlcat(buf, "savesrc,", len);
915 0 0         if (*buf) /* trim trailing comma */
916 0           buf[ my_strlcat(buf,"",len)-1 ] = '\0';
917 0           return buf;
918             }
919              
920              
921             static void
922 705           write_cached_fids()
923             {
924 705           fid_hash_entry *e = (fid_hash_entry*)fidhash.first_inserted;
925 780 100         while (e) {
926 75 50         if ( !(e->fid_flags & NYTP_FIDf_IS_ALIAS) )
927 75           emit_fid(e);
928 75           e = (fid_hash_entry*)e->he.next_inserted;
929             }
930 705           }
931              
932              
933             static fid_hash_entry *
934 32           find_autosplit_parent(pTHX_ char* file_name)
935             {
936             /* extract basename from file_name, then search for most recent entry
937             * in fidhash that has the same basename
938             */
939 32           fid_hash_entry *e = (fid_hash_entry*)fidhash.first_inserted;
940 32           fid_hash_entry *match = NULL;
941 32           const char *sep = "/";
942 32           char *base_end = strstr(file_name, " (autosplit");
943 32           char *base_start = rninstr(file_name, base_end, sep, sep+1);
944             STRLEN base_len;
945 32 50         base_start = (base_start) ? base_start+1 : file_name;
946 32           base_len = base_end - base_start;
947              
948 32 50         if (trace_level >= 3)
949 0           logwarn("find_autosplit_parent of '%.*s' (%s)\n",
950             (int)base_len, base_start, file_name);
951              
952 176 100         for ( ; e; e = (fid_hash_entry*)e->he.next_inserted) {
953             char *e_name;
954              
955 144 100         if (e->fid_flags & NYTP_FIDf_IS_AUTOSPLIT)
956 32           continue;
957 112 50         if (trace_level >= 4)
958 0           logwarn("find_autosplit_parent: checking '%.*s'\n", e->he.key_len, e->he.key);
959              
960             /* skip if key is too small to match */
961 112 100         if (e->he.key_len < base_len)
962 32           continue;
963             /* skip if the last base_len bytes don't match the base name */
964 80           e_name = e->he.key + e->he.key_len - base_len;
965 80 100         if (memcmp(e_name, base_start, base_len) != 0)
966 48           continue;
967             /* skip if the char before the matched key isn't a separator */
968 32 50         if (e->he.key_len > base_len && *(e_name-1) != *sep)
    50          
969 0           continue;
970              
971 32 50         if (trace_level >= 3)
972 0           logwarn("matched autosplit '%.*s' to parent fid %d '%.*s' (%c|%c)\n",
973 0           (int)base_len, base_start, e->he.id, e->he.key_len, e->he.key, *(e_name-1),*sep);
974 32           match = e;
975             /* keep looking, so we'll return the most recently profiled match */
976             }
977              
978 32           return match;
979             }
980              
981              
982             #if 0 /* currently unused */
983             static Hash_entry *
984             lookup_file_entry(pTHX_ char* file_name, STRLEN file_name_len) {
985             Hash_entry entry, *found;
986              
987             entry.key = file_name;
988             entry.key_len = (unsigned int)file_name_len;
989             if (hash_op(fidhash, &entry, &found, 0) == 0)
990             return found;
991              
992             return NULL;
993             }
994             #endif
995              
996              
997             /**
998             * Return a unique persistent id number for a file.
999             * If file name has not been seen before
1000             * then, if created_via is false it returns 0 otherwise it
1001             * assigns a new id and outputs the file and id to the stream.
1002             * If the file name is a synthetic name for an eval then
1003             * get_file_id recurses to process the 'embedded' file name first.
1004             * The created_via flag bit is stored in the fid info
1005             * (currently only used as a diagnostic tool)
1006             */
1007             static unsigned int
1008 42511           get_file_id(pTHX_ char* file_name, STRLEN file_name_len, int created_via)
1009             {
1010              
1011             fid_hash_entry *found, *parent_entry;
1012 42511           AV *src_av = Nullav;
1013              
1014 42511 100         if (1 != hash_op(&fidhash, file_name, file_name_len, (Hash_entry**)&found, (bool)(created_via ? 1 : 0))) {
1015             /* found existing entry or else didn't but didn't create new one either */
1016 40887 50         if (trace_level >= 7) {
1017 0 0         if (found)
1018 0           logwarn("fid %d: %.*s\n", found->he.id, found->he.key_len, found->he.key);
1019 0           else logwarn("fid -: %.*s not profiled\n", (int)file_name_len, file_name);
1020             }
1021 40887 100         return (found) ? found->he.id : 0;
1022             }
1023             /* inserted new entry */
1024 1624 100         if (fidhash.prior_inserted)
1025 994           fidhash.prior_inserted->next_inserted = fidhash.last_inserted;
1026              
1027             /* if this is a synthetic filename for a string eval
1028             * ie "(eval 42)[/some/filename.pl:line]"
1029             * then ensure we've already generated a fid for the underlying
1030             * filename, and associate that fid with this eval fid
1031             */
1032 1624 100         if ('(' == file_name[0]) { /* first char is '(' */
1033 679 100         if (']' == file_name[file_name_len-1]) { /* last char is ']' */
1034 661           char *start = strchr(file_name, '[');
1035 661           const char *colon = ":";
1036             /* can't use strchr here (not nul terminated) so use rninstr */
1037 661           char *end = rninstr(file_name, file_name+file_name_len-1, colon, colon+1);
1038              
1039 661 50         if (!start || !end || start > end) { /* should never happen */
    50          
    50          
1040 0           logwarn("NYTProf unsupported filename syntax '%s'\n", file_name);
1041 0           return 0;
1042             }
1043 661           ++start; /* move past [ */
1044             /* recurse */
1045 661           found->eval_fid = get_file_id(aTHX_ start, end - start,
1046             NYTP_FIDf_IS_EVAL | created_via);
1047 661           found->eval_line_num = atoi(end+1);
1048             }
1049 18 100         else if (filename_is_eval(file_name, file_name_len)) {
1050             /* strange eval that doesn't have a filename associated */
1051             /* seen in mod_perl, possibly from eval_sv(sv) api call */
1052             /* also when nameevals=0 option is in effect */
1053 16           char eval_file[] = "/unknown-eval-invoker";
1054 16           found->eval_fid = get_file_id(aTHX_ eval_file, sizeof(eval_file) - 1,
1055             NYTP_FIDf_IS_EVAL | NYTP_FIDf_IS_FAKE | created_via
1056             );
1057 16           found->eval_line_num = 1;
1058             }
1059             }
1060              
1061             /* detect Class::MOP #line evals */
1062             /* See _add_line_directive() in Class::MOP::Method::Generated */
1063 1624 100         if (!found->eval_fid) {
1064 947           char *tag = ninstr(file_name, file_name+file_name_len, class_mop_evaltag, class_mop_evaltag+class_mop_evaltag_len);
1065 947 50         if (tag) {
1066 0           char *definer = tag + class_mop_evaltag_len;
1067 0           int len = file_name_len - (definer - file_name);
1068 0           found->eval_fid = get_file_id(aTHX_ definer, len, created_via);
1069 0           found->eval_line_num = 1; /* XXX pity Class::MOP doesn't include the line here */
1070 0 0         if (trace_level >= 1)
1071 0           logwarn("Class::MOP eval for '%.*s' (fid %u:%u) from '%.*s'\n",
1072 0           len, definer, found->eval_fid, found->eval_line_num,
1073             (int)file_name_len, file_name);
1074             }
1075             }
1076              
1077             /* is the file is an autosplit, e.g., has a file_name like
1078             * "../../lib/POSIX.pm (autosplit into ../../lib/auto/POSIX/errno.al)"
1079             */
1080 1624 100         if ( ')' == file_name[file_name_len-1] && strstr(file_name, " (autosplit ")) {
    100          
1081 32           found->fid_flags |= NYTP_FIDf_IS_AUTOSPLIT;
1082             }
1083              
1084             /* if the file is an autosplit
1085             * then we want it to have the same fid as the file it was split from.
1086             * Thankfully that file will almost certainly be in the fid hash,
1087             * so we can find it and copy the details.
1088             * We do this after the string eval check above in the (untested) hope
1089             * that string evals inside autoloaded subs get treated properly! XXX
1090             */
1091 1624 100         if (found->fid_flags & NYTP_FIDf_IS_AUTOSPLIT
1092 32 50         && (parent_entry = find_autosplit_parent(aTHX_ file_name))
1093             ) {
1094             /* copy some details from parent_entry to found */
1095 32           found->he.id = parent_entry->he.id;
1096 32           found->eval_fid = parent_entry->eval_fid;
1097 32           found->eval_line_num = parent_entry->eval_line_num;
1098 32           found->file_size = parent_entry->file_size;
1099 32           found->file_mtime = parent_entry->file_mtime;
1100 32           found->fid_flags = parent_entry->fid_flags;
1101             /* prevent write_cached_fids() from writing this fid */
1102 32           found->fid_flags |= NYTP_FIDf_IS_ALIAS;
1103             /* avoid a gap in the fid sequence */
1104 32           --fidhash.next_id;
1105             /* write a log message if tracing */
1106 32 50         if (trace_level >= 2)
1107 0 0         logwarn("Use fid %2u (after %2u:%-4u) %x e%u:%u %.*s %s\n",
1108 0           found->he.id, last_executed_fid, last_executed_line,
1109 0           found->fid_flags, found->eval_fid, found->eval_line_num,
1110 0           found->he.key_len, found->he.key, (found->key_abs) ? found->key_abs : "");
1111             /* bail out without calling emit_fid() */
1112 32           return found->he.id;
1113             }
1114              
1115             /* determine absolute path if file_name is relative */
1116 1592           found->key_abs = NULL;
1117 1592 100         if (!found->eval_fid &&
    100          
1118 132 100         !(file_name[0] == '-'
1119 799 50         && (file_name_len==1 || (file_name[1]=='e' && file_name_len==2))) &&
    50          
    100          
1120             #ifdef WIN32
1121             /* XXX should we check for UNC names too? */
1122             (file_name_len < 3 || !isALPHA(file_name[0]) || file_name[1] != ':' ||
1123             (file_name[2] != '/' && file_name[2] != '\\'))
1124             #else
1125 783           *file_name != '/'
1126             #endif
1127             ) {
1128             char file_name_abs[MAXPATHLEN * 2];
1129             /* Note that the current directory may have changed
1130             * between loading the file and profiling it.
1131             * We don't use realpath() or similar here because we want to
1132             * keep the view of symlinks etc. as the program saw them.
1133             */
1134 516 50         if (!getcwd(file_name_abs, sizeof(file_name_abs))) {
1135             /* eg permission */
1136 0           logwarn("getcwd: %s\n", strerror(errno));
1137             }
1138             else {
1139             #ifdef WIN32
1140             char *p = file_name_abs;
1141             while (*p) {
1142             if ('\\' == *p)
1143             *p = '/';
1144             ++p;
1145             }
1146             if (p[-1] != '/')
1147             #else
1148 516 50         if (strNE(file_name_abs, "/"))
1149             #endif
1150             {
1151 516 50         if (strnEQ(file_name, "./", 2)) {
1152 0           ++file_name;
1153             } else {
1154             #ifndef VMS
1155 516           strcat(file_name_abs, "/");
1156             #endif
1157             }
1158             }
1159 516           strncat(file_name_abs, file_name, file_name_len);
1160 516           found->key_abs = strdup(file_name_abs);
1161             }
1162             }
1163              
1164 1592 100         if (fid_is_pmc(aTHX_ found))
1165 16           found->fid_flags |= NYTP_FIDf_IS_PMC;
1166 1592           found->fid_flags |= created_via; /* NYTP_FIDf_VIA_STMT or NYTP_FIDf_VIA_SUB */
1167              
1168             /* is source code available? */
1169             /* source only available if PERLDB_LINE or PERLDB_SAVESRC is true */
1170             /* which we set if savesrc option is enabled */
1171 1592 100         if ( (src_av = GvAV(gv_fetchfile_flags(found->he.key, found->he.key_len, 0))) )
1172 1356 100         if (av_len(src_av) > -1)
1173 1280           found->fid_flags |= NYTP_FIDf_HAS_SRC;
1174              
1175             /* flag "perl -e '...'" and "perl -" as string evals */
1176 1592 100         if (found->he.key[0] == '-' && (found->he.key_len == 1 ||
    100          
    50          
1177 16 50         (found->he.key[1] == 'e' && found->he.key_len == 2)))
1178 132           found->fid_flags |= NYTP_FIDf_IS_EVAL;
1179              
1180             /* if it's a string eval or a synthetic filename from CODE ref in @INC,
1181             * then we'd like to save the src (NYTP_FIDf_HAS_SRC) if it's available
1182             */
1183 1592 100         if (found->eval_fid
1184 915 100         || (found->fid_flags & NYTP_FIDf_IS_EVAL)
1185 763 100         || (profile_opts & NYTP_OPTf_SAVESRC)
1186 376 100         || (found->he.key_len > 10 && found->he.key[9] == 'x' && strnEQ(found->he.key, "/loader/0x", 10))
    50          
    0          
1187             ) {
1188 1216           found->fid_flags |= NYTP_FIDf_SAVE_SRC;
1189             }
1190              
1191 1592           emit_fid(found);
1192              
1193 1592 50         if (trace_level >= 2) {
1194             char buf[80];
1195             /* including last_executed_fid can be handy for tracking down how
1196             * a file got loaded */
1197 0 0         logwarn("New fid %2u (after %2u:%-4u) 0x%02x e%u:%u %.*s %s %s\n",
1198 0           found->he.id, last_executed_fid, last_executed_line,
1199 0           found->fid_flags, found->eval_fid, found->eval_line_num,
1200 0           found->he.key_len, found->he.key, (found->key_abs) ? found->key_abs : "",
1201 0           fmt_fid_flags(aTHX_ found->fid_flags, buf, sizeof(buf))
1202             );
1203             }
1204              
1205 42511           return found->he.id;
1206             }
1207              
1208              
1209             static UV
1210 11094           uv_from_av(pTHX_ AV *av, int idx, UV default_uv)
1211             {
1212 11094           SV **svp = av_fetch(av, idx, 0);
1213 11094 100         UV uv = (!svp || !SvOK(*svp)) ? default_uv : SvUV(*svp);
    50          
    0          
    0          
    50          
1214 11094           return uv;
1215             }
1216              
1217             static NV
1218 16641           nv_from_av(pTHX_ AV *av, int idx, NV default_nv)
1219             {
1220 16641           SV **svp = av_fetch(av, idx, 0);
1221 16641 100         NV nv = (!svp || !SvOK(*svp)) ? default_nv : SvNV(*svp);
    50          
    0          
    0          
    50          
1222 16641           return nv;
1223             }
1224              
1225              
1226             static const char *
1227 0           cx_block_type(PERL_CONTEXT *cx) {
1228             static char buf[20];
1229 0           switch (CxTYPE(cx)) {
1230 0           case CXt_NULL: return "CXt_NULL";
1231 0           case CXt_SUB: return "CXt_SUB";
1232 0           case CXt_FORMAT: return "CXt_FORMAT";
1233 0           case CXt_EVAL: return "CXt_EVAL";
1234 0           case CXt_SUBST: return "CXt_SUBST";
1235             #ifdef CXt_WHEN
1236 0           case CXt_WHEN: return "CXt_WHEN";
1237             #endif
1238 0           case CXt_BLOCK: return "CXt_BLOCK";
1239             #ifdef CXt_GIVEN
1240 0           case CXt_GIVEN: return "CXt_GIVEN";
1241             #endif
1242             #ifdef CXt_LOOP
1243             case CXt_LOOP: return "CXt_LOOP";
1244             #endif
1245             #ifdef CXt_LOOP_FOR
1246             case CXt_LOOP_FOR: return "CXt_LOOP_FOR";
1247             #endif
1248             #ifdef CXt_LOOP_PLAIN
1249 0           case CXt_LOOP_PLAIN: return "CXt_LOOP_PLAIN";
1250             #endif
1251             #ifdef CXt_LOOP_LAZYSV
1252 0           case CXt_LOOP_LAZYSV: return "CXt_LOOP_LAZYSV";
1253             #endif
1254             #ifdef CXt_LOOP_LAZYIV
1255 0           case CXt_LOOP_LAZYIV: return "CXt_LOOP_LAZYIV";
1256             #endif
1257             #ifdef CXt_LOOP_ARY
1258 0           case CXt_LOOP_ARY: return "CXt_LOOP_ARY";
1259             #endif
1260             #ifdef CXt_LOOP_LIST
1261 0           case CXt_LOOP_LIST: return "CXt_LOOP_LIST";
1262             #endif
1263             }
1264             /* short-lived and not thread safe but we only use this for tracing
1265             * and it should never be reached anyway
1266             */
1267 0           sprintf(buf, "CXt_%ld", (long)CxTYPE(cx));
1268 0           return buf;
1269             }
1270              
1271              
1272             /* based on S_dopoptosub_at() from perl pp_ctl.c */
1273             static int
1274 1388076           dopopcx_at(pTHX_ PERL_CONTEXT *cxstk, I32 startingblock, UV cx_type_mask)
1275             {
1276             I32 i;
1277             PERL_CONTEXT *cx;
1278 1388076 50         for (i = startingblock; i >= 0; i--) {
1279             UV type_bit;
1280 1388076           cx = &cxstk[i];
1281 1388076           type_bit = 1 << CxTYPE(cx);
1282 1388076 50         if (type_bit & cx_type_mask)
1283 1388076           return i;
1284             }
1285 0           return i; /* == -1 */
1286             }
1287              
1288              
1289             static COP *
1290 1489841           start_cop_of_context(pTHX_ PERL_CONTEXT *cx)
1291             {
1292             OP *start_op, *o;
1293             int type;
1294 1489841           int trace = 6;
1295              
1296 1489841           switch (CxTYPE(cx)) {
1297             case CXt_EVAL:
1298 1764           start_op = (OP*)cx->blk_oldcop;
1299 1764           break;
1300             case CXt_FORMAT:
1301 0           start_op = CvSTART(cx->blk_sub.cv);
1302 0           break;
1303             case CXt_SUB:
1304 719253           start_op = CvSTART(cx->blk_sub.cv);
1305 719253           break;
1306             #ifdef CXt_LOOP
1307             case CXt_LOOP:
1308             # if (PERL_VERSION < 10) || (PERL_VERSION == 9 && !defined(CX_LOOP_NEXTOP_GET))
1309             start_op = cx->blk_loop.redo_op;
1310             # else
1311             start_op = cx->blk_loop.my_op->op_redoop;
1312             # endif
1313             break;
1314             #else
1315             # if defined (CXt_LOOP_PLAIN) && defined(CXt_LOOP_LAZYIV) && defined (CXt_LOOP_LAZYSV)
1316             /* This is Perl 5.11.0 or later */
1317             case CXt_LOOP_LAZYIV:
1318             case CXt_LOOP_LAZYSV:
1319             case CXt_LOOP_PLAIN:
1320             # if defined (CXt_LOOP_FOR)
1321             case CXt_LOOP_FOR:
1322             # else
1323             case CXt_LOOP_ARY:
1324             case CXt_LOOP_LIST:
1325             # endif
1326 762844           start_op = cx->blk_loop.my_op->op_redoop;
1327 762844           break;
1328             # else
1329             # warning "The perl you are using is missing some essential defines. Your results may not be accurate."
1330             # endif
1331             #endif
1332             case CXt_BLOCK:
1333             /* this will be NULL for the top-level 'main' block */
1334 5980           start_op = (OP*)cx->blk_oldcop;
1335 5980           break;
1336             case CXt_SUBST: /* FALLTHRU */
1337             case CXt_NULL: /* FALLTHRU */
1338             default:
1339 0           start_op = NULL;
1340 0           break;
1341             }
1342 1489841 50         if (!start_op) {
1343 0 0         if (trace_level >= trace)
1344 0           logwarn("\tstart_cop_of_context: can't find start of %s\n",
1345             cx_block_type(cx));
1346 0           return NULL;
1347             }
1348             /* find next cop from OP */
1349 1489841           o = start_op;
1350 1489841 50         while ( o && (type = (o->op_type) ? o->op_type : (int)o->op_targ) ) {
    50          
    50          
1351 1489841 100         if (type == OP_NEXTSTATE ||
    100          
1352             #if PERL_VERSION < 11
1353             type == OP_SETSTATE ||
1354             #endif
1355             type == OP_DBSTATE)
1356             {
1357 1415316 50         if (trace_level >= trace)
1358 0 0         logwarn("\tstart_cop_of_context %s is %s line %d of %s\n",
    0          
1359 0           cx_block_type(cx), OP_NAME(o), (int)CopLINE((COP*)o),
1360 0           OutCopFILE((COP*)o));
1361 1415316           return (COP*)o;
1362             }
1363 74525 50         if (trace_level >= trace)
1364 0 0         logwarn("\tstart_cop_of_context %s op '%s' isn't a cop, giving up\n",
1365 0           cx_block_type(cx), OP_NAME(o));
1366 74525           return NULL;
1367             #if 0 /* old code that never worked very well anyway */
1368             if (CxTYPE(cx) == CXt_LOOP) /* e.g. "eval $_ for @ary" */
1369             return NULL;
1370             /* should never get here but we do */
1371             if (trace_level >= trace) {
1372             logwarn("\tstart_cop_of_context %s op '%s' isn't a cop\n",
1373             cx_block_type(cx), OP_NAME(o));
1374             if (trace_level > trace)
1375             do_op_dump(1, PerlIO_stderr(), o);
1376             }
1377             o = o->op_next;
1378             #endif
1379             }
1380 0 0         if (trace_level >= 3) {
1381 0           logwarn("\tstart_cop_of_context: can't find next cop for %s line %ld\n",
1382 0           cx_block_type(cx), (long)CopLINE(PL_curcop_nytprof));
1383 0           do_op_dump(1, PerlIO_stderr(), start_op);
1384             }
1385 0           return NULL;
1386             }
1387              
1388              
1389             /* Walk up the context stack calling callback
1390             * return first context that callback returns true for
1391             * else return null.
1392             * UV cx_type_mask is a bit flag that specifies what kinds of contexts the
1393             * callback should be called for: (cx_type_mask & (1 << CxTYPE(cx)))
1394             * Use ~0 to stop at all contexts.
1395             * The callback is called with the context pointer and a pointer to
1396             * a copy of the UV cx_type_mask argument (so it can change it on the fly).
1397             */
1398             static PERL_CONTEXT *
1399 723259           visit_contexts(pTHX_ UV cx_type_mask, int (*callback)(pTHX_ PERL_CONTEXT *cx,
1400             UV *cx_type_mask_ptr))
1401             {
1402             /* modelled on pp_caller() in pp_ctl.c */
1403 723259           I32 cxix = cxstack_ix;
1404 723259           PERL_CONTEXT *cx = NULL;
1405 723259           PERL_CONTEXT *ccstack = cxstack;
1406 723259           PERL_SI *top_si = PL_curstackinfo;
1407              
1408 723259 50         if (trace_level >= 6)
1409 0           logwarn("visit_contexts: \n");
1410              
1411             while (1) {
1412             /* we may be in a higher stacklevel, so dig down deeper */
1413             /* XXX so we'll miss code in sort blocks and signals? */
1414             /* callback should perhaps be moved to dopopcx_at */
1415 2111335 50         while (cxix < 0 && top_si->si_type != PERLSI_MAIN) {
    0          
1416 0 0         if (trace_level >= 6)
1417 0           logwarn("Not on main stack (type %d); digging top_si %p->%p, ccstack %p->%p\n",
1418 0           (int)top_si->si_type, (void*)top_si, (void*)top_si->si_prev,
1419 0           (void*)ccstack, (void*)top_si->si_cxstack);
1420 0           top_si = top_si->si_prev;
1421 0           ccstack = top_si->si_cxstack;
1422 0           cxix = dopopcx_at(aTHX_ ccstack, top_si->si_cxix, cx_type_mask);
1423             }
1424 2111335 50         if (cxix < 0 || (cxix == 0 && !top_si->si_prev)) {
    100          
    100          
1425             /* cxix==0 && !top_si->si_prev => top-level BLOCK */
1426 2422 50         if (trace_level >= 5)
1427 0           logwarn("visit_contexts: reached top of context stack\n");
1428 2422           return NULL;
1429             }
1430 2108913           cx = &ccstack[cxix];
1431 2108913 50         if (trace_level >= 5)
1432 0           logwarn("visit_context: %s cxix %d (si_prev %p)\n",
1433 0           cx_block_type(cx), (int)cxix, (void*)top_si->si_prev);
1434 2108913 100         if (callback(aTHX_ cx, &cx_type_mask))
1435 720837           return cx;
1436             /* no joy, look further */
1437 1388076           cxix = dopopcx_at(aTHX_ ccstack, cxix - 1, cx_type_mask);
1438 1388076           }
1439             return NULL; /* not reached */
1440             }
1441              
1442              
1443             static int
1444 1415316           _cop_in_same_file(COP *a, COP *b)
1445             {
1446 1415316           int same = 0;
1447 1415316 50         char *a_file = OutCopFILE(a);
1448 1415316 50         char *b_file = OutCopFILE(b);
1449 1415316 100         if (a_file == b_file)
1450 813724           same = 1;
1451             else
1452             /* fallback to strEQ, surprisingly common (check why) XXX expensive */
1453 601592 50         if (strEQ(a_file, b_file))
1454 0           same = 1;
1455 1415316           return same;
1456             }
1457              
1458              
1459             static int
1460 2108913           _check_context(pTHX_ PERL_CONTEXT *cx, UV *cx_type_mask_ptr)
1461             {
1462             COP *near_cop;
1463             PERL_UNUSED_ARG(cx_type_mask_ptr);
1464              
1465 2108913 100         if (CxTYPE(cx) == CXt_SUB) {
1466 719253 50         if (PL_debstash && CvSTASH(cx->blk_sub.cv) == PL_debstash)
    50          
1467 0           return 0; /* skip subs in DB package */
1468              
1469 719253           near_cop = start_cop_of_context(aTHX_ cx);
1470              
1471             /* only use the cop if it's in the same file */
1472 719253 100         if (_cop_in_same_file(near_cop, PL_curcop_nytprof)) {
1473 119245           last_sub_line = CopLINE(near_cop);
1474             /* treat sub as a block if we've not found a block yet */
1475 119245 100         if (!last_block_line)
1476 24970           last_block_line = last_sub_line;
1477             }
1478              
1479 719253 50         if (trace_level >= 8) {
1480 0           GV *sv = CvGV(cx->blk_sub.cv);
1481 0 0         logwarn("\tat %d: block %d sub %d for %s %s\n",
1482             last_executed_line, last_block_line, last_sub_line,
1483 0           cx_block_type(cx), (sv) ? GvNAME(sv) : "");
1484 0 0         if (trace_level >= 99)
1485 0           sv_dump((SV*)cx->blk_sub.cv);
1486             }
1487              
1488 719253           return 1; /* stop looking */
1489             }
1490              
1491             /* NULL, EVAL, LOOP, SUBST, BLOCK context */
1492 1389660 50         if (trace_level >= 6)
1493 0           logwarn("\t%s\n", cx_block_type(cx));
1494              
1495             /* if we've got a block line, skip this context and keep looking for a sub */
1496 1389660 100         if (last_block_line)
1497 619072           return 0;
1498              
1499             /* if we can't get a line number for this context, skip it */
1500 770588 100         if ((near_cop = start_cop_of_context(aTHX_ cx)) == NULL)
1501 74525           return 0;
1502              
1503             /* if this context is in a different file... */
1504 696063 100         if (!_cop_in_same_file(near_cop, PL_curcop_nytprof)) {
1505             /* if we started in a string eval ... */
1506 1584 50         if ('(' == *OutCopFILE(PL_curcop_nytprof)) {
    100          
1507             /* give up XXX could do better here */
1508 944           last_block_line = last_sub_line = last_executed_line;
1509 944           return 1;
1510             }
1511             /* shouldn't happen! */
1512 640 50         if (trace_level >= 5)
1513 0 0         logwarn("at %d: %s in different file (%s, %s)\n",
    0          
1514             last_executed_line, cx_block_type(cx),
1515 0           OutCopFILE(near_cop), OutCopFILE(PL_curcop_nytprof));
1516 640           return 1; /* stop looking */
1517             }
1518              
1519 694479           last_block_line = CopLINE(near_cop);
1520 694479 50         if (trace_level >= 5)
1521 0           logwarn("\tat %d: block %d for %s\n",
1522             last_executed_line, last_block_line, cx_block_type(cx));
1523 694479           return 0;
1524             }
1525              
1526              
1527             /* copied from perl's S_closest_cop in util.c as used by warn(...) */
1528              
1529             static const COP*
1530 555           closest_cop(pTHX_ const COP *cop, const OP *o)
1531             {
1532             dVAR;
1533             /* Look for PL_op starting from o. cop is the last COP we've seen. */
1534 555 50         if (!o || o == PL_op)
    0          
1535 555           return cop;
1536 0 0         if (o->op_flags & OPf_KIDS) {
1537             const OP *kid;
1538 0 0         for (kid = cUNOPo->op_first; kid; kid = OpSIBLING(kid)) {
    0          
1539             const COP *new_cop;
1540             /* If the OP_NEXTSTATE has been optimised away we can still use it
1541             * the get the file and line number. */
1542 0 0         if (kid->op_type == OP_NULL && kid->op_targ == OP_NEXTSTATE)
    0          
1543 0           cop = (const COP *)kid;
1544             /* Keep searching, and return when we've found something. */
1545 0           new_cop = closest_cop(aTHX_ cop, kid);
1546 0 0         if (new_cop)
1547 0           return new_cop;
1548             }
1549             }
1550             /* Nothing found. */
1551 0           return NULL;
1552             }
1553              
1554              
1555             /**
1556             * Main statement profiling function. Called before each breakable statement.
1557             */
1558             static void
1559 874840           DB_stmt(pTHX_ COP *cop, OP *op)
1560             {
1561             int saved_errno;
1562             char *file;
1563             long elapsed, overflow;
1564              
1565 874840 100         if (!is_profiling || !profile_stmts)
    100          
1566 10475           return;
1567             #ifdef MULTIPLICITY
1568             if (orig_my_perl && my_perl != orig_my_perl)
1569             return;
1570             #endif
1571              
1572 864365           saved_errno = errno;
1573              
1574 864365           get_time_of_day(end_time);
1575 864365           get_ticks_between(long, start_time, end_time, elapsed, overflow);
1576              
1577 864365           reinit_if_forked(aTHX);
1578              
1579             /* XXX move down into the (file != last_executed_fileptr) block ? */
1580             CHECK_SAWAMPERSAND(last_executed_fid, last_executed_line);
1581              
1582 864365 100         if (last_executed_fid) {
1583 863728 100         if (profile_blocks)
1584 723375           NYTP_write_time_block(out, elapsed, overflow, last_executed_fid,
1585             last_executed_line, last_block_line,
1586             last_sub_line);
1587             else
1588 140353           NYTP_write_time_line(out, elapsed, overflow, last_executed_fid,
1589             last_executed_line);
1590              
1591 863728 50         if (trace_level >= 5) /* previous fid:line and how much time we spent there */
1592 0           logwarn("\t@%d:%-4d %2ld ticks (%u, %u)\n",
1593             last_executed_fid, last_executed_line,
1594             elapsed, last_block_line, last_sub_line);
1595             }
1596              
1597 864365 100         if (!cop)
1598 864301           cop = PL_curcop_nytprof;
1599 864365 100         if ( (last_executed_line = CopLINE(cop)) == 0 ) {
1600             /* Might be a cop that has been optimised away. We can try to find such a
1601             * cop by searching through the optree starting from the sibling of PL_curcop.
1602             * See Perl_vmess in perl's util.c for how warn("...") finds the line number.
1603             */
1604 555 50         cop = (COP*)closest_cop(aTHX_ cop, OpSIBLING(cop));
1605 555 50         if (!cop)
1606 0           cop = PL_curcop_nytprof;
1607 555           last_executed_line = CopLINE(cop);
1608 555 50         if (!last_executed_line) {
1609             /* perl options, like -n, -p, -Mfoo etc can cause this because perl effectively
1610             * treats those as 'line 0', so we try not to warn in those cases.
1611             */
1612 555 50         char *pkg_name = CopSTASHPV(cop);
    50          
    50          
    50          
    0          
    50          
    50          
1613 555 50         int is_preamble = (PL_scopestack_ix <= 7 && strEQ(pkg_name,"main"));
    50          
1614              
1615             /* op is null when called via finish_profile called by END */
1616 555 50         if (!is_preamble && op) {
    0          
1617             /* warn() can't either, in the cases I've encountered */
1618 0 0         logwarn("Unable to determine line number in %s (ssix%d)\n",
1619 0           OutCopFILE(cop), (int)PL_scopestack_ix);
1620 0 0         if (trace_level > 5)
1621 0           do_op_dump(1, PerlIO_stderr(), (OP*)cop);
1622             }
1623 555           last_executed_line = 1; /* don't want zero line numbers in data */
1624             }
1625             }
1626              
1627 864365 50         file = OutCopFILE(cop);
1628 864365 100         if (!last_executed_fid) { /* first time */
1629 637 50         if (trace_level >= 1) {
1630 0 0         logwarn("~ first statement profiled at line %d of %s, pid %ld\n",
1631 0           (int)CopLINE(cop), OutCopFILE(cop), (long)getpid());
1632             }
1633             }
1634 864365 100         if (file != last_executed_fileptr) { /* cache (hit ratio ~50% e.g. for perlcritic) */
1635 3873           last_executed_fileptr = file;
1636 3873           last_executed_fid = get_file_id(aTHX_ file, strlen(file), NYTP_FIDf_VIA_STMT);
1637             }
1638              
1639 864365 50         if (trace_level >= 7) /* show the fid:line we're about to execute */
1640 0 0         logwarn("\t@%d:%-4d... %s\n", last_executed_fid, last_executed_line,
1641 0           (profile_blocks) ? "looking for block and sub lines" : "");
1642              
1643 864365 100         if (profile_blocks) {
1644 723984           last_block_line = 0;
1645 723984           last_sub_line = 0;
1646 723984 100         if (op) {
1647 723259           visit_contexts(aTHX_ ~0, &_check_context);
1648             }
1649             /* if we didn't find block or sub scopes then use current line */
1650 723984 100         if (!last_block_line) last_block_line = last_executed_line;
1651 723984 100         if (!last_sub_line) last_sub_line = last_executed_line;
1652             }
1653              
1654 864365           get_time_of_day(start_time);
1655              
1656             /* measure time we've spent measuring so we can discount it */
1657 864365           get_ticks_between(long, end_time, start_time, elapsed, overflow);
1658 864365           cumulative_overhead_ticks += elapsed;
1659              
1660 864365           SETERRNO(saved_errno, 0);
1661 864365           return;
1662             }
1663              
1664              
1665             static void
1666 251254           DB_leave(pTHX_ OP *op, OP *prev_op)
1667             {
1668             int saved_errno, is_multicall;
1669             unsigned int prev_last_executed_fid, prev_last_executed_line;
1670              
1671             /* Called _after_ ops that indicate we've completed a statement
1672             * and are returning into the middle of some outer statement.
1673             * Used to ensure that time between now and the _next_ statement
1674             * being entered, is allocated to the outer statement we've
1675             * returned into and not the previous statement.
1676             * PL_curcop has already been updated.
1677             */
1678              
1679 251254 100         if (!is_profiling || !out || !profile_stmts)
    50          
    50          
1680 2159           return;
1681             #ifdef MULTIPLICITY
1682             if (orig_my_perl && my_perl != orig_my_perl)
1683             return;
1684             #endif
1685              
1686 249095           saved_errno = errno;
1687 249095           prev_last_executed_fid = last_executed_fid;
1688 249095           prev_last_executed_line = last_executed_line;
1689              
1690             #if defined(CxMULTICALL) && 0 /* disabled for now */
1691             /* pp_return, pp_leavesub and pp_leavesublv
1692             * return a NULL op when returning from a MULTICALL.
1693             * See Lightweight Callbacks in perlcall.
1694             */
1695             is_multicall = (!op && cxstack_ix >= 0 && CxMULTICALL(&cxstack[cxstack_ix]));
1696             #else
1697 249095           is_multicall = 0;
1698             #endif
1699              
1700             /* measure and output end time of previous statement
1701             * (earlier than it would have been done)
1702             * and switch back to measuring the 'calling' statement
1703             */
1704 249095           DB_stmt(aTHX_ NULL, op);
1705              
1706             /* output a 'discount' marker to indicate the next statement time shouldn't
1707             * increment the count (because the time is not for a new statement but simply
1708             * a continuation of a previously counted statement).
1709             */
1710 249095           NYTP_write_discount(out);
1711              
1712             /* special cases */
1713 249095 100         if (last_executed_line == prev_last_executed_line
1714 198447           && last_executed_fid == prev_last_executed_fid
1715             ) {
1716             /* XXX OP_UNSTACK needs help */
1717             }
1718              
1719 249095 50         if (trace_level >= 5) {
1720 0 0         logwarn("\tleft %u:%u via %s back to %s at %u:%u (b%u s%u) - discounting next statement%s\n",
    0          
    0          
1721             prev_last_executed_fid, prev_last_executed_line,
1722 0 0         OP_NAME_safe(prev_op), OP_NAME_safe(op),
    0          
1723             last_executed_fid, last_executed_line, last_block_line, last_sub_line,
1724 0 0         (op || is_multicall) ? "" : ", LEAVING PERL"
1725             );
1726             }
1727              
1728 249095           SETERRNO(saved_errno, 0);
1729             }
1730              
1731              
1732             /**
1733             * Sets or toggles the option specified by 'option'.
1734             */
1735             static void
1736 11618           set_option(pTHX_ const char* option, const char* value)
1737             {
1738 11618 50         if (!option || !*option)
    50          
1739 0           croak("%s: invalid option", "NYTProf set_option");
1740 11618 50         if (!value || !*value)
    50          
1741 0           croak("%s: '%s' has no value", "NYTProf set_option", option);
1742              
1743 11618 100         if (strEQ(option, "file")) {
1744 1297           strncpy(PROF_output_file, value, MAXPATHLEN);
1745             }
1746 10321 50         else if (strEQ(option, "log")) {
1747 0           FILE *fp = fopen(value, "a");
1748 0 0         if (!fp) {
1749 0           logwarn("Can't open log file '%s' for writing: %s\n",
1750 0           value, strerror(errno));
1751 0           return;
1752             }
1753 0           logfh = fp;
1754             }
1755 10321 100         else if (strEQ(option, "start")) {
1756 1281 100         if (strEQ(value,"begin")) profile_start = NYTP_START_BEGIN;
1757 1205 50         else if (strEQ(value,"init")) profile_start = NYTP_START_INIT;
1758 0 0         else if (strEQ(value,"end")) profile_start = NYTP_START_END;
1759 0 0         else if (strEQ(value,"no")) profile_start = NYTP_START_NO;
1760 0           else croak("NYTProf option 'start' has invalid value '%s'\n", value);
1761             }
1762 9040 100         else if (strEQ(option, "addpid")) {
1763 30           profile_opts = (atoi(value))
1764 15           ? profile_opts | NYTP_OPTf_ADDPID
1765 15 50         : profile_opts & ~NYTP_OPTf_ADDPID;
1766             }
1767 9025 50         else if (strEQ(option, "addtimestamp")) {
1768 0           profile_opts = (atoi(value))
1769 0           ? profile_opts | NYTP_OPTf_ADDTIMESTAMP
1770 0 0         : profile_opts & ~NYTP_OPTf_ADDTIMESTAMP;
1771             }
1772 9025 100         else if (strEQ(option, "optimize") || strEQ(option, "optimise")) {
    50          
1773 32           profile_opts = (atoi(value))
1774 16           ? profile_opts | NYTP_OPTf_OPTIMIZE
1775 16 50         : profile_opts & ~NYTP_OPTf_OPTIMIZE;
1776             }
1777 9009 100         else if (strEQ(option, "savesrc")) {
1778 2560           profile_opts = (atoi(value))
1779 696           ? profile_opts | NYTP_OPTf_SAVESRC
1780 1280 100         : profile_opts & ~NYTP_OPTf_SAVESRC;
1781             }
1782 7729 50         else if (strEQ(option, "endatexit")) {
1783 0 0         if (atoi(value))
1784 0           PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
1785             }
1786 7729 50         else if (strEQ(option, "libcexit")) {
1787 0 0         if (atoi(value))
1788 0           atexit(finish_profile_nocontext);
1789             }
1790             else {
1791              
1792 7729           struct NYTP_options_t *opt_p = options;
1793 7729           const struct NYTP_options_t *const opt_end
1794             = options + sizeof(options) / sizeof (struct NYTP_options_t);
1795 7729           bool found = FALSE;
1796             do {
1797 64466 100         if (strEQ(option, opt_p->option_name)) {
1798 7729           opt_p->option_iv = (IV)strtol(value, NULL, 0);
1799 7729           found = TRUE;
1800 7729           break;
1801             }
1802 56737 50         } while (++opt_p < opt_end);
1803 7729 50         if (!found) {
1804 0           logwarn("Unknown NYTProf option: '%s'\n", option);
1805 0           return;
1806             }
1807             }
1808 11618 50         if (trace_level)
1809 0           logwarn("# %s=%s\n", option, value);
1810             }
1811              
1812              
1813             /**
1814             * Open the output file. This is encapsulated because the code can be reused
1815             * without the environment parsing overhead after each fork.
1816             */
1817             static void
1818 705           open_output_file(pTHX_ char *filename)
1819             {
1820             char filename_buf[MAXPATHLEN];
1821             /* 'x' is a GNU C lib extension for O_EXCL which gives us a little
1822             * extra protection, but it isn't POSIX compliant */
1823 705 50         const char *mode = (strnEQ(filename, "/dev/", 4) ? "wb" : "wbx");
1824             /* most systems that don't support it will silently ignore it
1825             * but for some we need to remove it to avoid an error */
1826             #ifdef WIN32
1827             mode = "wb";
1828             #endif
1829             #ifdef VMS
1830             mode = "wb";
1831             #endif
1832              
1833 705 100         if ((profile_opts & (NYTP_OPTf_ADDPID|NYTP_OPTf_ADDTIMESTAMP))
1834 663 50         || out /* already opened so assume we're forking and add the pid */
1835             ) {
1836 42 50         if (strlen(filename) >= MAXPATHLEN-(20+20)) /* buffer overrun protection */
1837 0           croak("Filename '%s' too long", filename);
1838 42           strcpy(filename_buf, filename);
1839 42 50         if ((profile_opts & NYTP_OPTf_ADDPID) || out)
    0          
1840 42           sprintf(&filename_buf[strlen(filename_buf)], ".%d", getpid());
1841 42 50         if ( profile_opts & NYTP_OPTf_ADDTIMESTAMP )
1842 0           sprintf(&filename_buf[strlen(filename_buf)], ".%.0" NVff, gettimeofday_nv());
1843 42           filename = filename_buf;
1844             /* caller is expected to have purged/closed old out if appropriate */
1845             }
1846              
1847             /* some protection against multiple processes writing to the same file */
1848 705           unlink(filename); /* throw away any previous file */
1849              
1850 705           out = NYTP_open(filename, mode);
1851 705 50         if (!out) {
1852 0           int fopen_errno = errno;
1853 0           const char *hint = "";
1854 0 0         if (fopen_errno==EEXIST && !(profile_opts & NYTP_OPTf_ADDPID))
    0          
1855 0           hint = " (enable addpid option to protect against concurrent writes)";
1856 0           disable_profile(aTHX);
1857 0           croak("NYTProf failed to open '%s' for writing, error %d: %s%s",
1858             filename, fopen_errno, strerror(fopen_errno), hint);
1859             }
1860 705 50         if (trace_level >= 1)
1861 0           logwarn("~ opened %s at %.6" NVff "\n", filename, gettimeofday_nv());
1862              
1863 705           output_header(aTHX);
1864 705           }
1865              
1866              
1867             static void
1868 711           close_output_file(pTHX) {
1869             int result;
1870             NV timeofday;
1871              
1872 711 100         if (!out)
1873 36           return;
1874              
1875 675           timeofday = gettimeofday_nv(); /* before write_*() calls */
1876 675           NYTP_write_attribute_nv(out, STR_WITH_LEN("cumulative_overhead_ticks"), cumulative_overhead_ticks);
1877              
1878 675           write_src_of_files(aTHX);
1879 675           write_sub_line_ranges(aTHX);
1880 675           write_sub_callers(aTHX);
1881             /* mark end of profile data for last_pid pid
1882             * which is the pid that this file relates to
1883             */
1884 675           NYTP_write_process_end(out, last_pid, timeofday);
1885              
1886 675 50         if ((result = NYTP_close(out, 0)))
1887 0           logwarn("Error closing profile data file: %s\n", strerror(result));
1888 675           out = NULL;
1889              
1890 675 50         if (trace_level >= 1)
1891 0           logwarn("~ closed file at %.6" NVff "\n", timeofday);
1892             }
1893              
1894              
1895             static int
1896 865192           reinit_if_forked(pTHX)
1897             {
1898             int open_new_file;
1899              
1900 865192 100         if (getpid() == last_pid)
1901 865161           return 0; /* not forked */
1902              
1903             /* we're now the child process */
1904 31 50         if (trace_level >= 1)
1905 0           logwarn("~ new pid %d (was %d) forkdepth %" IVdf "\n", getpid(), last_pid, profile_forkdepth);
1906              
1907             /* reset state */
1908 31           last_pid = getpid();
1909 31           last_executed_fileptr = NULL;
1910 31           last_executed_fid = 0; /* don't count the fork in the child */
1911 31 50         if (sub_callers_hv)
1912 31           hv_clear(sub_callers_hv);
1913              
1914 31           open_new_file = (out) ? 1 : 0;
1915 31 100         if (open_new_file) {
1916             /* data that was unflushed in the parent when it forked
1917             * is now duplicated unflushed in this child,
1918             * so discard it when we close the inherited filehandle.
1919             */
1920 30           int result = NYTP_close(out, 1);
1921 30 50         if (result)
1922 0           logwarn("Error closing profile data file: %s\n", strerror(result));
1923 30           out = NULL;
1924             /* if we fork while profiling then ensure we'll get a distinct filename */
1925 30           profile_opts |= NYTP_OPTf_ADDPID;
1926             }
1927              
1928 31 100         if (profile_forkdepth == 0) { /* parent doesn't want children profiled */
1929 4           disable_profile(aTHX);
1930 4           open_new_file = 0;
1931             }
1932             else /* count down another generation */
1933 27           --profile_forkdepth;
1934              
1935 31 100         if (open_new_file)
1936 27           open_output_file(aTHX_ PROF_output_file);
1937              
1938 31           return 1; /* have forked */
1939             }
1940              
1941              
1942             /******************************************
1943             * Sub caller and inclusive time tracking
1944             ******************************************/
1945              
1946             static AV *
1947 5586           new_sub_call_info_av(pTHX)
1948             {
1949 5586           AV *av = newAV();
1950 5586           av_store(av, NYTP_SCi_CALL_COUNT, newSVuv(1));
1951 5586           av_store(av, NYTP_SCi_INCL_RTIME, newSVnv(0.0));
1952 5586           av_store(av, NYTP_SCi_EXCL_RTIME, newSVnv(0.0));
1953 5586           av_store(av, NYTP_SCi_INCL_TICKS, newSVnv(0.0));
1954 5586           av_store(av, NYTP_SCi_EXCL_TICKS, newSVnv(0.0));
1955             /* others allocated when needed */
1956 5586           return av;
1957             }
1958              
1959             /* subroutine profiler subroutine entry structure. Represents a call
1960             * from one sub to another (the arc between the nodes, if you like)
1961             */
1962             typedef struct subr_entry_st subr_entry_t;
1963             struct subr_entry_st {
1964             unsigned int already_counted;
1965             U32 subr_prof_depth;
1966             long unsigned subr_call_seqn;
1967             SSize_t prev_subr_entry_ix; /* ix to callers subr_entry */
1968              
1969             time_of_day_t initial_call_timeofday;
1970             struct tms initial_call_cputimes;
1971             NV initial_overhead_ticks;
1972             NV initial_subr_ticks;
1973              
1974             unsigned int caller_fid;
1975             int caller_line;
1976             const char *caller_subpkg_pv;
1977             SV *caller_subnam_sv;
1978              
1979             CV *called_cv;
1980             int called_cv_depth;
1981             const char *called_is_xs; /* NULL, "xsub", or "syop" */
1982             const char *called_subpkg_pv;
1983             SV *called_subnam_sv;
1984             /* ensure all items are initialized in first phase of pp_subcall_profiler */
1985             int hide_subr_call_time; /* eg for CORE:accept */
1986             };
1987              
1988             /* save stack index to the current subroutine entry structure */
1989             static SSize_t subr_entry_ix = -1;
1990              
1991             #define subr_entry_ix_ptr(ix) ((ix != -1) ? SSPTR(ix, subr_entry_t *) : NULL)
1992              
1993              
1994             static void
1995 530           append_linenum_to_begin(pTHX_ subr_entry_t *subr_entry) {
1996 530           UV line = 0;
1997             SV *fullnamesv;
1998             SV *DBsv;
1999 530           char *subname = SvPVX(subr_entry->called_subnam_sv);
2000             STRLEN pkg_len;
2001             STRLEN total_len;
2002              
2003             /* If sub is a BEGIN then append the line number to our name
2004             * so multiple BEGINs (either explicit or implicit, e.g., "use")
2005             * in the same file/package can be distinguished.
2006             */
2007 530 50         if (!subname || *subname != 'B' || strNE(subname,"BEGIN"))
    50          
    100          
2008 32           return;
2009              
2010             /* get, and delete, the entry for this sub in the PL_DBsub hash */
2011 498           pkg_len = strlen(subr_entry->called_subpkg_pv);
2012 498           total_len = pkg_len + 2 /* :: */ + 5; /* BEGIN */
2013 498           fullnamesv = newSV(total_len + 1); /* +1 for '\0' */
2014 498           memcpy(SvPVX(fullnamesv), subr_entry->called_subpkg_pv, pkg_len);
2015 498           memcpy(SvPVX(fullnamesv) + pkg_len, "::BEGIN", 7 + 1); /* + 1 for '\0' */
2016 498 50         SvCUR_set(fullnamesv, total_len);
    0          
    50          
    0          
    0          
    50          
    0          
2017 498           SvPOK_on(fullnamesv);
2018 498           DBsv = hv_delete(GvHV(PL_DBsub), SvPVX(fullnamesv), (I32)total_len, 1);
2019              
2020 498 100         if (DBsv && parse_DBsub_value(aTHX_ DBsv, NULL, &line, NULL, SvPVX(fullnamesv))) {
    50          
2021 496           (void)SvREFCNT_inc(DBsv); /* was made mortal by hv_delete */
2022 496           sv_catpvf(fullnamesv, "@%u", (unsigned int)line);
2023 496 50         if (hv_fetch(GvHV(PL_DBsub), SvPV_nolen(fullnamesv), (I32)SvCUR(fullnamesv), 0)) {
    100          
2024             static unsigned int dup_begin_seqn;
2025 36           sv_catpvf(fullnamesv, ".%u", ++dup_begin_seqn);
2026             }
2027 496 50         (void) hv_store(GvHV(PL_DBsub), SvPV_nolen(fullnamesv), (I32)SvCUR(fullnamesv), DBsv, 0);
2028              
2029             /* As we know the length of fullnamesv *before* the concatenation, we
2030             can calculate the length and offset of the formatted addition, and
2031             hence directly string append it, rather than duplicating the call to
2032             a *printf function. */
2033 496           sv_catpvn(subr_entry->called_subnam_sv, SvPVX(fullnamesv) + total_len,
2034             SvCUR(fullnamesv) - total_len);
2035             }
2036 498           SvREFCNT_dec(fullnamesv);
2037             }
2038              
2039              
2040             static char *
2041 0           subr_entry_summary(pTHX_ subr_entry_t *subr_entry, int state)
2042             {
2043             static char buf[80]; /* XXX */
2044 0 0         sprintf(buf, "(seix %d%s%d, ac%u)",
2045 0           (int)subr_entry->prev_subr_entry_ix,
2046             (state) ? "<-" : "->",
2047             (int)subr_entry_ix,
2048             subr_entry->already_counted
2049             );
2050 0           return buf;
2051             }
2052              
2053              
2054             static void
2055 131055           subr_entry_destroy(pTHX_ subr_entry_t *subr_entry)
2056             {
2057 131055 50         if ((trace_level >= 6 || subr_entry->already_counted>1)
    50          
2058             /* ignore the typical second (fallback) destroy */
2059 0 0         && !(subr_entry->prev_subr_entry_ix == subr_entry_ix && subr_entry->already_counted==1)
    0          
2060             ) {
2061 0 0         logwarn("%2u << %s::%s done %s\n",
2062 0           (unsigned int)subr_entry->subr_prof_depth,
2063             subr_entry->called_subpkg_pv,
2064 0 0         (subr_entry->called_subnam_sv && SvOK(subr_entry->called_subnam_sv))
    0          
    0          
2065 0 0         ? SvPV_nolen(subr_entry->called_subnam_sv)
2066             : "?",
2067             subr_entry_summary(aTHX_ subr_entry, 1));
2068             }
2069 131055 100         if (subr_entry->caller_subnam_sv) {
2070 65570           sv_free(subr_entry->caller_subnam_sv);
2071 65570           subr_entry->caller_subnam_sv = Nullsv;
2072             }
2073 131055 100         if (subr_entry->called_subnam_sv) {
2074 65570           sv_free(subr_entry->called_subnam_sv);
2075 65570           subr_entry->called_subnam_sv = Nullsv;
2076             }
2077 131055 50         if (subr_entry->prev_subr_entry_ix <= subr_entry_ix)
2078 131055           subr_entry_ix = subr_entry->prev_subr_entry_ix;
2079             else
2080 0           logwarn("skipped attempt to raise subr_entry_ix from %d to %d\n",
2081 0           (int)subr_entry_ix, (int)subr_entry->prev_subr_entry_ix);
2082 131055           }
2083              
2084              
2085             static void
2086 131055           incr_sub_inclusive_time(pTHX_ subr_entry_t *subr_entry)
2087             {
2088 131055           int saved_errno = errno;
2089             char called_subname_pv[NYTP_MAX_SUB_NAME_LEN];
2090 131055           char *called_subname_pv_end = called_subname_pv;
2091             char subr_call_key[NYTP_MAX_SUB_NAME_LEN];
2092             int subr_call_key_len;
2093             NV overhead_ticks, called_sub_ticks;
2094             SV *incl_time_sv, *excl_time_sv;
2095             NV incl_subr_ticks, excl_subr_ticks;
2096             SV *sv_tmp;
2097             AV *subr_call_av;
2098             time_of_day_t sub_end_time;
2099             long ticks, overflow;
2100              
2101             /* an undef SV is a special marker used by subr_entry_setup */
2102 131055 100         if (subr_entry->called_subnam_sv && !SvOK(subr_entry->called_subnam_sv)) {
    100          
    50          
    50          
2103 4 50         if (trace_level)
2104 0           logwarn("Don't know name of called sub, assuming xsub/builtin exited via an exception (which isn't handled yet)\n");
2105 4           subr_entry->already_counted++;
2106             }
2107              
2108             /* For xsubs we get called both explicitly when the xsub returns, and by
2109             * the destructor. (That way if the xsub leaves via an exception then we'll
2110             * still get called, albeit a little later than we'd like.)
2111             */
2112 131055 100         if (subr_entry->already_counted) {
2113 65489           subr_entry_destroy(aTHX_ subr_entry);
2114 65489           return;
2115             }
2116 65566           subr_entry->already_counted++;
2117              
2118             /* statement overheads we've accumulated since we entered the sub */
2119 65566           overhead_ticks = cumulative_overhead_ticks - subr_entry->initial_overhead_ticks;
2120             /* ticks spent in subroutines called by this subroutine */
2121 65566           called_sub_ticks = cumulative_subr_ticks - subr_entry->initial_subr_ticks;
2122              
2123             /* calculate ticks since we entered the sub */
2124 65566           get_time_of_day(sub_end_time);
2125 65566           get_ticks_between(NV, subr_entry->initial_call_timeofday, sub_end_time, ticks, overflow);
2126              
2127 65566           incl_subr_ticks = (overflow*ticks_per_sec) + ticks;
2128             /* subtract statement measurement overheads */
2129 65566           incl_subr_ticks -= overhead_ticks;
2130              
2131 65566 50         if (subr_entry->hide_subr_call_time) {
2132             /* account for the time spent in the sub as if it was statement
2133             * profiler overhead. That has the effect of neatly subtracting
2134             * the time from all the sub calls up the call stack.
2135             */
2136 0           cumulative_overhead_ticks += incl_subr_ticks;
2137 0           incl_subr_ticks = 0;
2138 0           called_sub_ticks = 0;
2139             }
2140              
2141             /* exclusive = inclusive - time spent in subroutines called by this subroutine */
2142 65566           excl_subr_ticks = incl_subr_ticks - called_sub_ticks;
2143              
2144 65566 50         subr_call_key_len = my_snprintf(subr_call_key, sizeof(subr_call_key), "%s::%s[%u:%d]",
    50          
    50          
2145             subr_entry->caller_subpkg_pv,
2146             (subr_entry->caller_subnam_sv) ? SvPV_nolen(subr_entry->caller_subnam_sv) : "(null)",
2147             subr_entry->caller_fid, subr_entry->caller_line);
2148 65566 50         if (subr_call_key_len >= sizeof(subr_call_key))
2149 0           croak(nytp_panic_overflow_msg_fmt, "subr_call_key", subr_call_key);
2150              
2151             /* compose called_subname_pv as "${pkg}::${sub}" avoiding sprintf */
2152             STMT_START {
2153             STRLEN len;
2154             const char *p;
2155              
2156 65566           p = subr_entry->called_subpkg_pv;
2157 1127344 100         while (*p)
2158 1061778           *called_subname_pv_end++ = *p++;
2159 65566           *called_subname_pv_end++ = ':';
2160 65566           *called_subname_pv_end++ = ':';
2161 65566 50         if (subr_entry->called_subnam_sv) {
2162             /* We create this SV, so we know that it is well-formed, and has a
2163             trailing '\0' */
2164 65566 50         p = SvPV(subr_entry->called_subnam_sv, len);
2165             }
2166             else {
2167             /* C string constants have a trailing '\0'. */
2168 0           p = "(null)"; len = 6;
2169             }
2170 65566           memcpy(called_subname_pv_end, p, len + 1);
2171 65566           called_subname_pv_end += len;
2172 65566 50         if (called_subname_pv_end >= called_subname_pv+sizeof(called_subname_pv))
2173 0           croak(nytp_panic_overflow_msg_fmt, "called_subname_pv", called_subname_pv);
2174             } STMT_END;
2175              
2176             /* { called_subname => { "caller_subname[fid:line]" => [ count, incl_time, ... ] } } */
2177 65566           sv_tmp = *hv_fetch(sub_callers_hv, called_subname_pv, (I32)(called_subname_pv_end - called_subname_pv), 1);
2178              
2179 65566 100         if (!SvROK(sv_tmp)) { /* autoviv hash ref - is first call of this called subname from anywhere */
2180 3139           HV *hv = newHV();
2181 3139           sv_setsv(sv_tmp, newRV_noinc((SV *)hv));
2182              
2183 3139 100         if (subr_entry->called_is_xs) {
2184             /* create dummy item with fid=0 & line=0 to act as flag to indicate xs */
2185 733           AV *av = new_sub_call_info_av(aTHX);
2186 733           av_store(av, NYTP_SCi_CALL_COUNT, newSVuv(0));
2187 733           sv_setsv(*hv_fetch(hv, "[0:0]", 5, 1), newRV_noinc((SV *)av));
2188              
2189 733 100         if ( ('s' == *subr_entry->called_is_xs) /* "sop" (slowop) */
2190 127 50         || (subr_entry->called_cv && SvTYPE(subr_entry->called_cv) == SVt_PVCV)
    50          
2191             ) {
2192             /* We just use an empty string as the filename for xsubs
2193             * because CvFILE() isn't reliable on perl 5.8.[78]
2194             * and the name of the .c file isn't very useful anyway.
2195             * The reader can try to associate the xsubs with the
2196             * corresonding .pm file using the package part of the subname.
2197             */
2198 733           SV *sv = *hv_fetch(GvHV(PL_DBsub), called_subname_pv, (I32)(called_subname_pv_end - called_subname_pv), 1);
2199 733 100         if (!SvOK(sv))
    50          
    50          
2200 685           sv_setpvs(sv, ":0-0"); /* empty file name */
2201 733 50         if (trace_level >= 2)
2202 0           logwarn("Marking '%s' as %s\n", called_subname_pv, subr_entry->called_is_xs);
2203             }
2204             }
2205             }
2206              
2207             /* drill-down to array of sub call information for this subr_call_key */
2208 65566           sv_tmp = *hv_fetch((HV*)SvRV(sv_tmp), subr_call_key, subr_call_key_len, 1);
2209 65566 100         if (!SvROK(sv_tmp)) { /* first call from this subname[fid:line] - autoviv array ref */
2210 4853           subr_call_av = new_sub_call_info_av(aTHX);
2211              
2212 4853           sv_setsv(sv_tmp, newRV_noinc((SV *)subr_call_av));
2213              
2214 4853 50         if (subr_entry->called_subpkg_pv) { /* note that a sub in this package was called */
2215 4853           SV *pf_sv = *hv_fetch(pkg_fids_hv, subr_entry->called_subpkg_pv, (I32)strlen(subr_entry->called_subpkg_pv), 1);
2216 4853 100         if (SvTYPE(pf_sv) == SVt_NULL) { /* log when first created */
2217 813           sv_upgrade(pf_sv, SVt_PV);
2218 813 50         if (trace_level >= 3)
2219 4853           logwarn("Noting that subs in package '%s' were called\n",
2220             subr_entry->called_subpkg_pv);
2221             }
2222             }
2223             }
2224             else {
2225 60713           subr_call_av = (AV *)SvRV(sv_tmp);
2226 60713           sv_inc(AvARRAY(subr_call_av)[NYTP_SCi_CALL_COUNT]);
2227             }
2228              
2229 65566 50         if (trace_level >= 5) {
2230 0           logwarn("%2u <- %s %" NVgf " excl = %" NVgf "t incl - %" NVgf "t (%" NVgf "-%" NVgf "), oh %" NVff "-%" NVff "=%" NVff "t, d%d @%d:%d #%lu %p\n",
2231 0           (unsigned int)subr_entry->subr_prof_depth, called_subname_pv,
2232             excl_subr_ticks, incl_subr_ticks,
2233             called_sub_ticks,
2234             cumulative_subr_ticks, subr_entry->initial_subr_ticks,
2235             cumulative_overhead_ticks, subr_entry->initial_overhead_ticks, overhead_ticks,
2236             (int)subr_entry->called_cv_depth,
2237             subr_entry->caller_fid, subr_entry->caller_line,
2238             subr_entry->subr_call_seqn, (void*)subr_entry);
2239             }
2240              
2241             /* only count inclusive time for the outer-most calls */
2242 65566 100         if (subr_entry->called_cv_depth <= 1) {
2243 65534           incl_time_sv = *av_fetch(subr_call_av, NYTP_SCi_INCL_TICKS, 1);
2244 65534 50         sv_setnv(incl_time_sv, SvNV(incl_time_sv)+incl_subr_ticks);
2245             }
2246             else { /* recursing into an already entered sub */
2247             /* measure max depth and accumulate incl time separately */
2248 32           SV *reci_time_sv = *av_fetch(subr_call_av, NYTP_SCi_RECI_RTIME, 1);
2249 32           SV *max_depth_sv = *av_fetch(subr_call_av, NYTP_SCi_REC_DEPTH, 1);
2250 32 100         sv_setnv(reci_time_sv, (SvOK(reci_time_sv)) ? SvNV(reci_time_sv)+(incl_subr_ticks/ticks_per_sec) : (incl_subr_ticks/ticks_per_sec));
    50          
    50          
    50          
2251             /* we track recursion depth here, which is called_cv_depth-1 */
2252 32 100         if (!SvOK(max_depth_sv) || subr_entry->called_cv_depth-1 > SvIV(max_depth_sv))
    50          
    50          
    50          
    50          
2253 16           sv_setiv(max_depth_sv, subr_entry->called_cv_depth-1);
2254             }
2255 65566           excl_time_sv = *av_fetch(subr_call_av, NYTP_SCi_EXCL_TICKS, 1);
2256 65566 50         sv_setnv(excl_time_sv, SvNV(excl_time_sv)+excl_subr_ticks);
2257              
2258 65566 100         if (opt_calls && out) {
    100          
2259 60845           NYTP_write_call_return(out, subr_entry->subr_prof_depth, called_subname_pv, incl_subr_ticks, excl_subr_ticks);
2260             }
2261              
2262 65566           subr_entry_destroy(aTHX_ subr_entry);
2263              
2264 65566           cumulative_subr_ticks += excl_subr_ticks;
2265 65566           SETERRNO(saved_errno, 0);
2266             }
2267              
2268             static void /* wrapper called at scope exit due to save_destructor below */
2269 81805           incr_sub_inclusive_time_ix(pTHX_ void *subr_entry_ix_void)
2270             {
2271             /* recover the SSize_t ix that was stored as a void pointer */
2272 81805           SSize_t save_ix = (SSize_t)PTR2IV(subr_entry_ix_void);
2273 81805 50         incr_sub_inclusive_time(aTHX_ subr_entry_ix_ptr(save_ix));
2274 81805           }
2275              
2276              
2277             static CV *
2278 109386           resolve_sub_to_cv(pTHX_ SV *sv, GV **subname_gv_ptr)
2279             {
2280             GV *dummy_gv;
2281             HV *stash;
2282             CV *cv;
2283              
2284 109386 50         if (!subname_gv_ptr)
2285 0           subname_gv_ptr = &dummy_gv;
2286             else
2287 109386           *subname_gv_ptr = Nullgv;
2288              
2289             /* copied from top of perl's pp_entersub */
2290             /* modified to return either CV or else a GV */
2291             /* or a NULL in cases that pp_entersub would croak */
2292 109386           switch (SvTYPE(sv)) {
2293             default:
2294 1476 100         if (!SvROK(sv)) {
2295             char *sym;
2296              
2297 36 50         if (sv == &PL_sv_yes) { /* unfound import, ignore */
2298 0           return NULL;
2299             }
2300 36 50         if (SvGMAGICAL(sv)) {
2301 0           mg_get(sv);
2302 0 0         if (SvROK(sv))
2303 0           goto got_rv;
2304 0 0         sym = SvPOKp(sv) ? SvPVX(sv) : Nullch;
2305             }
2306             else
2307 36 100         sym = SvPV_nolen(sv);
2308 36 50         if (!sym)
2309 0           return NULL;
2310 36 100         if (PL_op->op_private & HINT_STRICT_REFS)
2311 4           return NULL;
2312 32           cv = get_cv(sym, TRUE);
2313 32           break;
2314             }
2315             got_rv:
2316             {
2317 1440           SV **sp = &sv; /* Used in tryAMAGICunDEREF macro. */
2318 1440           tryAMAGICunDEREF(to_cv);
2319             }
2320 1440           cv = (CV*)SvRV(sv);
2321 1440 50         if (SvTYPE(cv) == SVt_PVCV)
2322 1440           break;
2323             /* FALL THROUGH */
2324             case SVt_PVHV:
2325             case SVt_PVAV:
2326 0           return NULL;
2327             case SVt_PVCV:
2328 4517           cv = (CV*)sv;
2329 4517           break;
2330             case SVt_PVGV:
2331 103393 50         if (!(isGV_with_GP(sv) && (cv = GvCVu((GV*)sv))))
    50          
    0          
    50          
    100          
2332 16           cv = sv_2cv(sv, &stash, subname_gv_ptr, FALSE);
2333 103393 100         if (!cv) /* would autoload in this situation */
2334 16           return NULL;
2335 103377           break;
2336             }
2337 109366 50         if (cv && !*subname_gv_ptr && CvGV(cv) && isGV_with_GP(CvGV(cv))) {
    50          
    50          
    50          
    50          
    0          
2338 109366           *subname_gv_ptr = CvGV(cv);
2339             }
2340 109386           return cv;
2341             }
2342              
2343              
2344              
2345             static CV*
2346 2601           current_cv(pTHX_ I32 ix, PERL_SI *si)
2347             {
2348             /* returning the current cv */
2349             /* logic based on perl's S_deb_curcv in dump.c */
2350             /* see also http://metacpan.org/release/Devel-StackBlech/ */
2351             PERL_CONTEXT *cx;
2352 2601 100         if (!si)
2353 1795           si = PL_curstackinfo;
2354              
2355 2601 100         if (ix < 0) {
2356             /* caller isn't on the same stack so we'll walk the stacks as well */
2357 148 100         if (si->si_type != PERLSI_MAIN)
2358 48           return current_cv(aTHX_ si->si_prev->si_cxix, si->si_prev);
2359 100 50         if (trace_level >= 9)
2360 0           logwarn("finding current_cv(%d,%p) si_type %d - context stack empty\n",
2361 0           (int)ix, (void*)si, (int)si->si_type);
2362 100           return Nullcv; /* PL_main_cv ? */
2363             }
2364              
2365 2453           cx = &si->si_cxstack[ix];
2366              
2367 2453 50         if (trace_level >= 9)
2368 0           logwarn("finding current_cv(%d,%p) - cx_type %d %s, si_type %d\n",
2369 0           (int)ix, (void*)si, CxTYPE(cx), cx_block_type(cx), (int)si->si_type);
2370              
2371             /* the common case of finding the caller on the same stack */
2372 2453 100         if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT)
    50          
2373 8           return cx->blk_sub.cv;
2374 2445 100         else if (CxTYPE(cx) == CXt_EVAL && !CxTRYBLOCK(cx))
    100          
2375 369           return current_cv(aTHX_ ix - 1, si); /* recurse up stack */
2376 2076 100         else if (ix == 0 && si->si_type == PERLSI_MAIN)
    100          
2377 1687           return PL_main_cv;
2378 389 100         else if (ix > 0) /* more on this stack? */
2379 274           return current_cv(aTHX_ ix - 1, si); /* recurse up stack */
2380              
2381             /* caller isn't on the same stack so we'll walk the stacks as well */
2382 115 50         if (si->si_type != PERLSI_MAIN) {
2383 115           return current_cv(aTHX_ si->si_prev->si_cxix, si->si_prev);
2384             }
2385 0           return Nullcv;
2386             }
2387              
2388              
2389             static SSize_t
2390 65570           subr_entry_setup(pTHX_ COP *prev_cop, subr_entry_t *clone_subr_entry, OPCODE op_type, SV *subr_sv)
2391             {
2392 65570           int saved_errno = errno;
2393             subr_entry_t *subr_entry;
2394             SSize_t prev_subr_entry_ix;
2395             subr_entry_t *caller_subr_entry;
2396             const char *found_caller_by;
2397             char *file;
2398              
2399             /* allocate struct to save stack (very efficient) */
2400             /* XXX "warning: cast from pointer to integer of different size" with use64bitall=define */
2401 65570           prev_subr_entry_ix = subr_entry_ix;
2402 65570           subr_entry_ix = SSNEWa(sizeof(*subr_entry), MEM_ALIGNBYTES);
2403              
2404 65570 50         if (subr_entry_ix <= prev_subr_entry_ix) {
2405             /* one cause of this is running NYTProf with threads */
2406 0           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);
2407             /* limit the damage */
2408 0           disable_profile(aTHX);
2409 0           return prev_subr_entry_ix;
2410             }
2411              
2412 65570 50         subr_entry = subr_entry_ix_ptr(subr_entry_ix);
2413 65570           Zero(subr_entry, 1, subr_entry_t);
2414              
2415 65570           subr_entry->prev_subr_entry_ix = prev_subr_entry_ix;
2416 65570 100         caller_subr_entry = subr_entry_ix_ptr(prev_subr_entry_ix);
2417 65570           subr_entry->subr_prof_depth = (caller_subr_entry)
2418 65570 100         ? caller_subr_entry->subr_prof_depth+1 : 1;
2419              
2420 65570           get_time_of_day(subr_entry->initial_call_timeofday);
2421 65570           subr_entry->initial_overhead_ticks = cumulative_overhead_ticks;
2422 65570           subr_entry->initial_subr_ticks = cumulative_subr_ticks;
2423 65570           subr_entry->subr_call_seqn = (unsigned long)(++cumulative_subr_seqn);
2424              
2425             /* try to work out what sub's being called in advance
2426             * mainly for xsubs because otherwise they're transparent
2427             * because xsub calls don't get a new context
2428             */
2429 128407 100         if (op_type == OP_ENTERSUB || op_type == OP_GOTO) {
    100          
2430 62837           GV *called_gv = Nullgv;
2431 62837           subr_entry->called_cv = resolve_sub_to_cv(aTHX_ subr_sv, &called_gv);
2432 62837 100         if (called_gv) {
2433 62833 50         char *p = HvNAME(GvSTASH(called_gv));
    50          
    50          
    0          
    50          
    50          
2434 62833           subr_entry->called_subpkg_pv = p;
2435 62833           subr_entry->called_subnam_sv = newSVpv(GvNAME(called_gv), 0);
2436              
2437             /* detect calls to POSIX::_exit */
2438 62833 50         if ('P'==*p++ && 'O'==*p++ && 'S'==*p++ && 'I'==*p++ && 'X'==*p++ && 0==*p) {
    0          
    0          
    0          
    0          
    0          
2439 0           char *s = GvNAME(called_gv);
2440 0 0         if ('_'==*s++ && 'e'==*s++ && 'x'==*s++ && 'i'==*s++ && 't'==*s++ && 0==*s) {
    0          
    0          
    0          
    0          
    0          
2441 62833           finish_profile(aTHX);
2442             }
2443             }
2444             }
2445             else {
2446             /* resolve_sub_to_cv couldn't work out what's being called,
2447             * possibly because it's something that'll cause pp_entersub to croak
2448             * anyway. So we mark the subr_entry in a particular way and hope that
2449             * pp_subcall_profiler() can fill in the details.
2450             * If there is an exception then we'll wind up in incr_sub_inclusive_time
2451             * which will see this mark and ignore the call.
2452             */
2453 4           subr_entry->called_subnam_sv = newSV(0);
2454             }
2455 62837           subr_entry->called_is_xs = NULL; /* work it out later */
2456             }
2457             else { /* slowop */
2458              
2459             /* pretend slowops (builtins) are xsubs */
2460 2733           const char *slowop_name = PL_op_name[op_type];
2461 2733 50         if (profile_slowops == 1) { /* 1 == put slowops into 1 package */
2462 0           subr_entry->called_subpkg_pv = "CORE";
2463 0           subr_entry->called_subnam_sv = newSVpv(slowop_name, 0);
2464             }
2465             else { /* 2 == put slowops into multiple packages */
2466 2733           SV **opname = NULL;
2467             SV *sv;
2468 2733 100         if (!slowop_name_cache)
2469 362           slowop_name_cache = newAV();
2470 2733           opname = av_fetch(slowop_name_cache, op_type, TRUE);
2471 2733 50         if (!opname)
2472 0           croak("panic: opname cache read for '%s' (%d)\n", slowop_name, op_type);
2473 2733           sv = *opname;
2474              
2475 2733 100         if(!SvOK(sv)) {
    50          
    50          
2476 557           const STRLEN len = strlen(slowop_name);
2477 557           sv_grow(sv, 5 + len + 1);
2478 557           memcpy(SvPVX(sv), "CORE:", 5);
2479 557           memcpy(SvPVX(sv) + 5, slowop_name, len + 1);
2480 557 50         SvCUR_set(sv, 5 + len);
    0          
    50          
    0          
    0          
    50          
    0          
2481 557           SvPOK_on(sv);
2482             }
2483 2733           subr_entry->called_subnam_sv = SvREFCNT_inc(sv);
2484 2733 50         subr_entry->called_subpkg_pv = CopSTASHPV(PL_curcop);
    50          
    50          
    50          
    0          
    50          
    50          
2485             }
2486 2733           subr_entry->called_cv_depth = 1; /* an approximation for slowops */
2487 2733           subr_entry->called_is_xs = "sop";
2488             /* XXX make configurable eg for wait(), and maybe even subs like FCGI::Accept
2489             * so perhaps use $hide_sub_calls->{$package}{$subname} to make it general.
2490             * Then the logic would have to move out of this block.
2491             */
2492 2733 50         if (OP_ACCEPT == op_type)
2493 0           subr_entry->hide_subr_call_time = 1;
2494             }
2495              
2496             /* These refer to the last perl statement executed, so aren't
2497             * strictly correct where an opcode or xsub is making the call,
2498             * but they're still more useful than nothing.
2499             * In reports the references line shows calls made by the
2500             * opcode or xsub that's called at that line.
2501             */
2502 65570 50         file = OutCopFILE(prev_cop);
2503 131140           subr_entry->caller_fid = (file == last_executed_fileptr)
2504             ? last_executed_fid
2505 65570 100         : get_file_id(aTHX_ file, strlen(file), NYTP_FIDf_VIA_SUB);
2506 65570           subr_entry->caller_line = CopLINE(prev_cop);
2507              
2508             /* Gather details about the calling subroutine */
2509 65570 100         if (clone_subr_entry) {
2510 168           subr_entry->caller_subpkg_pv = clone_subr_entry->caller_subpkg_pv;
2511 168           subr_entry->caller_subnam_sv = SvREFCNT_inc(clone_subr_entry->caller_subnam_sv);
2512 168           found_caller_by = "(cloned)";
2513             }
2514             else
2515             /* Should we calculate the caller or can we reuse the caller_subr_entry?
2516             * Sometimes we'll have a caller_subr_entry but it won't have the name yet.
2517             * For example if the caller is an xsub that's callback into perl.
2518             */
2519 65402 50         if (profile_findcaller /* user wants us to calculate each time */
2520 65402 100         || !caller_subr_entry /* we don't have a caller struct */
2521 63607 50         || !caller_subr_entry->called_subpkg_pv /* we don't have caller details */
2522 63607 50         || !caller_subr_entry->called_subnam_sv
2523 63607 50         || !SvOK(caller_subr_entry->called_subnam_sv)
    0          
    0          
2524 1795           ) {
2525              
2526             /* get the current CV and determine the current sub name from that */
2527 1795           CV *caller_cv = current_cv(aTHX_ cxstack_ix, NULL);
2528 1795           subr_entry->caller_subnam_sv = newSV(0); /* XXX add cache/stack thing for these SVs */
2529              
2530             if (0) {
2531             logwarn(" .. caller_subr_entry %p(%s::%s) cxstack_ix=%d: caller_cv=%p\n",
2532             (void*)caller_subr_entry,
2533             caller_subr_entry ? caller_subr_entry->called_subpkg_pv : "(null)",
2534             (caller_subr_entry && caller_subr_entry->called_subnam_sv && SvOK(caller_subr_entry->called_subnam_sv))
2535             ? SvPV_nolen(caller_subr_entry->called_subnam_sv) : "(null)",
2536             (int)cxstack_ix, (void*)caller_cv
2537             );
2538             }
2539              
2540 1795 100         if (caller_cv == PL_main_cv) {
2541             /* PL_main_cv is run-time main (compile-time, eg 'use', is a main::BEGIN) */
2542             /* We don't record timing data for main::RUNTIME because timing data
2543             * is stored per calling location, and there is no calling location.
2544             * XXX Currently we don't output a subinfo for main::RUNTIME unless
2545             * some sub is called from main::RUNTIME. That may change.
2546             */
2547 1687           subr_entry->caller_subpkg_pv = "main";
2548 1687           sv_setpvs(subr_entry->caller_subnam_sv, "RUNTIME"); /* *cough* */
2549 1687           ++main_runtime_used;
2550             }
2551 108 100         else if (caller_cv == 0) {
2552             /* should never happen - but does in PostgreSQL 8.4.1 plperl
2553             * possibly because perl_run() has already returned
2554             */
2555 100           subr_entry->caller_subpkg_pv = "main";
2556 100           sv_setpvs(subr_entry->caller_subnam_sv, "NULL"); /* *cough* */
2557             }
2558             else {
2559 8           HV *stash_hv = NULL;
2560 8           GV *gv = CvGV(caller_cv);
2561 8           GV *egv = GvEGV(gv);
2562 8 50         if (!egv)
2563 0           gv = egv;
2564              
2565 8 50         if (gv && (stash_hv = GvSTASH(gv))) {
    50          
2566 8 50         subr_entry->caller_subpkg_pv = HvNAME(stash_hv);
    50          
    50          
    0          
    50          
    50          
2567 8           sv_setpvn(subr_entry->caller_subnam_sv,GvNAME(gv),GvNAMELEN(gv));
2568             }
2569             else {
2570 0 0         logwarn("Can't determine name of calling sub (GV %p, Stash %p, CV flags %d) at %s line %d\n",
2571 0           (void*)gv, (void*)stash_hv, (int)CvFLAGS(caller_cv),
2572 0           OutCopFILE(prev_cop), (int)CopLINE(prev_cop));
2573 0           sv_dump((SV*)caller_cv);
2574              
2575 0           subr_entry->caller_subpkg_pv = "__UNKNOWN__";
2576 0           sv_setpvs(subr_entry->caller_subnam_sv, "__UNKNOWN__");
2577             }
2578             }
2579 1795 50         found_caller_by = (profile_findcaller) ? "" : "(calculated)";
2580             }
2581             else {
2582 63607           subr_entry_t *caller_se = caller_subr_entry;
2583 63607 50         int caller_is_op = caller_se->called_is_xs && strEQ(caller_se->called_is_xs,"sop");
    0          
2584             /* if the caller is an op then use the caller of that op as our caller.
2585             * that makes more sense from the users perspective (and is consistent
2586             * with the findcaller=1 option).
2587             * XXX disabled for now because (I'm pretty sure) it needs a corresponding
2588             * change in incr_sub_inclusive_time otherwise the incl/excl times are distorted.
2589             */
2590             if (0 && caller_is_op) {
2591             subr_entry->caller_subpkg_pv = caller_se->caller_subpkg_pv;
2592             subr_entry->caller_subnam_sv = SvREFCNT_inc(caller_se->caller_subnam_sv);
2593             }
2594             else {
2595 63607           subr_entry->caller_subpkg_pv = caller_se->called_subpkg_pv;
2596 63607           subr_entry->caller_subnam_sv = SvREFCNT_inc(caller_se->called_subnam_sv);
2597             }
2598 63607           found_caller_by = "(inherited)";
2599             }
2600              
2601 65570 50         if (trace_level >= 4) {
2602 0 0         logwarn("%2u >> %s at %u:%d from %s::%s %s %s\n",
2603 0           (unsigned int)subr_entry->subr_prof_depth,
2604             PL_op_name[op_type],
2605             subr_entry->caller_fid, subr_entry->caller_line,
2606             subr_entry->caller_subpkg_pv,
2607 0           SvPV_nolen(subr_entry->caller_subnam_sv),
2608             found_caller_by,
2609             subr_entry_summary(aTHX_ subr_entry, 0)
2610             );
2611             }
2612              
2613             /* This is our safety-net destructor. For perl subs an identical destructor
2614             * will be pushed onto the stack _inside_ the scope we're interested in.
2615             * That destructor will be more accurate than this one. This one is here
2616             * mainly to catch exceptions thrown from xs subs and slowops.
2617             */
2618 65570           save_destructor_x(incr_sub_inclusive_time_ix, INT2PTR(void *, (IV)subr_entry_ix));
2619              
2620 65570 100         if (opt_calls >= 2 && out) {
    50          
2621 4583           NYTP_write_call_entry(out, subr_entry->caller_fid, subr_entry->caller_line);
2622             }
2623              
2624 65570           SETERRNO(saved_errno, 0);
2625              
2626 65570           return subr_entry_ix;
2627             }
2628              
2629              
2630             static OP *
2631 68858           pp_entersub_profiler(pTHX)
2632             {
2633 68858           return pp_subcall_profiler(aTHX_ 0);
2634             }
2635              
2636             static OP *
2637 7511           pp_slowop_profiler(pTHX)
2638             {
2639 7511           return pp_subcall_profiler(aTHX_ 1);
2640             }
2641              
2642             static OP *
2643 76369           pp_subcall_profiler(pTHX_ int is_slowop)
2644             {
2645 76369           int saved_errno = errno;
2646             OP *op;
2647 76369           COP *prev_cop = PL_curcop; /* not PL_curcop_nytprof here */
2648 76369           OP *next_op = PL_op->op_next; /* op to execute after sub returns */
2649             /* pp_entersub can be called with PL_op->op_type==0 */
2650 76369 100         OPCODE op_type = (is_slowop || (opcode) PL_op->op_type == OP_GOTO) ? (opcode) PL_op->op_type : OP_ENTERSUB;
    100          
2651              
2652             CV *called_cv;
2653 76369           dSP;
2654 76369           SV *sub_sv = *SP;
2655             SSize_t this_subr_entry_ix; /* local copy (needed for goto) */
2656              
2657             subr_entry_t *subr_entry;
2658              
2659             /* pre-conditions */
2660 76369 50         if (!profile_subs /* not profiling subs */
2661             /* don't profile if currently disabled */
2662 76369 100         || !is_profiling
2663             /* don't profile calls to non-existant import() methods */
2664             /* or our DB::_INIT as that makes tests perl version sensitive */
2665 66812 100         || (op_type==OP_ENTERSUB && (sub_sv == &PL_sv_yes || sub_sv == DB_CHECK_cv || sub_sv == DB_INIT_cv
    100          
    50          
    50          
2666 63857 100         || sub_sv == DB_END_cv || sub_sv == DB_fin_cv))
    100          
2667             /* don't profile other kinds of goto */
2668 65602 100         || (op_type==OP_GOTO &&
    100          
2669 168 50         ( !(SvROK(sub_sv) && SvTYPE(SvRV(sub_sv)) == SVt_PVCV)
2670 168 50         || subr_entry_ix == -1) /* goto out of sub whose entry wasn't profiled */
2671             )
2672             #ifdef MULTIPLICITY
2673             || (orig_my_perl && my_perl != orig_my_perl)
2674             #endif
2675             ) {
2676 10799           return run_original_op(op_type);
2677             }
2678              
2679 65570 100         if (!profile_stmts) {
2680 76           reinit_if_forked(aTHX);
2681             CHECK_SAWAMPERSAND(last_executed_fid, last_executed_line);
2682             }
2683              
2684 65570 50         if (trace_level >= 99) {
2685 0           logwarn("profiling a call [op %ld, %s, seix %d]\n",
2686             (long)op_type, PL_op_name[op_type], (int)subr_entry_ix);
2687             /* crude, but the only way to deal with the miriad logic at the
2688             * start of pp_entersub (which ought to be available as separate sub)
2689             */
2690 0           sv_dump(sub_sv);
2691             }
2692            
2693              
2694             /* Life would be so much simpler if we could reliably tell, at this point,
2695             * what sub was going to get called. But we can't in many cases.
2696             * So we gather up as much into as possible before the call.
2697             */
2698              
2699 65570 100         if (op_type != OP_GOTO) {
2700              
2701             /* For normal subs, pp_entersub enters the sub and returns the
2702             * first op *within* the sub (typically a nextstate/dbstate).
2703             * For XS subs, pp_entersub executes the entire sub
2704             * and returns the op *after* the sub (PL_op->op_next).
2705             * Other ops we profile (eg slowops) act like xsubs.
2706             */
2707              
2708 65402           called_cv = NULL;
2709 65402           this_subr_entry_ix = subr_entry_setup(aTHX_ prev_cop, NULL, op_type, sub_sv);
2710              
2711             /* This call may exit via an exception, in which case the
2712             * remaining code below doesn't get executed and the sub call
2713             * details are discarded. For perl subs that just means we don't
2714             * see calls the failed with "Unknown sub" errors, etc.
2715             * For xsubs it's a more significant issue. Especially if the
2716             * xsub calls back into perl.
2717             */
2718 65402           SETERRNO(saved_errno, 0);
2719 65402           op = run_original_op(op_type);
2720 65349           saved_errno = errno;
2721              
2722             }
2723             else {
2724              
2725             /* goto &sub opcode acts like a return followed by a call all in one.
2726             * When this op starts executing, the 'current' subr_entry that was
2727             * pushed onto the savestack by pp_subcall_profiler will be 'already_counted'
2728             * so the profiling of that call will be handled naturally for us.
2729             * So far so good.
2730             * Before it gets destroyed we'll take a copy of the subr_entry.
2731             * Then tell subr_entry_setup() to use our copy as a template so it'll
2732             * seem like the sub we goto'd was called by the same sub that called
2733             * the one that executed the goto. Except that we do use the fid:line
2734             * of the goto statement. That way the call graph makes sense and the
2735             * 'calling location' make sense. Got all that?
2736             */
2737             /* save a copy of prev_cop - see t/test18-goto2.p */
2738 168           COP prev_cop_copy = *prev_cop;
2739             /* save a copy of the subr_entry of the sub we're goto'ing out of */
2740             /* so we can reuse the caller _* info after it's destroyed */
2741             subr_entry_t goto_subr_entry;
2742 168 50         subr_entry_t *src = subr_entry_ix_ptr(subr_entry_ix);
2743 168           Copy(src, &goto_subr_entry, 1, subr_entry_t);
2744              
2745             /* XXX if the goto op or goto'd xsub croaks then this'll leak */
2746             /* we can't mortalize here because we're about to leave scope */
2747 168           (void)SvREFCNT_inc(goto_subr_entry.caller_subnam_sv);
2748 168           (void)SvREFCNT_inc(goto_subr_entry.called_subnam_sv);
2749 168           (void)SvREFCNT_inc(sub_sv);
2750              
2751             /* grab the CvSTART of the called sub since it's available */
2752 168           called_cv = (CV*)SvRV(sub_sv);
2753              
2754             /* if goto &sub then op will be the first op of the called sub
2755             * if goto &xsub then op will be the first op after the call to the
2756             * op we're goto'ing out of.
2757             */
2758 168           SETERRNO(saved_errno, 0);
2759 168           op = run_original_op(op_type); /* perform the goto &sub */
2760 168           saved_errno = errno;
2761              
2762             /* now we're in goto'd sub, mortalize the REFCNT_inc's done above */
2763 168           sv_2mortal(goto_subr_entry.caller_subnam_sv);
2764 168           sv_2mortal(goto_subr_entry.called_subnam_sv);
2765 168           this_subr_entry_ix = subr_entry_setup(aTHX_ &prev_cop_copy, &goto_subr_entry, op_type, sub_sv);
2766 168           SvREFCNT_dec(sub_sv);
2767             }
2768              
2769 65517 50         subr_entry = subr_entry_ix_ptr(this_subr_entry_ix);
2770              
2771             /* detect wierdness/corruption */
2772 65517 50         assert(subr_entry);
2773 65517 50         assert(subr_entry->caller_fid < fidhash.next_id);
2774              
2775             /* Check if this call has already been counted because the op performed
2776             * a leave_scope(). E.g., OP_SUBSTCONT at end of s/.../\1/
2777             * or Scope::Upper's unwind()
2778             */
2779 65517 100         if (subr_entry->already_counted) {
2780 32 50         if (trace_level >= 9)
2781 0 0         logwarn("%2u -- %s::%s already counted %s\n",
2782 0           (unsigned int)subr_entry->subr_prof_depth,
2783             subr_entry->called_subpkg_pv,
2784 0 0         (subr_entry->called_subnam_sv && SvOK(subr_entry->called_subnam_sv))
    0          
    0          
2785 0 0         ? SvPV_nolen(subr_entry->called_subnam_sv)
2786             : "?",
2787             subr_entry_summary(aTHX_ subr_entry, 1));
2788 32 50         assert(subr_entry->already_counted < 3);
2789 32           goto skip_sub_profile;
2790             }
2791              
2792 65485 100         if (is_slowop) {
2793             /* already fully handled by subr_entry_setup */
2794             }
2795             else {
2796 62800           char *stash_name = NULL;
2797 62800           const char *is_xs = NULL;
2798              
2799 62800 100         if (op_type == OP_GOTO) {
2800             /* use the called_cv that was the arg to the goto op */
2801 168 100         is_xs = (CvISXSUB(called_cv)) ? "xsub" : NULL;
2802             }
2803             else
2804 62632 100         if (op != next_op) { /* have entered a sub */
2805             /* use cv of sub we've just entered to get name */
2806 16083           called_cv = cxstack[cxstack_ix].blk_sub.cv;
2807 16083           is_xs = NULL;
2808             }
2809             else { /* have returned from XS so use sub_sv for name */
2810             /* determine the original fully qualified name for sub */
2811             /* CV or NULL */
2812 46549           GV *gv = NULL;
2813 46549           called_cv = resolve_sub_to_cv(aTHX_ sub_sv, &gv);
2814            
2815 46549 50         if (!called_cv && gv) { /* XXX no test case for this */
    0          
2816 0 0         stash_name = HvNAME(GvSTASH(gv));
    0          
    0          
    0          
    0          
    0          
2817 0           sv_setpv(subr_entry->called_subnam_sv, GvNAME(gv));
2818 0 0         if (trace_level >= 0)
2819 0 0         logwarn("Assuming called sub is named %s::%s at %s line %d (please report as a bug)\n",
    0          
2820 0           stash_name, SvPV_nolen(subr_entry->called_subnam_sv),
2821 0           OutCopFILE(prev_cop), (int)CopLINE(prev_cop));
2822             }
2823 46549           is_xs = "xsub";
2824             }
2825              
2826 62800 50         if (called_cv && CvGV(called_cv)) {
    50          
2827 62800           GV *gv = CvGV(called_cv);
2828             /* Class::MOP can create CvGV where SvTYPE of GV is SVt_NULL */
2829 62800 50         if (SvTYPE(gv) == SVt_PVGV && GvSTASH(gv)) {
    50          
2830             /* for a plain call of an imported sub the GV is of the current
2831             * package, so we dig to find the original package
2832             */
2833 62800 50         stash_name = HvNAME(GvSTASH(gv));
    50          
    50          
    0          
    50          
    50          
2834 62800           sv_setpv(subr_entry->called_subnam_sv, GvNAME(gv));
2835             }
2836 0 0         else if (trace_level >= 1) {
2837 0 0         logwarn("NYTProf is confused about CV %p called as %s at %s line %d (please report as a bug)\n",
    0          
2838 0           (void*)called_cv, SvPV_nolen(sub_sv), OutCopFILE(prev_cop), (int)CopLINE(prev_cop));
2839             /* looks like Class::MOP doesn't give the CV GV stash a name */
2840 0 0         if (trace_level >= 2) {
2841 0           sv_dump((SV*)called_cv); /* coredumps in Perl_do_gvgv_dump, looks line GvXPVGV is false, presumably on a Class::MOP wierdo sub */
2842 0           sv_dump((SV*)gv);
2843             }
2844             }
2845             }
2846              
2847             /* called_subnam_sv should have been set by now - else we're getting desperate */
2848 62800 50         if (!SvOK(subr_entry->called_subnam_sv)) {
    0          
    0          
2849 0 0         const char *what = (is_xs) ? is_xs : "sub";
2850              
2851 0 0         if (!called_cv) { /* should never get here as pp_entersub would have croaked */
2852 0 0         logwarn("unknown entersub %s '%s' (please report this as a bug)\n", what, SvPV_nolen(sub_sv));
2853 0 0         stash_name = CopSTASHPV(PL_curcop);
    0          
    0          
    0          
    0          
    0          
    0          
2854 0 0         sv_setpvf(subr_entry->called_subnam_sv, "__UNKNOWN__[%s,%s])", what, SvPV_nolen(sub_sv));
2855             }
2856             else { /* unnamed CV, e.g. seen in mod_perl/Class::MOP. XXX do better? */
2857 0 0         stash_name = HvNAME(CvSTASH(called_cv));
    0          
    0          
    0          
    0          
    0          
2858 0           sv_setpvf(subr_entry->called_subnam_sv, "__UNKNOWN__[%s,0x%p]", what, (void*)called_cv);
2859 0 0         if (trace_level)
2860 0 0         logwarn("unknown entersub %s assumed to be anon called_cv '%s'\n",
2861 0           what, SvPV_nolen(sub_sv));
2862             }
2863 0 0         if (trace_level >= 9)
2864 0           sv_dump(sub_sv);
2865             }
2866            
2867 62800           subr_entry->called_subpkg_pv = stash_name;
2868 62800 100         if (*SvPVX(subr_entry->called_subnam_sv) == 'B')
2869 530           append_linenum_to_begin(aTHX_ subr_entry);
2870              
2871             /* if called was xsub then we've already left it, so use depth+1 */
2872 62800 50         subr_entry->called_cv_depth = (called_cv) ? CvDEPTH(called_cv)+(is_xs?1:0) : 0;
2873 62800           subr_entry->called_cv = called_cv;
2874 62800           subr_entry->called_is_xs = is_xs;
2875             }
2876              
2877             /* ignore our own DB::_INIT sub - only shows up with 5.8.9+ & 5.10.1+ */
2878 65485 100         if (subr_entry->called_is_xs
2879 49250 100         && subr_entry->called_subpkg_pv[0] == 'D'
2880 46260 100         && subr_entry->called_subpkg_pv[1] == 'B'
2881 96 50         && subr_entry->called_subpkg_pv[2] == '\0'
2882             ) {
2883             STRLEN len;
2884 96 50         char *p = SvPV(subr_entry->called_subnam_sv, len);
2885              
2886 96 50         if(*p == '_' && (memEQs(p, len, "_CHECK") || memEQs(p, len, "_INIT") || memEQs(p, len, "_END"))) {
    0          
    0          
    0          
    0          
    0          
    0          
2887 0           subr_entry->already_counted++;
2888 96           goto skip_sub_profile;
2889             }
2890             }
2891             /* catch profile_subs being turned off by disable_profile call */
2892 65485 50         if (!profile_subs)
2893 0           subr_entry->already_counted++;
2894              
2895 65485 50         if (trace_level >= 4) {
2896 0 0         logwarn("%2u ->%4s %s::%s from %s::%s @%u:%u (d%d, oh %" NVff "t, sub %" NVff "s) #%lu\n",
    0          
    0          
2897 0           (unsigned int)subr_entry->subr_prof_depth,
2898 0           (subr_entry->called_is_xs) ? subr_entry->called_is_xs : "sub",
2899             subr_entry->called_subpkg_pv,
2900 0 0         subr_entry->called_subnam_sv ? SvPV_nolen(subr_entry->called_subnam_sv) : "(null)",
2901             subr_entry->caller_subpkg_pv,
2902 0 0         subr_entry->caller_subnam_sv ? SvPV_nolen(subr_entry->caller_subnam_sv) : "(null)",
2903             subr_entry->caller_fid, subr_entry->caller_line,
2904             subr_entry->called_cv_depth,
2905             subr_entry->initial_overhead_ticks,
2906 0           subr_entry->initial_subr_ticks / ticks_per_sec,
2907             subr_entry->subr_call_seqn
2908             );
2909             }
2910              
2911 65485 100         if (subr_entry->called_is_xs) {
2912             /* for xsubs/builtins we've already left the sub, so end the timing now
2913             * rather than wait for the calling scope to get cleaned up.
2914             */
2915 49250           incr_sub_inclusive_time(aTHX_ subr_entry);
2916             }
2917             else {
2918             /* push a destructor hook onto the context stack to ensure we account
2919             * for time in the sub when we leave it, even if via an exception.
2920             */
2921 16235           save_destructor_x(incr_sub_inclusive_time_ix, INT2PTR(void *, (IV)this_subr_entry_ix));
2922             }
2923              
2924             skip_sub_profile:
2925 65517           SETERRNO(saved_errno, 0);
2926              
2927 65517           return op;
2928             }
2929              
2930              
2931             static OP *
2932 364702           pp_stmt_profiler(pTHX) /* handles OP_DBSTATE, OP_SETSTATE, etc */
2933             {
2934 364702           OP *op = run_original_op(PL_op->op_type);
2935 364702           DB_stmt(aTHX_ NULL, op);
2936 364702           return op;
2937             }
2938              
2939             static OP *
2940 251230           pp_leave_profiler(pTHX) /* handles OP_LEAVESUB, OP_LEAVEEVAL, etc */
2941             {
2942 251230           OP *prev_op = PL_op;
2943 251230           OP *op = run_original_op(PL_op->op_type);
2944 251230           DB_leave(aTHX_ op, prev_op);
2945 251230           return op;
2946             }
2947              
2948             static OP *
2949 57           pp_fork_profiler(pTHX) /* handles OP_FORK */
2950             {
2951 57           OP *op = run_original_op(PL_op->op_type);
2952 57           reinit_if_forked(aTHX);
2953 57           return op;
2954             }
2955              
2956             static OP *
2957 24           pp_exit_profiler(pTHX) /* handles OP_EXIT, OP_EXEC, etc */
2958             {
2959 24           DB_leave(aTHX_ NULL, PL_op); /* call DB_leave *before* run_original_op() */
2960 24 50         if (PL_op->op_type == OP_EXEC)
2961 0           finish_profile(aTHX); /* this is the last chance we'll get */
2962 24           return run_original_op(PL_op->op_type);
2963             }
2964              
2965              
2966             static int
2967 694           enable_profile(pTHX_ char *file)
2968             {
2969             /* enable the run-time aspects to profiling */
2970 694           int prev_is_profiling = is_profiling;
2971             #ifdef MULTIPLICITY
2972             if (orig_my_perl && my_perl != orig_my_perl) {
2973             if (trace_level)
2974             logwarn("~ enable_profile call from different interpreter ignored\n");
2975             return 0;
2976             }
2977             #endif
2978              
2979 694 50         if (profile_usecputime) {
2980 0           warn("The NYTProf usecputime option has been removed (try using clock=N if possible)");
2981 0           return 0;
2982             }
2983              
2984 694 50         if (trace_level)
2985 0 0         logwarn("~ enable_profile (previously %s) to %s\n",
    0          
2986             prev_is_profiling ? "enabled" : "disabled",
2987 0 0         (file && *file) ? file : PROF_output_file);
2988              
2989 694           reinit_if_forked(aTHX);
2990              
2991 694 100         if (file && *file && strNE(file, PROF_output_file)) {
    50          
    50          
2992             /* caller wants output to go to a new file */
2993 32           close_output_file(aTHX);
2994 32           strncpy(PROF_output_file, file, sizeof(PROF_output_file)-1);
2995             }
2996              
2997 694 100         if (!out) {
2998 678           open_output_file(aTHX_ PROF_output_file);
2999             }
3000              
3001 694           last_executed_fileptr = NULL; /* discard cached OutCopFILE */
3002 694           is_profiling = 1; /* enable NYTProf profilers */
3003 694 100         if (opt_use_db_sub) /* set PL_DBsingle if required */
3004 338           sv_setiv(PL_DBsingle, 1);
3005              
3006             /* discard time spent since profiler was disabled */
3007 694           get_time_of_day(start_time);
3008              
3009 694           return prev_is_profiling;
3010             }
3011              
3012              
3013             static int
3014 731           disable_profile(pTHX)
3015             {
3016 731           int prev_is_profiling = is_profiling;
3017             #ifdef MULTIPLICITY
3018             if (orig_my_perl && my_perl != orig_my_perl) {
3019             if (trace_level)
3020             logwarn("~ disable_profile call from different interpreter ignored\n");
3021             return 0;
3022             }
3023             #endif
3024 731 100         if (is_profiling) {
3025 694 100         if (opt_use_db_sub)
3026 338           sv_setiv(PL_DBsingle, 0);
3027 694 100         if (out)
3028 691           NYTP_flush(out);
3029 694           is_profiling = 0;
3030             }
3031 731 50         if (trace_level)
3032 0 0         logwarn("~ disable_profile (previously %s, pid %d, trace %" IVdf ")\n",
3033             prev_is_profiling ? "enabled" : "disabled", getpid(), trace_level);
3034 731           return prev_is_profiling;
3035             }
3036              
3037              
3038             static void
3039 679           finish_profile(pTHX)
3040             {
3041             /* can be called after the perl interp is destroyed, via libcexit */
3042 679           int saved_errno = errno;
3043             #ifdef MULTIPLICITY
3044             if (orig_my_perl && my_perl != orig_my_perl)
3045             if (trace_level) {
3046             logwarn("~ finish_profile call from different interpreter ignored\n");
3047             return;
3048             }
3049             #endif
3050              
3051 679 50         if (trace_level >= 1)
3052 0           logwarn("~ finish_profile (overhead %" NVgf "t, is_profiling %d)\n",
3053             cumulative_overhead_ticks, is_profiling);
3054              
3055             /* write data for final statement, unless DB_leave has already */
3056 679 100         if (!profile_leave || opt_use_db_sub)
    100          
3057 499           DB_stmt(aTHX_ NULL, NULL);
3058              
3059 679           disable_profile(aTHX);
3060              
3061 679           close_output_file(aTHX);
3062              
3063 679 50         if (trace_level >= 2) {
3064 0           hash_stats(&fidhash, 0);
3065 0           hash_stats(&strhash, 0);
3066             }
3067              
3068             /* reset sub profiler data */
3069 679 50         if (HvKEYS(sub_callers_hv)) {
    100          
3070             /* HvKEYS check avoids hv_clear() if interp has been destroyed RT#86548 */
3071 613           hv_clear(sub_callers_hv);
3072             }
3073              
3074             /* reset other state */
3075 679           cumulative_overhead_ticks = 0;
3076 679           cumulative_subr_ticks = 0;
3077              
3078 679           SETERRNO(saved_errno, 0);
3079 679           }
3080              
3081              
3082             static void
3083 0           finish_profile_nocontext()
3084             {
3085             /* can be called after the perl interp is destroyed, via libcexit */
3086             dTHX;
3087 0           finish_profile(aTHX);
3088 0           }
3089              
3090              
3091             static void
3092 630           _init_profiler_clock(pTHX)
3093             {
3094             #ifdef HAS_CLOCK_GETTIME
3095 630 50         if (profile_clock == -1) { /* auto select */
3096             # ifdef CLOCK_MONOTONIC
3097 630           profile_clock = CLOCK_MONOTONIC;
3098             # else
3099             profile_clock = CLOCK_REALTIME;
3100             # endif
3101             }
3102             /* downgrade to CLOCK_REALTIME if desired clock not available */
3103 630 50         if (clock_gettime(profile_clock, &start_time) != 0) {
3104 0 0         if (trace_level)
3105 0           logwarn("~ clock_gettime clock %ld not available (%s) using CLOCK_REALTIME instead\n",
3106 0           (long)profile_clock, strerror(errno));
3107 0           profile_clock = CLOCK_REALTIME;
3108             /* check CLOCK_REALTIME as well, just in case */
3109 0 0         if (clock_gettime(profile_clock, &start_time) != 0)
3110 0           croak("clock_gettime CLOCK_REALTIME not available (%s), aborting",
3111 0           strerror(errno));
3112             }
3113             #else
3114             if (profile_clock != -1) { /* user tried to select different clock */
3115             logwarn("clock %ld not available (clock_gettime not supported on this system)\n", (long)profile_clock);
3116             profile_clock = -1;
3117             }
3118             #endif
3119             #ifdef HAS_QPC
3120             {
3121             const char * fnname;
3122             if(!QueryPerformanceFrequency((LARGE_INTEGER *)&time_frequency)) {
3123             fnname = "QueryPerformanceFrequency";
3124             goto win32_failed;
3125             }
3126             {
3127             LARGE_INTEGER tmp; /* do 1 test call, dont check return value for
3128             further calls for performance reasons */
3129             if(!QueryPerformanceCounter(&tmp)) {
3130             fnname = "QueryPerformanceCounter";
3131             win32_failed:
3132             croak("%s failed with Win32 error %lu, no clocks available", fnname, GetLastError());
3133             }
3134             }
3135             }
3136             #endif
3137 630           ticks_per_sec = TICKS_PER_SEC;
3138 630           }
3139              
3140              
3141             /* Initial setup - should only be called once */
3142              
3143             static int
3144 630           init_profiler(pTHX)
3145             {
3146             #ifndef HAS_GETTIMEOFDAY
3147             SV **svp;
3148             #endif
3149              
3150             #ifdef MULTIPLICITY
3151             if (!orig_my_perl) {
3152             if (1)
3153             orig_my_perl = my_perl;
3154             }
3155             else if (orig_my_perl && orig_my_perl != my_perl) {
3156             logwarn("NYTProf: perl interpreter address changed after init (threads/multiplicity not supported)\n");
3157             return 0;
3158             }
3159             #endif
3160              
3161             /* Save the process id early. We monitor it to detect forks */
3162 630           last_pid = getpid();
3163 630           DB_CHECK_cv = (SV*)GvCV(gv_fetchpv("DB::_CHECK", FALSE, SVt_PVCV));
3164 630           DB_INIT_cv = (SV*)GvCV(gv_fetchpv("DB::_INIT", FALSE, SVt_PVCV));
3165 630           DB_END_cv = (SV*)GvCV(gv_fetchpv("DB::_END", FALSE, SVt_PVCV));
3166 630           DB_fin_cv = (SV*)GvCV(gv_fetchpv("DB::finish_profile", FALSE, SVt_PVCV));
3167              
3168 630 100         if (opt_use_db_sub) {
3169 306           PL_perldb |= PERLDBf_LINE; /* line-by-line profiling via DB::DB (if $DB::single true) */
3170 306           PL_perldb |= PERLDBf_SINGLE; /* start (after BEGINs) with single-step on XXX still needed? */
3171             }
3172              
3173 630 50         if (profile_opts & NYTP_OPTf_OPTIMIZE)
3174 630           PL_perldb &= ~PERLDBf_NOOPT;
3175 0           else PL_perldb |= PERLDBf_NOOPT;
3176              
3177 630 100         if (profile_opts & NYTP_OPTf_SAVESRC) {
3178             /* ask perl to keep the source lines so we can copy them */
3179 322           PL_perldb |= PERLDBf_SAVESRC | PERLDBf_SAVESRC_NOSUBS;
3180             }
3181              
3182 630 50         if (!opt_nameevals)
3183 0           PL_perldb &= PERLDBf_NAMEEVAL;
3184 630 50         if (!opt_nameanonsubs)
3185 0           PL_perldb &= PERLDBf_NAMEANON;
3186              
3187 630 50         if (opt_perldb) /* force a PL_perldb value - for testing only, not documented */
3188 0           PL_perldb = opt_perldb;
3189              
3190 630           _init_profiler_clock(aTHX);
3191              
3192 630 50         if (trace_level)
3193 0           logwarn("~ init_profiler for pid %d, clock %ld, tps %d, start %d, perldb 0x%lx, exitf 0x%lx\n",
3194 0           last_pid, (long)profile_clock, ticks_per_sec, profile_start,
3195             (long unsigned)PL_perldb, (long unsigned)PL_exit_flags);
3196              
3197 630 50         if (get_hv("DB::sub", 0) == NULL) {
3198 0           logwarn("NYTProf internal error - perl not in debug mode\n");
3199 0           return 0;
3200             }
3201              
3202             #ifdef WANT_TIME_HIRES
3203             require_pv("Time/HiRes.pm"); /* before opcode redirection */
3204             svp = hv_fetch(PL_modglobal, "Time::U2time", 12, 0);
3205             if (!svp || !SvIOK(*svp)) croak("Time::HiRes is required");
3206             time_hires_u2time_hook = INT2PTR(int(*)(pTHX_ UV*), SvIV(*svp));
3207             if (trace_level || !time_hires_u2time_hook)
3208             logwarn("NYTProf using Time::HiRes %p\n", time_hires_u2time_hook);
3209             #endif
3210              
3211             /* create file id mapping hash */
3212 630           fidhash.table = (Hash_entry**)safemalloc(sizeof(Hash_entry*) * fidhash.size);
3213 630           memset(fidhash.table, 0, sizeof(Hash_entry*) * fidhash.size);
3214              
3215             /* redirect opcodes for statement profiling */
3216 630           Newxc(PL_ppaddr_orig, OP_max, void *, orig_ppaddr_t);
3217 630           Copy(PL_ppaddr, PL_ppaddr_orig, OP_max, void *);
3218 630 100         if (profile_stmts && !opt_use_db_sub) {
    100          
3219 314           PL_ppaddr[OP_NEXTSTATE] = pp_stmt_profiler;
3220 314           PL_ppaddr[OP_DBSTATE] = pp_stmt_profiler;
3221             #ifdef OP_SETSTATE
3222 314           PL_ppaddr[OP_SETSTATE] = pp_stmt_profiler;
3223             #endif
3224 314 100         if (profile_leave) {
3225 166           PL_ppaddr[OP_LEAVESUB] = pp_leave_profiler;
3226 166           PL_ppaddr[OP_LEAVESUBLV] = pp_leave_profiler;
3227 166           PL_ppaddr[OP_LEAVE] = pp_leave_profiler;
3228 166           PL_ppaddr[OP_LEAVELOOP] = pp_leave_profiler;
3229 166           PL_ppaddr[OP_LEAVEWRITE] = pp_leave_profiler;
3230 166           PL_ppaddr[OP_LEAVEEVAL] = pp_leave_profiler;
3231 166           PL_ppaddr[OP_LEAVETRY] = pp_leave_profiler;
3232 166           PL_ppaddr[OP_RETURN] = pp_leave_profiler;
3233             /* natural end of simple loop */
3234 166           PL_ppaddr[OP_UNSTACK] = pp_leave_profiler;
3235             /* OP_NEXT is missing because that jumps to OP_UNSTACK */
3236             /* OP_EXIT and OP_EXEC need special handling */
3237 166           PL_ppaddr[OP_EXIT] = pp_exit_profiler;
3238 166           PL_ppaddr[OP_EXEC] = pp_exit_profiler;
3239             }
3240             }
3241             /* calls reinit_if_forked() asap after a fork */
3242 630           PL_ppaddr[OP_FORK] = pp_fork_profiler;
3243              
3244 630 100         if (profile_slowops) {
3245             /* XXX this should turn into a loop over an array that maps
3246             * opcodes to the subname we'll use: OP_PRTF => "printf"
3247             */
3248             #include "slowops.h"
3249             }
3250              
3251             /* redirect opcodes for caller tracking */
3252 630 50         if (!sub_callers_hv)
3253 630           sub_callers_hv = newHV();
3254 630 50         if (!pkg_fids_hv)
3255 630           pkg_fids_hv = newHV();
3256 630           PL_ppaddr[OP_ENTERSUB] = pp_entersub_profiler;
3257 630           PL_ppaddr[OP_GOTO] = pp_entersub_profiler;
3258              
3259 630 100         if (!PL_checkav) PL_checkav = newAV();
3260 630 100         if (!PL_initav) PL_initav = newAV();
3261 630 100         if (!PL_endav) PL_endav = newAV();
3262             /* pre-extend PL_endav to reduce the chance of DB::_END realloc'ing
3263             * it while END blocks are executed (which could upset some embedded
3264             * applications that don't handle PL_endav carefully, like mod_perl)
3265             */
3266 630           av_extend(PL_endav, av_len(PL_endav)+30);
3267              
3268 630 100         if (profile_start == NYTP_START_BEGIN) {
3269 93           enable_profile(aTHX_ NULL);
3270             } else {
3271             /* handled by _INIT */
3272 537           av_push(PL_initav, SvREFCNT_inc(get_cv("DB::_INIT", GV_ADDWARN)));
3273             }
3274 630 50         if (PL_minus_c) {
3275 0           av_push(PL_checkav, SvREFCNT_inc(get_cv("DB::_CHECK", GV_ADDWARN)));
3276             } else {
3277 630           av_push(PL_endav, SvREFCNT_inc(get_cv("DB::_END", GV_ADDWARN)));
3278             }
3279              
3280             /* seed first run time */
3281 630           get_time_of_day(start_time);
3282              
3283 630 50         if (trace_level >= 1)
3284 0           logwarn("~ init_profiler done\n");
3285              
3286 630           return 1;
3287             }
3288              
3289              
3290             /************************************
3291             * Devel::NYTProf::Reader Functions *
3292             ************************************/
3293              
3294             static void
3295 4036584           add_entry(pTHX_ AV *dest_av, unsigned int file_num, unsigned int line_num,
3296             NV time, unsigned int eval_file_num, unsigned int eval_line_num, int count)
3297             {
3298             /* get ref to array of per-line data */
3299 4036584 50         unsigned int fid = (eval_line_num) ? eval_file_num : file_num;
3300 4036584           SV *line_time_rvav = *av_fetch(dest_av, fid, 1);
3301              
3302 4036584 100         if (!SvROK(line_time_rvav)) /* autoviv */
3303 6762           sv_setsv(line_time_rvav, newRV_noinc((SV*)newAV()));
3304              
3305 4036584           store_profile_line_entry(aTHX_ line_time_rvav, line_num, time, count, fid);
3306 4036584           }
3307              
3308              
3309             static AV *
3310 4036584           store_profile_line_entry(pTHX_ SV *rvav, unsigned int line_num, NV time,
3311             int count, unsigned int fid)
3312             {
3313 4036584           SV *time_rvav = *av_fetch((AV*)SvRV(rvav), line_num, 1);
3314             AV *line_av;
3315 4036584 100         if (!SvROK(time_rvav)) { /* autoviv */
3316 25706           line_av = newAV();
3317 25706           sv_setsv(time_rvav, newRV_noinc((SV*)line_av));
3318 25706           av_store(line_av, 0, newSVnv(time));
3319 25706           av_store(line_av, 1, newSViv(count));
3320             /* if eval then 2 is used for lines within the string eval */
3321 25706 50         if (embed_fid_line) { /* used to optimize reporting */
3322 0           av_store(line_av, 3, newSVuv(fid));
3323 25706           av_store(line_av, 4, newSVuv(line_num));
3324             }
3325             }
3326             else {
3327             SV *time_sv;
3328 4010878           line_av = (AV*)SvRV(time_rvav);
3329 4010878           time_sv = *av_fetch(line_av, 0, 1);
3330 4010878 50         sv_setnv(time_sv, time + SvNV(time_sv));
3331 4010878 100         if (count) {
3332 3033068           SV *sv = *av_fetch(line_av, 1, 1);
3333 3033068 50         (count == 1) ? sv_inc(sv) : sv_setiv(sv, (IV)time + SvIV(sv));
    0          
3334             }
3335             }
3336 4036584           return line_av;
3337             }
3338              
3339              
3340             /* Given a fully-qualified name, return the length of the package name.
3341             * As most callers get len via the hash API, they will have an I32, where
3342             * "negative" length signifies UTF-8. As we're only dealing with looking for
3343             * ASCII here, it doesn't matter to use which encoding sub_name is in, but it
3344             * reduces total code by doing the abs(len) in here.
3345             */
3346             static STRLEN
3347 36393           pkg_name_len(pTHX_ char *sub_name, I32 len)
3348             {
3349             /* pTHX_ needed for old rninstr in old perl versions */
3350 36393           const char *delim = "::";
3351             /* find end of package name */
3352 36393 50         char *colon = rninstr(sub_name, sub_name+(len > 0 ? len : -len), delim, delim+2);
3353 36393 50         if (!colon || colon == sub_name)
    50          
3354 0           return 0; /* no :: delimiter */
3355 36393           return (colon - sub_name);
3356             }
3357              
3358             /* Given a fully-qualified sub_name lookup the package name portion in
3359             * the pkg_fids_hv hash. Return Nullsv if there's no package name or no
3360             * correponding entry, else returns the SV.
3361             *
3362             * About pkg_fids_hv:
3363             * pp_subcall_profiler() creates undef entries for a package
3364             * name the first time a sub in the package is called.
3365             * write_sub_line_ranges() updates the SV with the filename associated
3366             * with the package, or at least its best guess.
3367             */
3368             static SV *
3369 36393           sub_pkg_filename_sv(pTHX_ char *sub_name, I32 len)
3370             {
3371             SV **svp;
3372 36393           STRLEN pkg_len = pkg_name_len(aTHX_ sub_name, len);
3373 36393 50         if (!pkg_len)
3374 0           return Nullsv; /* no :: delimiter */
3375 36393           svp = hv_fetch(pkg_fids_hv, sub_name, (I32)pkg_len, 0);
3376 36393 100         if (!svp)
3377 29641           return Nullsv; /* not a package we've profiled sub calls into */
3378 6752           return *svp;
3379             }
3380              
3381              
3382             static int
3383 36055           parse_DBsub_value(pTHX_ SV *sv, STRLEN *filename_len_p, UV *first_line_p, UV *last_line_p, char *sub_name) {
3384             /* "filename:first-last" */
3385 36055 50         char *filename = SvPV_nolen(sv);
3386 36055           char *first = strrchr(filename, ':'); /* find last colon */
3387             char *last;
3388 36055           int first_is_neg = 0;
3389              
3390 36055 50         if (first && filename_len_p)
    100          
3391 35559           *filename_len_p = first - filename;
3392              
3393 36055 50         if (!first++) /* start of first number, if colon was found */
3394 0           return 0;
3395 36055 50         if ('-' == *first) { /* first number is negative */
3396 0           ++first;
3397 0           first_is_neg = 1;
3398             }
3399 36055           last = strchr(first, '-'); /* find separator dash */
3400              
3401 36055 50         if (!last || !grok_number(first, last-first, first_line_p))
    50          
3402 0           return 0;
3403 36055 50         if (first_is_neg) {
3404 0           warn("Negative first line number in %%DB::sub entry '%s' for %s\n",
3405             filename, sub_name);
3406 0           *first_line_p = 0;
3407             }
3408              
3409 36055 50         if ('-' == *++last) { /* skip past dash, is next char a minus? */
3410 0           warn("Negative last line number in %%DB::sub entry '%s' for %s\n",
3411             filename, sub_name);
3412 0           last = (char *)"0";
3413             }
3414 36055 100         if (last_line_p)
3415 35559           *last_line_p = atoi(last);
3416              
3417 36055           return 1;
3418             }
3419              
3420              
3421             static void
3422 675           write_sub_line_ranges(pTHX)
3423             {
3424             char *sub_name;
3425             I32 sub_name_len;
3426             SV *file_lines_sv;
3427 675           HV *hv = GvHV(PL_DBsub);
3428             unsigned int fid;
3429              
3430 675 50         if (trace_level >= 1)
3431 0           logwarn("~ writing sub line ranges - prescan\n");
3432              
3433             /* Skim through PL_DBsub hash to build a package to filename hash
3434             * by associating the package part of the sub_name in the key
3435             * with the filename part of the value.
3436             * but only for packages we already know we're interested in
3437             */
3438 675           hv_iterinit(hv);
3439 35688 100         while (NULL != (file_lines_sv = hv_iternextsv(hv, &sub_name, &sub_name_len))) {
3440             STRLEN file_lines_len;
3441 35013 50         char *filename = SvPV(file_lines_sv, file_lines_len);
3442             char *first;
3443             STRLEN filename_len;
3444             SV *pkg_filename_sv;
3445              
3446             /* This is a heuristic, and might not be robust, but it seems that
3447             it's possible to get problematically bogus entries in this hash.
3448             Specifically, setting the 'lvalue' attribute on an XS subroutine
3449             during a bootstrap can cause op.c to load attributes, and in turn
3450             cause a DynaLoader::BEGIN entry in %DB::sub associated with the
3451             .pm file of the XS sub's module, not DynaLoader. This has the result
3452             that if we try to associate XSUBs with filenames using %DB::sub,
3453             we can go very wrong.
3454              
3455             Fortunately all "wrong" entries so far spotted have a line range
3456             with a non-zero start, and a zero end. This cannot be legal, so we
3457             ignore those.
3458             */
3459              
3460 35013 100         if (file_lines_len > 4
3461 34228 100         && filename[file_lines_len - 2] == '-' && filename[file_lines_len - 1] == '0'
    100          
3462 517 50         && filename[file_lines_len - 4] != ':' && filename[file_lines_len - 3] != '0')
    0          
3463 34271           continue; /* ignore filenames from %DB::sub that match /:[^0]-0$/ */
3464              
3465 35013           first = strrchr(filename, ':');
3466 35013 50         filename_len = (first) ? first - filename : 0;
3467              
3468             /* get sv for package-of-subname to filename mapping */
3469 35013           pkg_filename_sv = sub_pkg_filename_sv(aTHX_ sub_name, sub_name_len);
3470              
3471 35013 100         if (!pkg_filename_sv) /* we don't know package */
3472 29553           continue;
3473              
3474             /* already got a cached filename for this package XXX should allow multiple */
3475 5460 100         if (SvOK(pkg_filename_sv)) {
    50          
    50          
3476             STRLEN cached_len;
3477 4450 50         char *cached_filename = SvPV(pkg_filename_sv, cached_len);
3478              
3479             /*
3480             * if the cached filename is an eval and the current one isn't
3481             * then we should cache the current one instead
3482             */
3483 4450 100         if (filename_len > 0
3484 3933 100         && filename_is_eval(cached_filename, cached_len)
3485 93 100         && !filename_is_eval(filename, filename_len)
3486             ) {
3487 52 50         if (trace_level >= 3)
3488 0           logwarn("Package '%.*s' (of sub %.*s) association promoted from '%.*s' to '%.*s'\n",
3489 0           (int)pkg_name_len(aTHX_ sub_name, sub_name_len), sub_name,
3490             (int)sub_name_len, sub_name,
3491             (int)cached_len, cached_filename,
3492             (int)filename_len, filename);
3493 52           sv_setpvn(pkg_filename_sv, filename, filename_len);
3494 52           continue;
3495             }
3496              
3497 4398 50         if (trace_level >= 3
3498 0 0         && strnNE(SvPV_nolen(pkg_filename_sv), filename, filename_len)
    0          
3499 0 0         && !filename_is_eval(filename, filename_len)
3500             ) {
3501             /* eg utf8::SWASHNEW is already associated with .../utf8.pm not .../utf8_heavy.pl */
3502 0 0         logwarn("Package '%.*s' (of sub %.*s) not associated with '%.*s' because already associated with '%s'\n",
3503 0           (int)pkg_name_len(aTHX_ sub_name, sub_name_len), sub_name,
3504             (int)sub_name_len, sub_name,
3505             (int)filename_len, filename,
3506 0           SvPV_nolen(pkg_filename_sv)
3507             );
3508             }
3509 4450           continue;
3510             }
3511              
3512             /* ignore if filename is empty (eg xs) */
3513 1010 100         if (!filename_len) {
3514 268 50         if (trace_level >= 3)
3515 0           logwarn("Sub %.*s has no filename associated (%s)\n",
3516             (int)sub_name_len, sub_name, filename);
3517 268           continue;
3518             }
3519              
3520             /* associate the filename with the package */
3521 742           sv_setpvn(pkg_filename_sv, filename, filename_len);
3522              
3523             /* ensure a fid is assigned since we don't allow it below */
3524 742           fid = get_file_id(aTHX_ filename, filename_len, NYTP_FIDf_VIA_SUB);
3525              
3526 742 50         if (trace_level >= 3)
3527 742           logwarn("Associating package of %s with %.*s (fid %d)\n",
3528             sub_name, (int)filename_len, filename, fid );
3529             }
3530              
3531 675 100         if (main_runtime_used) { /* Create fake entry for main::RUNTIME sub */
3532 594           char runtime[] = "main::RUNTIME";
3533 594           const I32 runtime_len = sizeof(runtime) - 1;
3534 594           SV *sv = *hv_fetch(hv, runtime, runtime_len, 1);
3535              
3536             /* get name of file that contained first profiled sub in 'main::' */
3537 594           SV *pkg_filename_sv = sub_pkg_filename_sv(aTHX_ runtime, runtime_len);
3538 594 100         if (!pkg_filename_sv) { /* no subs in main, so guess */
3539 88           sv_setpvn(sv, fidhash.first_inserted->key, fidhash.first_inserted->key_len);
3540             }
3541 506 100         else if (SvOK(pkg_filename_sv)) {
    50          
    50          
3542 505           sv_setsv(sv, pkg_filename_sv);
3543             }
3544             else {
3545 1           sv_setpvn(sv, "", 0);
3546             }
3547 594           sv_catpvs(sv, ":1-1");
3548             }
3549              
3550 675 50         if (trace_level >= 1)
3551 0 0         logwarn("~ writing sub line ranges of %ld subs\n", (long)HvKEYS(hv));
3552              
3553             /* Iterate over PL_DBsub writing out fid and source line range of subs.
3554             * If filename is missing (i.e., because it's an xsub so has no source file)
3555             * then use the filename of another sub in the same package.
3556             */
3557 36234 100         while (NULL != (file_lines_sv = hv_iternextsv(hv, &sub_name, &sub_name_len))) {
3558             /* "filename:first-last" */
3559 35559 50         char *filename = SvPV_nolen(file_lines_sv);
3560             STRLEN filename_len;
3561             UV first_line, last_line;
3562              
3563 35559 50         if (!parse_DBsub_value(aTHX_ file_lines_sv, &filename_len, &first_line, &last_line, sub_name)) {
3564 0           logwarn("Can't parse %%DB::sub entry for %s '%s'\n", sub_name, filename);
3565 29514           continue;
3566             }
3567              
3568 35559 100         if (!filename_len) { /* no filename, so presumably a fake entry for xsub */
3569             /* do we know a filename that contains subs in the same package */
3570 786           SV *pkg_filename_sv = sub_pkg_filename_sv(aTHX_ sub_name, sub_name_len);
3571 786 50         if (pkg_filename_sv && SvOK(pkg_filename_sv)) {
    100          
    50          
    50          
3572 657 50         filename = SvPV(pkg_filename_sv, filename_len);
3573 657 50         if (trace_level >= 2)
3574 0           logwarn("Sub %s is xsub, we'll associate it with filename %.*s\n",
3575             sub_name, (int)filename_len, filename);
3576             }
3577             }
3578              
3579 35559           fid = get_file_id(aTHX_ filename, filename_len, 0);
3580 35559 100         if (!fid) {
3581 29514 50         if (trace_level >= 4)
3582 0           logwarn("Sub %s has no fid assigned (for file '%.*s')\n",
3583             sub_name, (int)filename_len, filename);
3584 29514           continue; /* no point in writing subs in files we've not profiled */
3585             }
3586              
3587 6045 50         if (trace_level >= 2)
3588 0           logwarn("Sub %s fid %u lines %lu..%lu\n",
3589             sub_name, fid, (unsigned long)first_line, (unsigned long)last_line);
3590              
3591 6045           NYTP_write_sub_info(out, fid, sub_name, sub_name_len, (unsigned long)first_line,
3592             (unsigned long)last_line);
3593             }
3594 675           }
3595              
3596              
3597             static void
3598 675           write_sub_callers(pTHX)
3599             {
3600             char *called_subname;
3601             I32 called_subname_len;
3602             SV *fid_line_rvhv;
3603 675           int negative_time_calls = 0;
3604              
3605 675 50         if (!sub_callers_hv)
3606 0           return;
3607 675 50         if (trace_level >= 1)
3608 0 0         logwarn("~ writing sub callers for %ld subs\n", (long)HvKEYS(sub_callers_hv));
3609              
3610 675           hv_iterinit(sub_callers_hv);
3611 3791 100         while (NULL != (fid_line_rvhv = hv_iternextsv(sub_callers_hv, &called_subname, &called_subname_len))) {
3612             HV *fid_lines_hv;
3613             char *caller_subname;
3614             I32 caller_subname_len;
3615             SV *sv;
3616              
3617 3116 50         if (!SvROK(fid_line_rvhv) || SvTYPE(SvRV(fid_line_rvhv))!=SVt_PVHV) {
    50          
3618 0           logwarn("bad entry %s in sub_callers_hv\n", called_subname);
3619 0           continue;
3620             }
3621 3116           fid_lines_hv = (HV*)SvRV(fid_line_rvhv);
3622              
3623             if (0) {
3624             logwarn("Callers of %s:\n", called_subname);
3625             /* level, *file, *sv, I32 nest, I32 maxnest, bool dumpops, STRLEN pvlim */
3626             do_sv_dump(0, Perl_debug_log, fid_line_rvhv, 0, 5, 0, 100);
3627             }
3628              
3629             /* iterate over callers to this sub ({ "subname[fid:line]" => [ ... ] }) */
3630 3116           hv_iterinit(fid_lines_hv);
3631 8663 100         while (NULL != (sv = hv_iternextsv(fid_lines_hv, &caller_subname, &caller_subname_len))) {
3632             NV sc[NYTP_SCi_elements];
3633 5547           AV *av = (AV *)SvRV(sv);
3634 5547           int trace = (trace_level >= 3);
3635             UV count;
3636             UV depth;
3637              
3638 5547           unsigned int fid = 0, line = 0;
3639 5547           const char *fid_line_delim = "[";
3640 5547           char *fid_line_start = rninstr(caller_subname, caller_subname+caller_subname_len, fid_line_delim, fid_line_delim+1);
3641 5547 50         if (!fid_line_start) {
3642 0           logwarn("bad fid_lines_hv key '%s'\n", caller_subname);
3643 0           continue;
3644             }
3645 5547 50         if (2 != sscanf(fid_line_start+1, "%u:%u", &fid, &line)) {
3646 0           logwarn("bad fid_lines_hv format '%s'\n", caller_subname);
3647 0           continue;
3648             }
3649             /* trim length to effectively hide the [fid:line] suffix */
3650 5547           caller_subname_len = (I32)(fid_line_start-caller_subname);
3651              
3652             /* catch negative line numbers that have been stored unsigned */
3653 5547 50         if (line > 2147483600) { /* ~2**31 */
3654 0           logwarn("%s called by %.*s at fid %u line %u - crazy line number changed to 0\n",
3655             called_subname, (int)caller_subname_len, caller_subname, fid, line);
3656 0           line = 0;
3657             }
3658              
3659 5547           count = uv_from_av(aTHX_ av, NYTP_SCi_CALL_COUNT, 0);
3660 5547           sc[NYTP_SCi_CALL_COUNT] = count * 1.0;
3661 5547           sc[NYTP_SCi_INCL_RTIME] = nv_from_av(aTHX_ av, NYTP_SCi_INCL_TICKS, 0.0) / ticks_per_sec;
3662 5547           sc[NYTP_SCi_EXCL_RTIME] = nv_from_av(aTHX_ av, NYTP_SCi_EXCL_TICKS, 0.0) / ticks_per_sec;
3663 5547           sc[NYTP_SCi_RECI_RTIME] = nv_from_av(aTHX_ av, NYTP_SCi_RECI_RTIME, 0.0);
3664 5547           depth = uv_from_av(aTHX_ av, NYTP_SCi_REC_DEPTH , 0);
3665 5547           sc[NYTP_SCi_REC_DEPTH] = depth * 1.0;
3666              
3667 5547           NYTP_write_sub_callers(out, fid, line,
3668             caller_subname, caller_subname_len,
3669             (unsigned int)count,
3670             sc[NYTP_SCi_INCL_RTIME],
3671             sc[NYTP_SCi_EXCL_RTIME],
3672             sc[NYTP_SCi_RECI_RTIME],
3673             (unsigned int)depth,
3674             called_subname, called_subname_len);
3675              
3676             /* sanity check - early warning */
3677 5547 50         if (sc[NYTP_SCi_INCL_RTIME] < 0.0 || sc[NYTP_SCi_EXCL_RTIME] < 0.0) {
    50          
3678 0           ++negative_time_calls;
3679 0 0         if (trace_level) {
3680 0           logwarn("%s call has negative time: incl %" NVff "s, excl %" NVff "s:\n",
3681             called_subname, sc[NYTP_SCi_INCL_RTIME], sc[NYTP_SCi_EXCL_RTIME]);
3682 0           trace = 1;
3683             }
3684             }
3685              
3686 5547 50         if (trace) {
3687 0 0         if (!fid && !line) {
    0          
3688 0           logwarn("%s is xsub\n", called_subname);
3689             }
3690             else {
3691 5547           logwarn("%s called by %.*s at %u:%u: count %ld (i%" NVff "s e%" NVff "s, d%d ri%" NVff "s)\n",
3692             called_subname, (int)caller_subname_len, caller_subname, fid, line,
3693 0           (long)sc[NYTP_SCi_CALL_COUNT], sc[NYTP_SCi_INCL_RTIME], sc[NYTP_SCi_EXCL_RTIME],
3694 0           (int)sc[NYTP_SCi_REC_DEPTH], sc[NYTP_SCi_RECI_RTIME]);
3695             }
3696             }
3697             }
3698             }
3699 675 50         if (negative_time_calls) {
3700 675           logwarn("Warning: %d subroutine calls had negative time! See TROUBLESHOOTING in the NYTProf documentation. (Clock %ld)\n",
3701 0           negative_time_calls, (long)profile_clock);
3702             }
3703             }
3704              
3705              
3706             static void
3707 675           write_src_of_files(pTHX)
3708             {
3709             fid_hash_entry *e;
3710 675           int t_has_src = 0;
3711 675           int t_save_src = 0;
3712 675           int t_no_src = 0;
3713 675           long t_lines = 0;
3714              
3715 675 50         if (trace_level >= 1)
3716 0           logwarn("~ writing file source code\n");
3717              
3718 2252 100         for (e = (fid_hash_entry*)fidhash.first_inserted; e; e = (fid_hash_entry*)e->he.next_inserted) {
3719             I32 lines;
3720             int line;
3721 1577           AV *src_av = GvAV(gv_fetchfile_flags(e->he.key, e->he.key_len, 0));
3722              
3723 1577 100         if ( !(e->fid_flags & NYTP_FIDf_HAS_SRC) ) {
3724 246           const char *hint = "";
3725 246           ++t_no_src;
3726 246 100         if (src_av && av_len(src_av) > -1) /* sanity check */
    50          
3727 0           hint = " (NYTP_FIDf_HAS_SRC not set but src available!)";
3728 246 50         if (trace_level >= 3 || *hint)
    50          
3729 0           logwarn("fid %d has no src saved for %.*s%s\n",
3730             e->he.id, e->he.key_len, e->he.key, hint);
3731 246           continue;
3732             }
3733 1331 50         if (!src_av) { /* sanity check */
3734 0           ++t_no_src;
3735 0           logwarn("fid %d has no src but NYTP_FIDf_HAS_SRC is set! (%.*s)\n",
3736             e->he.id, e->he.key_len, e->he.key);
3737 0           continue;
3738             }
3739 1331           ++t_has_src;
3740              
3741 1331 100         if ( !(e->fid_flags & NYTP_FIDf_SAVE_SRC) ) {
3742 320           continue;
3743             }
3744 1011           ++t_save_src;
3745              
3746 1011           lines = av_len(src_av); /* -1 is empty, 1 is 1 line etc, 0 shouldn't happen */
3747 1011 50         if (trace_level >= 3)
3748 0           logwarn("fid %d has %ld src lines for %.*s\n",
3749             e->he.id, (long)lines, e->he.key_len, e->he.key);
3750 29188 100         for (line = 1; line <= lines; ++line) { /* lines start at 1 */
3751 28177           SV **svp = av_fetch(src_av, line, 0);
3752 28177           STRLEN len = 0;
3753 28177 100         const char *src = (svp) ? SvPV(*svp, len) : "";
    50          
3754             /* outputting the tag and fid for each (non empty) line
3755             * is a little inefficient, but not enough to worry about */
3756 28177           NYTP_write_src_line(out, e->he.id, line, src, (I32)len); /* includes newline */
3757 28177 50         if (trace_level >= 8) {
3758 0 0         logwarn("fid %d src line %d: %s%s", e->he.id, line, src,
3759 0 0         (len && src[len-1]=='\n') ? "" : "\n");
3760             }
3761 28177           ++t_lines;
3762             }
3763             }
3764              
3765 675 50         if (trace_level >= 2)
3766 0           logwarn("~ wrote %ld source lines for %d files (%d skipped without savesrc option, %d others had no source available)\n",
3767             t_lines, t_save_src, t_has_src-t_save_src, t_no_src);
3768 675           }
3769              
3770              
3771             static void
3772 23708           normalize_eval_seqn(pTHX_ SV *sv) {
3773             /* in-place-edit any eval sequence numbers to 0 */
3774             STRLEN len;
3775 23708 50         char *start = SvPV(sv, len);
3776             char *first_space;
3777              
3778 23708           return; /* disabled, again */
3779              
3780             /* effectively does
3781             s/(
3782             \( # first character is literal (
3783             (?:re_)?eval\ # eval or re_eval followed by space
3784             ) # [capture that]
3785             [0-9]+ # digits
3786             (?=\)) # look ahead for literal )
3787             /$1 0/xg # and rebuild, replacing the digts with 0
3788             */
3789              
3790             /* Assumption is that space is the least common character in a filename. */
3791              
3792             for (; len >= 8 && (first_space = (char *)memchr(start, ' ', len));
3793             (len -= first_space +1 - start), (start = first_space + 1)) {
3794             char *first_digit;
3795             char *close;
3796              
3797             if (!((first_space - start >= 5
3798             && memEQ(first_space - 5, "(eval", 5))
3799             || (first_space - start >= 8
3800             && memEQ(first_space - 8, "(re_eval", 8)))) {
3801             /* Fixed string not found. Try again. */
3802             continue;
3803             }
3804              
3805             first_digit = first_space + 1;
3806             if (*first_digit < '0' || *first_digit > '9')
3807             continue;
3808              
3809             close = first_digit + 1;
3810              
3811             while (*close >= '0' && *close <= '9')
3812             ++close;
3813              
3814             if (*close != ')')
3815             continue;
3816              
3817             if (trace_level >= 15)
3818             logwarn("recognized eval in name at '%s' in %s\n", first_digit, start);
3819              
3820             *first_digit++ = '0';
3821              
3822             /* first_digit now points to the target of the move. */
3823              
3824             if (close != first_digit) {
3825             /* 2 or more digits */
3826             memmove(first_digit, close,
3827             start + len + 1 /* pointer beyond the trailing '\0' */
3828             - close); /* pointer to the ) */
3829              
3830             len -= (close - first_digit);
3831             SvCUR_set(sv, SvCUR(sv) - (close - first_digit));
3832             }
3833              
3834             if (trace_level >= 15)
3835             logwarn("edited it to: %s\n", start);
3836             }
3837             }
3838              
3839              
3840             static AV *
3841 15760           lookup_subinfo_av(pTHX_ SV *subname_sv, HV *sub_subinfo_hv)
3842             {
3843             /* { 'pkg::sub' => [
3844             * fid, first_line, last_line, incl_time
3845             * ], ... }
3846             */
3847 15760           HE *he = hv_fetch_ent(sub_subinfo_hv, subname_sv, 1, 0);
3848 15760           SV *sv = HeVAL(he);
3849 15760 100         if (!SvROK(sv)) { /* autoviv */
3850 7972           AV *av = newAV();
3851 7972           SV *rv = newRV_noinc((SV *)av);
3852             /* 0: fid - may be undef
3853             * 1: start_line - may be undef if not known and not known to be xs
3854             * 2: end_line - ditto
3855             * typically due to an xsub that was called but exited via an exception
3856             */
3857 7972           sv_setsv(*av_fetch(av, NYTP_SIi_SUB_NAME, 1), newSVsv(subname_sv));
3858 7972           sv_setuv(*av_fetch(av, NYTP_SIi_CALL_COUNT, 1), 0); /* call count */
3859 7972           sv_setnv(*av_fetch(av, NYTP_SIi_INCL_RTIME, 1), 0.0); /* incl_time */
3860 7972           sv_setnv(*av_fetch(av, NYTP_SIi_EXCL_RTIME, 1), 0.0); /* excl_time */
3861 7972           sv_setsv(*av_fetch(av, NYTP_SIi_PROFILE, 1), &PL_sv_undef); /* ref to profile */
3862 7972           sv_setuv(*av_fetch(av, NYTP_SIi_REC_DEPTH, 1), 0); /* rec_depth */
3863 7972           sv_setnv(*av_fetch(av, NYTP_SIi_RECI_RTIME, 1), 0.0); /* reci_time */
3864 7972           sv_setsv(sv, rv);
3865             }
3866 15760           return (AV *)SvRV(sv);
3867             }
3868              
3869              
3870             static void
3871 16898           store_attrib_sv(pTHX_ HV *attr_hv, const char *text, I32 text_len, SV *value_sv)
3872             {
3873 16898           (void)hv_store(attr_hv, text, text_len, value_sv, 0);
3874 16898 50         if (trace_level >= 1)
3875 0 0         logwarn(": %.*s = '%s'\n", (int) text_len, text, SvPV_nolen(value_sv));
3876 16898           }
3877              
3878             #if 0 /* not used at the moment */
3879             static int
3880             eval_outer_fid(pTHX_
3881             AV *fid_fileinfo_av,
3882             unsigned int fid,
3883             int recurse,
3884             unsigned int *eval_file_num_ptr,
3885             unsigned int *eval_line_num_ptr
3886             ) {
3887             unsigned int outer_fid;
3888             AV *av;
3889             SV *fid_info_rvav = *av_fetch(fid_fileinfo_av, fid, 1);
3890             if (!SvROK(fid_info_rvav)) /* should never happen */
3891             return 0;
3892             av = (AV *)SvRV(fid_info_rvav);
3893             outer_fid = (unsigned int)SvUV(*av_fetch(av,NYTP_FIDi_EVAL_FID,1));
3894             if (!outer_fid)
3895             return 0;
3896             if (outer_fid == fid) {
3897             logwarn("Possible corruption: eval_outer_fid of %d is %d!\n", fid, outer_fid);
3898             return 0;
3899             }
3900             if (eval_file_num_ptr)
3901             *eval_file_num_ptr = outer_fid;
3902             if (eval_line_num_ptr)
3903             *eval_line_num_ptr = (unsigned int)SvUV(*av_fetch(av,NYTP_FIDi_EVAL_LINE,1));
3904             if (recurse)
3905             eval_outer_fid(aTHX_ fid_fileinfo_av, outer_fid, recurse, eval_file_num_ptr, eval_line_num_ptr);
3906             return 1;
3907             }
3908             #endif
3909              
3910             typedef struct loader_state_base {
3911             unsigned long input_chunk_seqn;
3912             } Loader_state_base;
3913              
3914             typedef void (*loader_callback)(Loader_state_base *cb_data, const int tag, ...);
3915              
3916             typedef struct loader_state_callback {
3917             Loader_state_base base_state;
3918             #ifdef MULTIPLICITY
3919             PerlInterpreter *interp;
3920             #endif
3921             CV *cb[nytp_tag_max];
3922             SV *cb_args[11]; /* must be large enough for the largest callback argument list */
3923             SV *tag_names[nytp_tag_max];
3924             SV *input_chunk_seqn_sv;
3925             } Loader_state_callback;
3926              
3927             typedef struct loader_state_profiler {
3928             Loader_state_base base_state;
3929             #ifdef MULTIPLICITY
3930             PerlInterpreter *interp;
3931             #endif
3932             unsigned int last_file_num;
3933             unsigned int last_line_num;
3934             int statement_discount;
3935             UV total_stmts_discounted;
3936             UV total_stmts_measured;
3937             NV total_stmts_duration;
3938             UV total_sub_calls;
3939             AV *fid_line_time_av;
3940             AV *fid_block_time_av;
3941             AV *fid_sub_time_av;
3942             AV *fid_srclines_av;
3943             AV *fid_fileinfo_av;
3944             HV *sub_subinfo_hv;
3945             HV *live_pids_hv;
3946             HV *attr_hv;
3947             HV *option_hv;
3948             HV *file_info_stash;
3949             /* these times don't reflect profile_enable & profile_disable calls */
3950             NV profiler_start_time;
3951             NV profiler_end_time;
3952             NV profiler_duration;
3953             } Loader_state_profiler;
3954              
3955             static void
3956 326178           load_discount_callback(Loader_state_base *cb_data, const int tag, ...)
3957             {
3958 326178           Loader_state_profiler *state = (Loader_state_profiler *)cb_data;
3959             PERL_UNUSED_ARG(tag);
3960              
3961 326178 50         if (trace_level >= 8)
3962 0           logwarn("discounting next statement after %u:%d\n",
3963             state->last_file_num, state->last_line_num);
3964 326178 50         if (state->statement_discount)
3965 0           logwarn("multiple statement discount after %u:%d\n",
3966             state->last_file_num, state->last_line_num);
3967 326178           ++state->statement_discount;
3968 326178           ++state->total_stmts_discounted;
3969 326178           }
3970              
3971             static void
3972 1345528           load_time_callback(Loader_state_base *cb_data, const int tag, ...)
3973             {
3974 1345528           Loader_state_profiler *state = (Loader_state_profiler *)cb_data;
3975             dTHXa(state->interp);
3976             va_list args;
3977 1345528           char trace_note[80] = "";
3978             SV *fid_info_rvav;
3979             NV seconds;
3980 1345528           unsigned int eval_file_num = 0;
3981 1345528           unsigned int eval_line_num = 0;
3982             I32 ticks;
3983             unsigned int file_num;
3984             unsigned int line_num;
3985              
3986 1345528           va_start(args, tag);
3987              
3988 1345528 50         ticks = va_arg(args, I32);
3989 1345528 50         file_num = va_arg(args, unsigned int);
3990 1345528 50         line_num = va_arg(args, unsigned int);
3991              
3992 1345528           seconds = (NV)ticks / ticks_per_sec;
3993              
3994 1345528           fid_info_rvav = *av_fetch(state->fid_fileinfo_av, file_num, 1);
3995 1345528 50         if (!SvROK(fid_info_rvav)) { /* should never happen */
3996 0 0         if (!SvOK(fid_info_rvav)) { /* only warn once */
    0          
    0          
3997 0           logwarn("Fid %u used but not defined\n", file_num);
3998 0           sv_setsv(fid_info_rvav, &PL_sv_no);
3999             }
4000             }
4001              
4002 1345528 50         if (trace_level >= 8) {
4003 0           const char *new_file_name = "";
4004 0 0         if (file_num != state->last_file_num && SvROK(fid_info_rvav))
    0          
4005 0 0         new_file_name = SvPV_nolen(*av_fetch((AV *)SvRV(fid_info_rvav), NYTP_FIDi_FILENAME, 1));
4006 0           logwarn("Read %d:%-4d %2ld ticks%s %s\n",
4007             file_num, line_num, (long)ticks, trace_note, new_file_name);
4008             }
4009              
4010 1345528           add_entry(aTHX_ state->fid_line_time_av, file_num, line_num,
4011             seconds, eval_file_num, eval_line_num,
4012 1345528           1 - state->statement_discount
4013             );
4014              
4015 1345528 50         if (tag == nytp_time_block) {
4016 1345528 50         unsigned int block_line_num = va_arg(args, unsigned int);
4017 1345528 50         unsigned int sub_line_num = va_arg(args, unsigned int);
4018              
4019 1345528 100         if (!state->fid_block_time_av)
4020 966           state->fid_block_time_av = newAV();
4021 1345528           add_entry(aTHX_ state->fid_block_time_av, file_num, block_line_num,
4022             seconds, eval_file_num, eval_line_num,
4023 1345528           1 - state->statement_discount
4024             );
4025              
4026 1345528 100         if (!state->fid_sub_time_av)
4027 966           state->fid_sub_time_av = newAV();
4028 1345528           add_entry(aTHX_ state->fid_sub_time_av, file_num, sub_line_num,
4029             seconds, eval_file_num, eval_line_num,
4030 1345528           1 - state->statement_discount
4031             );
4032              
4033 1345528 50         if (trace_level >= 8)
4034 0           logwarn("\tblock %u, sub %u\n", block_line_num, sub_line_num);
4035             }
4036              
4037 1345528           va_end(args);
4038              
4039 1345528           state->total_stmts_measured++;
4040 1345528           state->total_stmts_duration += seconds;
4041 1345528           state->statement_discount = 0;
4042 1345528           state->last_file_num = file_num;
4043 1345528           state->last_line_num = line_num;
4044 1345528           }
4045              
4046             static void
4047 2422           load_new_fid_callback(Loader_state_base *cb_data, const int tag, ...)
4048             {
4049 2422           Loader_state_profiler *state = (Loader_state_profiler *)cb_data;
4050             dTHXa(state->interp);
4051             va_list args;
4052             AV *av;
4053             SV *rv;
4054             SV **svp;
4055             SV *filename_sv;
4056             unsigned int file_num;
4057             unsigned int eval_file_num;
4058             unsigned int eval_line_num;
4059             unsigned int fid_flags;
4060             unsigned int file_size;
4061             unsigned int file_mtime;
4062              
4063 2422           va_start(args, tag);
4064              
4065 2422 50         file_num = va_arg(args, unsigned int);
4066 2422 50         eval_file_num = va_arg(args, unsigned int);
4067 2422 50         eval_line_num = va_arg(args, unsigned int);
4068 2422 50         fid_flags = va_arg(args, unsigned int);
4069 2422 50         file_size = va_arg(args, unsigned int);
4070 2422 50         file_mtime = va_arg(args, unsigned int);
4071 2422 50         filename_sv = va_arg(args, SV *);
4072              
4073 2422           va_end(args);
4074              
4075 2422 50         if (trace_level >= 2) {
4076             char buf[80];
4077             char parent_fid[80];
4078 0 0         if (eval_file_num || eval_line_num)
    0          
4079 0           sprintf(parent_fid, " (is eval at %u:%u)", eval_file_num, eval_line_num);
4080             else
4081 0           sprintf(parent_fid, " (file sz%d mt%d)", file_size, file_mtime);
4082              
4083 0 0         logwarn("Fid %2u is %s%s 0x%x(%s)\n",
4084 0           file_num, SvPV_nolen(filename_sv), parent_fid,
4085             fid_flags, fmt_fid_flags(aTHX_ fid_flags, buf, sizeof(buf)));
4086             }
4087              
4088             /* [ name, eval_file_num, eval_line_num, fid, flags, size, mtime, ... ]
4089             */
4090 2422           av = newAV();
4091 2422           rv = newRV_noinc((SV*)av);
4092 2422           sv_bless(rv, state->file_info_stash);
4093              
4094 2422           svp = av_fetch(state->fid_fileinfo_av, file_num, 1);
4095 2422 50         if (SvOK(*svp)) { /* should never happen, perhaps file is corrupt */
    50          
    50          
4096 0           AV *old_av = (AV *)SvRV(*av_fetch(state->fid_fileinfo_av, file_num, 1));
4097 0           SV *old_name = *av_fetch(old_av, 0, 1);
4098 0 0         logwarn("Fid %d redefined from %s to %s\n", file_num,
    0          
4099 0           SvPV_nolen(old_name), SvPV_nolen(filename_sv));
4100             }
4101 2422           sv_setsv(*svp, rv);
4102              
4103 2422           av_store(av, NYTP_FIDi_FILENAME, filename_sv); /* av now owns the sv */
4104 2422 100         if (eval_file_num) {
4105             SV *has_evals;
4106             /* this eval fid refers to the fid that contained the eval */
4107 1112           SV *eval_fi = *av_fetch(state->fid_fileinfo_av, eval_file_num, 1);
4108 1112 50         if (!SvROK(eval_fi)) { /* should never happen */
4109             char buf[80];
4110 0 0         logwarn("Eval '%s' (fid %d, flags:%s) has unknown invoking fid %d\n",
4111 0           SvPV_nolen(filename_sv), file_num,
4112             fmt_fid_flags(aTHX_ fid_flags, buf, sizeof(buf)), eval_file_num);
4113             /* so make it look like a real file instead of an eval */
4114 0           av_store(av, NYTP_FIDi_EVAL_FI, NULL);
4115 0           eval_file_num = 0;
4116 0           eval_line_num = 0;
4117             }
4118             else {
4119 1112           av_store(av, NYTP_FIDi_EVAL_FI, sv_rvweaken(newSVsv(eval_fi)));
4120             /* the fid that contained the eval has a list of eval fids */
4121 1112           has_evals = *av_fetch((AV *)SvRV(eval_fi), NYTP_FIDi_HAS_EVALS, 1);
4122 1112 100         if (!SvROK(has_evals)) /* autoviv */
4123 576           sv_setsv(has_evals, newRV_noinc((SV*)newAV()));
4124 1112           av_push((AV *)SvRV(has_evals), sv_rvweaken(newSVsv(rv)));
4125             }
4126             }
4127             else {
4128 1310           av_store(av, NYTP_FIDi_EVAL_FI, NULL);
4129             }
4130 2422 100         av_store(av, NYTP_FIDi_EVAL_FID, (eval_file_num) ? newSVuv(eval_file_num) : &PL_sv_no);
4131 2422 100         av_store(av, NYTP_FIDi_EVAL_LINE, (eval_file_num) ? newSVuv(eval_line_num) : &PL_sv_no);
4132 2422           av_store(av, NYTP_FIDi_FID, newSVuv(file_num));
4133 2422           av_store(av, NYTP_FIDi_FLAGS, newSVuv(fid_flags));
4134 2422           av_store(av, NYTP_FIDi_FILESIZE, newSVuv(file_size));
4135 2422           av_store(av, NYTP_FIDi_FILEMTIME, newSVuv(file_mtime));
4136 2422           av_store(av, NYTP_FIDi_PROFILE, NULL);
4137 2422           av_store(av, NYTP_FIDi_HAS_EVALS, NULL);
4138 2422           av_store(av, NYTP_FIDi_SUBS_DEFINED, newRV_noinc((SV*)newHV()));
4139 2422           av_store(av, NYTP_FIDi_SUBS_CALLED, newRV_noinc((SV*)newHV()));
4140 2422           }
4141              
4142             static void
4143 32560           load_src_line_callback(Loader_state_base *cb_data, const int tag, ...)
4144             {
4145 32560           Loader_state_profiler *state = (Loader_state_profiler *)cb_data;
4146             dTHXa(state->interp);
4147             va_list args;
4148             unsigned int file_num;
4149             unsigned int line_num;
4150             SV *src;
4151             AV *file_av;
4152              
4153 32560           va_start(args, tag);
4154              
4155 32560 50         file_num = va_arg(args, unsigned int);
4156 32560 50         line_num = va_arg(args, unsigned int);
4157 32560 50         src = va_arg(args, SV *);
4158              
4159 32560           va_end(args);
4160              
4161             /* first line in the file seen */
4162 32560 100         if (!av_exists(state->fid_srclines_av, file_num)) {
4163 1266           file_av = newAV();
4164 1266           av_store(state->fid_srclines_av, file_num, newRV_noinc((SV*)file_av));
4165             }
4166             else {
4167 31294           file_av = (AV *)SvRV(*av_fetch(state->fid_srclines_av, file_num, 1));
4168             }
4169            
4170 32560           av_store(file_av, line_num, src);
4171              
4172 32560 50         if (trace_level >= 8) {
4173 0 0         logwarn("Fid %2u:%u src: %s\n", file_num, line_num, SvPV_nolen(src));
4174             }
4175 32560           }
4176              
4177             static void
4178 7812           load_sub_info_callback(Loader_state_base *cb_data, const int tag, ...)
4179             {
4180 7812           Loader_state_profiler *state = (Loader_state_profiler *)cb_data;
4181             dTHXa(state->interp);
4182             va_list args;
4183             unsigned int fid;
4184             unsigned int first_line;
4185             unsigned int last_line;
4186             SV *subname_sv;
4187 7812           int skip_subinfo_store = 0;
4188             STRLEN subname_len;
4189             char *subname_pv;
4190             AV *av;
4191             SV *sv;
4192              
4193 7812           va_start(args, tag);
4194              
4195 7812 50         fid = va_arg(args, unsigned int);
4196 7812 50         first_line = va_arg(args, unsigned int);
4197 7812 50         last_line = va_arg(args, unsigned int);
4198 7812 50         subname_sv = va_arg(args, SV *);
4199              
4200 7812           va_end(args);
4201              
4202 7812           normalize_eval_seqn(aTHX_ subname_sv);
4203              
4204 7812 50         subname_pv = SvPV(subname_sv, subname_len);
4205 7812 50         if (trace_level >= 2)
4206 0           logwarn("Sub %s fid %u lines %u..%u\n",
4207             subname_pv, fid, first_line, last_line);
4208              
4209 7812           av = lookup_subinfo_av(aTHX_ subname_sv, state->sub_subinfo_hv);
4210 7812 50         if (SvOK(*av_fetch(av, NYTP_SIi_FID, 1))) {
    50          
    50          
4211             /* We've already seen this subroutine name.
4212             * Should only happen for anon subs in string evals so we warn
4213             * for other cases.
4214             */
4215 0 0         if (!instr(subname_pv, "__ANON__[(eval"))
4216 0           logwarn("Sub %s already defined!\n", subname_pv);
4217              
4218             /* We could always discard the fid+first_line+last_line here,
4219             * because we already have them stored, but for consistency
4220             * (and for the stability of the tests) we'll prefer the lowest fid
4221             */
4222 0 0         if (fid > SvUV(*av_fetch(av, NYTP_SIi_FID, 1)))
    0          
4223 0           skip_subinfo_store = 1;
4224              
4225             /* Finally, note that the fileinfo NYTP_FIDi_SUBS_DEFINED hash,
4226             * updated below, does get an entry for the sub *from each fid*
4227             * (ie string eval) that defines the subroutine.
4228             */
4229             }
4230 7812 50         if (!skip_subinfo_store) {
4231 7812           sv_setuv(*av_fetch(av, NYTP_SIi_FID, 1), fid);
4232 7812           sv_setuv(*av_fetch(av, NYTP_SIi_FIRST_LINE, 1), first_line);
4233 7812           sv_setuv(*av_fetch(av, NYTP_SIi_LAST_LINE, 1), last_line);
4234             }
4235              
4236             /* add sub to NYTP_FIDi_SUBS_DEFINED hash */
4237 7812           sv = SvRV(*av_fetch(state->fid_fileinfo_av, fid, 1));
4238 7812           sv = SvRV(*av_fetch((AV *)sv, NYTP_FIDi_SUBS_DEFINED, 1));
4239 7812           (void)hv_store((HV *)sv, subname_pv, (I32)subname_len, newRV_inc((SV*)av), 0);
4240 7812           }
4241              
4242             static void
4243 7948           load_sub_callers_callback(Loader_state_base *cb_data, const int tag, ...)
4244             {
4245 7948           Loader_state_profiler *state = (Loader_state_profiler *)cb_data;
4246             dTHXa(state->interp);
4247             va_list args;
4248             unsigned int fid;
4249             unsigned int line;
4250             SV *caller_subname_sv;
4251             unsigned int count;
4252             NV incl_time;
4253             NV excl_time;
4254             NV reci_time;
4255             unsigned int rec_depth;
4256             SV *called_subname_sv;
4257             char text[MAXPATHLEN*2];
4258             SV *sv;
4259             AV *subinfo_av;
4260             int len;
4261              
4262 7948           va_start(args, tag);
4263              
4264 7948 50         fid = va_arg(args, unsigned int);
4265 7948 50         line = va_arg(args, unsigned int);
4266 7948 50         count = va_arg(args, unsigned int);
4267 7948 50         incl_time = va_arg(args, NV);
4268 7948 50         excl_time = va_arg(args, NV);
4269 7948 50         reci_time = va_arg(args, NV);
4270 7948 50         rec_depth = va_arg(args, unsigned int);
4271 7948 50         called_subname_sv = va_arg(args, SV *);
4272 7948 50         caller_subname_sv = va_arg(args, SV *);
4273              
4274 7948           va_end(args);
4275              
4276 7948           normalize_eval_seqn(aTHX_ caller_subname_sv);
4277 7948           normalize_eval_seqn(aTHX_ called_subname_sv);
4278              
4279 7948 50         if (trace_level >= 6)
4280 0 0         logwarn("Sub %s called by %s %u:%u: count %d, incl %" NVff ", excl %" NVff "\n",
    0          
4281 0           SvPV_nolen(called_subname_sv), SvPV_nolen(caller_subname_sv),
4282             fid, line, count, incl_time, excl_time);
4283              
4284 7948           subinfo_av = lookup_subinfo_av(aTHX_ called_subname_sv, state->sub_subinfo_hv);
4285              
4286             /* subinfo_av's NYTP_SIi_CALLED_BY element is a hash ref:
4287             * { caller_fid => { caller_line => [ count, incl_time, ... ] } }
4288             */
4289 7948           sv = *av_fetch(subinfo_av, NYTP_SIi_CALLED_BY, 1);
4290 7948 100         if (!SvROK(sv)) /* autoviv */
4291 4112           sv_setsv(sv, newRV_noinc((SV*)newHV()));
4292              
4293 7948           len = sprintf(text, "%u", fid);
4294 7948           sv = *hv_fetch((HV*)SvRV(sv), text, len, 1);
4295 7948 100         if (!SvROK(sv)) /* autoviv */
4296 5910           sv_setsv(sv, newRV_noinc((SV*)newHV()));
4297              
4298             /* XXX gets called with fid=0 to indicate is_xsub
4299             * That's a hack that should be removed once we have per-sub flags
4300             */
4301 7948 100         if (fid) {
4302             SV *fi;
4303             AV *av;
4304 6838           len = sprintf(text, "%u", line);
4305              
4306 6838           sv = *hv_fetch((HV*)SvRV(sv), text, len, 1);
4307 6838 100         if (!SvROK(sv)) /* autoviv */
4308 6822           sv_setsv(sv, newRV_noinc((SV*)newAV()));
4309 16 50         else if (trace_level)
4310             /* calls to sub1 from the same fid:line could have different caller
4311             * subs due to evals or if profile_findcaller is off.
4312             */
4313 0 0         logwarn("Merging extra sub caller info for %s called at %d:%d\n",
4314 0           SvPV_nolen(called_subname_sv), fid, line);
4315              
4316 6838           av = (AV *)SvRV(sv);
4317 6838           sv = *av_fetch(av, NYTP_SCi_CALL_COUNT, 1);
4318 6838 100         sv_setuv(sv, (SvOK(sv)) ? SvUV(sv) + count : count);
    50          
    50          
    50          
4319 6838           sv = *av_fetch(av, NYTP_SCi_INCL_RTIME, 1);
4320 6838 100         sv_setnv(sv, (SvOK(sv)) ? SvNV(sv) + incl_time : incl_time);
    50          
    50          
    50          
4321 6838           sv = *av_fetch(av, NYTP_SCi_EXCL_RTIME, 1);
4322 6838 100         sv_setnv(sv, (SvOK(sv)) ? SvNV(sv) + excl_time : excl_time);
    50          
    50          
    50          
4323 6838           sv = *av_fetch(av, NYTP_SCi_INCL_TICKS, 1);
4324 6838           sv_setnv(sv, 0.0);
4325 6838           sv = *av_fetch(av, NYTP_SCi_EXCL_TICKS, 1);
4326 6838           sv_setnv(sv, 0.0);
4327 6838           sv = *av_fetch(av, NYTP_SCi_RECI_RTIME, 1);
4328 6838 100         sv_setnv(sv, (SvOK(sv)) ? SvNV(sv) + reci_time : reci_time);
    50          
    50          
    50          
4329 6838           sv = *av_fetch(av, NYTP_SCi_REC_DEPTH, 1);
4330 6838 100         if (!SvOK(sv) || SvUV(sv) < rec_depth) /* max() */
    50          
    50          
    50          
    50          
4331 6822           sv_setuv(sv, rec_depth);
4332             /* XXX temp hack way to store calling subname as key with undef value */
4333             /* ideally we should assign ids to subs (sid) the way we do with files (fid) */
4334 6838           sv = *av_fetch(av, NYTP_SCi_CALLING_SUB, 1);
4335 6838 100         if (!SvROK(sv)) /* autoviv */
4336 6822           sv_setsv(sv, newRV_noinc((SV*)newHV()));
4337 6838           (void)hv_fetch_ent((HV *)SvRV(sv), caller_subname_sv, 1, 0);
4338              
4339             /* also reference this sub call info array from the calling fileinfo
4340             * fi->[NYTP_FIDi_SUBS_CALLED] => { line => { subname => [ ... ] } }
4341             */
4342 6838           fi = SvRV(*av_fetch(state->fid_fileinfo_av, fid, 1));
4343 6838           fi = *av_fetch((AV *)fi, NYTP_FIDi_SUBS_CALLED, 1);
4344 6838           fi = *hv_fetch((HV*)SvRV(fi), text, len, 1);
4345 6838 100         if (!SvROK(fi)) /* autoviv */
4346 6058           sv_setsv(fi, newRV_noinc((SV*)newHV()));
4347 6838           fi = HeVAL(hv_fetch_ent((HV *)SvRV(fi), called_subname_sv, 1, 0));
4348             if (1) { /* ref a clone of the sub call info array */
4349 6838 50         AV *av2 = av_make(AvFILL(av)+1, AvARRAY(av));
4350 6838           av = av2;
4351             }
4352 6838           sv_setsv(fi, newRV_inc((SV *)av));
4353             }
4354             else { /* is meta-data about sub */
4355             /* line == 0: is_xs - set line range to 0,0 as marker */
4356 1110           sv_setiv(*av_fetch(subinfo_av, NYTP_SIi_FIRST_LINE, 1), 0);
4357 1110           sv_setiv(*av_fetch(subinfo_av, NYTP_SIi_LAST_LINE, 1), 0);
4358             }
4359              
4360             /* accumulate per-sub totals into subinfo */
4361 7948           sv = *av_fetch(subinfo_av, NYTP_SIi_CALL_COUNT, 1);
4362 7948 50         sv_setuv(sv, count + (SvOK(sv) ? SvUV(sv) : 0));
    0          
    0          
    50          
4363 7948           sv = *av_fetch(subinfo_av, NYTP_SIi_INCL_RTIME, 1);
4364 7948 50         sv_setnv(sv, incl_time + (SvOK(sv) ? SvNV(sv) : 0.0));
    0          
    0          
    50          
4365 7948           sv = *av_fetch(subinfo_av, NYTP_SIi_EXCL_RTIME, 1);
4366 7948 50         sv_setnv(sv, excl_time + (SvOK(sv) ? SvNV(sv) : 0.0));
    0          
    0          
    50          
4367             /* sub rec_depth - record the maximum */
4368 7948           sv = *av_fetch(subinfo_av, NYTP_SIi_REC_DEPTH, 1);
4369 7948 50         if (!SvOK(sv) || rec_depth > SvUV(sv))
    0          
    0          
    50          
    100          
4370 16           sv_setuv(sv, rec_depth);
4371 7948           sv = *av_fetch(subinfo_av, NYTP_SIi_RECI_RTIME, 1);
4372 7948 50         sv_setnv(sv, reci_time + (SvOK(sv) ? SvNV(sv) : 0.0));
    0          
    0          
    50          
4373              
4374 7948           state->total_sub_calls += count;
4375 7948           }
4376              
4377             static void
4378 994           load_pid_start_callback(Loader_state_base *cb_data, const int tag, ...)
4379             {
4380 994           Loader_state_profiler *state = (Loader_state_profiler *)cb_data;
4381             dTHXa(state->interp);
4382             va_list args;
4383             unsigned int pid;
4384             unsigned int ppid;
4385             NV start_time;
4386             char text[MAXPATHLEN*2];
4387             int len;
4388              
4389 994           va_start(args, tag);
4390              
4391 994 50         pid = va_arg(args, unsigned int);
4392 994 50         ppid = va_arg(args, unsigned int);
4393 994 50         start_time = va_arg(args, NV);
4394              
4395 994           va_end(args);
4396              
4397 994           state->profiler_start_time = start_time;
4398              
4399 994           len = sprintf(text, "%d", pid);
4400 994           (void)hv_store(state->live_pids_hv, text, len, newSVuv(ppid), 0);
4401 994 50         if (trace_level)
4402 0           logwarn("Start of profile data for pid %s (ppid %d, %" IVdf " pids live) at %" NVff "\n",
4403 0 0         text, ppid, (IV)HvKEYS(state->live_pids_hv), start_time);
4404              
4405 994           store_attrib_sv(aTHX_ state->attr_hv, STR_WITH_LEN("profiler_start_time"),
4406             newSVnv(start_time));
4407 994           }
4408              
4409             static void
4410 994           load_pid_end_callback(Loader_state_base *cb_data, const int tag, ...)
4411             {
4412 994           Loader_state_profiler *state = (Loader_state_profiler *)cb_data;
4413             dTHXa(state->interp);
4414             va_list args;
4415             unsigned int pid;
4416             NV end_time;
4417             char text[MAXPATHLEN*2];
4418             int len;
4419              
4420 994           va_start(args, tag);
4421              
4422 994 50         pid = va_arg(args, unsigned int);
4423 994 50         end_time = va_arg(args, NV);
4424              
4425 994           va_end(args);
4426              
4427 994           state->profiler_end_time = end_time;
4428              
4429 994           len = sprintf(text, "%d", pid);
4430 994 50         if (!hv_delete(state->live_pids_hv, text, len, 0))
4431 0           logwarn("Inconsistent pids in profile data (pid %d not introduced)\n",
4432             pid);
4433 994 50         if (trace_level)
4434 0           logwarn("End of profile data for pid %s (%" IVdf " remaining) at %" NVff "\n", text,
4435 0 0         (IV)HvKEYS(state->live_pids_hv), state->profiler_end_time);
4436              
4437 994           store_attrib_sv(aTHX_ state->attr_hv, STR_WITH_LEN("profiler_end_time"),
4438             newSVnv(end_time));
4439 994           state->profiler_duration += state->profiler_end_time - state->profiler_start_time;
4440 994           store_attrib_sv(aTHX_ state->attr_hv, STR_WITH_LEN("profiler_duration"),
4441             newSVnv(state->profiler_duration));
4442              
4443 994           }
4444              
4445             static void
4446 8946           load_attribute_callback(Loader_state_base *cb_data, const int tag, ...)
4447             {
4448 8946           Loader_state_profiler *state = (Loader_state_profiler *)cb_data;
4449             dTHXa(state->interp);
4450             va_list args;
4451             char *key;
4452             unsigned long key_len;
4453             unsigned int key_utf8;
4454             char *value;
4455             unsigned long value_len;
4456             unsigned int value_utf8;
4457              
4458 8946           va_start(args, tag);
4459              
4460 8946 50         key = va_arg(args, char *);
4461 8946 50         key_len = va_arg(args, unsigned long);
4462 8946 50         key_utf8 = va_arg(args, unsigned int);
4463              
4464 8946 50         value = va_arg(args, char *);
4465 8946 50         value_len = va_arg(args, unsigned long);
4466 8946 50         value_utf8 = va_arg(args, unsigned int);
4467              
4468 8946           va_end(args);
4469              
4470 8946 50         store_attrib_sv(aTHX_ state->attr_hv, key,
    50          
4471 0           key_utf8 ? -(I32)key_len : key_len,
4472             newSVpvn_flags(value, value_len,
4473             value_utf8 ? SVf_UTF8 : 0));
4474 8946           }
4475              
4476             static void
4477 17892           load_option_callback(Loader_state_base *cb_data, const int tag, ...)
4478             {
4479 17892           Loader_state_profiler *state = (Loader_state_profiler *)cb_data;
4480             dTHXa(state->interp);
4481             va_list args;
4482             char *key;
4483             unsigned long key_len;
4484             unsigned int key_utf8;
4485             char *value;
4486             unsigned long value_len;
4487             unsigned int value_utf8;
4488             SV *value_sv;
4489              
4490 17892           va_start(args, tag);
4491              
4492 17892 50         key = va_arg(args, char *);
4493 17892 50         key_len = va_arg(args, unsigned long);
4494 17892 50         key_utf8 = va_arg(args, unsigned int);
4495              
4496 17892 50         value = va_arg(args, char *);
4497 17892 50         value_len = va_arg(args, unsigned long);
4498 17892 50         value_utf8 = va_arg(args, unsigned int);
4499              
4500 17892           va_end(args);
4501              
4502 17892 50         value_sv = newSVpvn_flags(value, value_len, value_utf8 ? SVf_UTF8 : 0);
4503 17892 50         (void)hv_store(state->option_hv, key, key_utf8 ? -(I32)key_len : key_len, value_sv, 0);
4504 17892 50         if (trace_level >= 1)
4505 0 0         logwarn("! %.*s = '%s'\n", (int) key_len, key, SvPV_nolen(value_sv));
4506 17892           }
4507              
4508             struct perl_callback_info_t {
4509             const char *description;
4510             STRLEN len;
4511             const char *args;
4512             };
4513              
4514             static struct perl_callback_info_t callback_info[nytp_tag_max] =
4515             {
4516             {STR_WITH_LEN("[no tag]"), NULL},
4517             {STR_WITH_LEN("VERSION"), "uu"},
4518             {STR_WITH_LEN("ATTRIBUTE"), "33"},
4519             {STR_WITH_LEN("OPTION"), "33"},
4520             {STR_WITH_LEN("COMMENT"), "3"},
4521             {STR_WITH_LEN("TIME_BLOCK"), "iuuuu"},
4522             {STR_WITH_LEN("TIME_LINE"), "iuu"},
4523             {STR_WITH_LEN("DISCOUNT"), ""},
4524             {STR_WITH_LEN("NEW_FID"), "uuuuuuS"},
4525             {STR_WITH_LEN("SRC_LINE"), "uuS"},
4526             {STR_WITH_LEN("SUB_INFO"), "uuus"},
4527             {STR_WITH_LEN("SUB_CALLERS"), "uuunnnuss"},
4528             {STR_WITH_LEN("PID_START"), "uun"},
4529             {STR_WITH_LEN("PID_END"), "un"},
4530             {STR_WITH_LEN("[string]"), NULL},
4531             {STR_WITH_LEN("[string utf8]"), NULL},
4532             {STR_WITH_LEN("START_DEFLATE"), ""},
4533             {STR_WITH_LEN("SUB_ENTRY"), "uu"},
4534             {STR_WITH_LEN("SUB_RETURN"), "unns"}
4535             };
4536              
4537             static void
4538 591275           load_perl_callback(Loader_state_base *cb_data, const int tag, ...)
4539             {
4540 591275           Loader_state_callback *state = (Loader_state_callback *)cb_data;
4541             dTHXa(state->interp);
4542 591275           dSP;
4543             va_list args;
4544 591275           SV **cb_args = state->cb_args;
4545 591275           int i = 0;
4546             char type;
4547 591275           const char *arglist = callback_info[tag].args;
4548 591275           const char *const description = callback_info[tag].description;
4549              
4550 591275 50         if (!arglist) {
4551 0 0         if (description)
4552 0           croak("Type '%s' passed to perl callback incorrectly", description);
4553             else
4554 0           croak("Unknown type %d passed to perl callback", tag);
4555             }
4556              
4557 591275 100         if (!state->cb[tag])
4558 574667           return;
4559              
4560 16608 50         if (trace_level >= 9) {
4561 0           logwarn("\tcallback %s[%s] \n", description, arglist);
4562             }
4563              
4564 16608           sv_setuv_mg(state->input_chunk_seqn_sv, state->base_state.input_chunk_seqn);
4565              
4566 16608           va_start(args, tag);
4567              
4568 16608 50         PUSHMARK(SP);
4569              
4570 16608 50         XPUSHs(state->tag_names[tag]);
4571              
4572 64177 100         while ((type = *arglist++)) {
4573 47569           switch(type) {
4574             case 'u':
4575             {
4576 7209 100         unsigned int u = va_arg(args, unsigned int);
4577              
4578 7209           sv_setuv(cb_args[i], u);
4579 7209 50         XPUSHs(cb_args[i++]);
4580 7209           break;
4581             }
4582             case 'i':
4583             {
4584 3 50         I32 i32 = va_arg(args, I32);
4585              
4586 3           sv_setuv(cb_args[i], i32);
4587 3 50         XPUSHs(cb_args[i++]);
4588 3           break;
4589             }
4590             case 'n':
4591             {
4592 14335 50         NV n = va_arg(args, NV);
4593              
4594 14335           sv_setnv(cb_args[i], n);
4595 14335 50         XPUSHs(cb_args[i++]);
4596 14335           break;
4597             }
4598             case 's':
4599             {
4600 7170 100         SV *sv = va_arg(args, SV *);
4601              
4602 7170           sv_setsv(cb_args[i], sv);
4603 7170 50         XPUSHs(cb_args[i++]);
4604 7170           break;
4605             }
4606             case 'S':
4607             {
4608 4 100         SV *sv = va_arg(args, SV *);
4609              
4610 4 50         XPUSHs(sv_2mortal(sv));
4611 4           break;
4612             }
4613             case '3':
4614             {
4615 18848 50         char *p = va_arg(args, char *);
4616 18848 100         unsigned long len = va_arg(args, unsigned long);
4617 18848 100         unsigned int utf8 = va_arg(args, unsigned int);
4618            
4619 18848           sv_setpvn(cb_args[i], p, len);
4620 18848 50         if (utf8)
4621 0           SvUTF8_on(cb_args[i]);
4622             else
4623 18848           SvUTF8_off(cb_args[i]);
4624              
4625 18848 50         XPUSHs(cb_args[i++]);
4626 18848           break;
4627             }
4628              
4629             default:
4630 0           croak("Bad type '%c' in perl callback", type);
4631             }
4632             }
4633 16608           va_end(args);
4634 16608 50         assert(i <= C_ARRAY_LENGTH(state->cb_args));
4635              
4636 16608           PUTBACK;
4637 16608           call_sv((SV *)state->cb[tag], G_DISCARD);
4638             }
4639              
4640              
4641             static loader_callback perl_callbacks[nytp_tag_max] =
4642             {
4643             0,
4644             load_perl_callback,
4645             load_perl_callback,
4646             load_perl_callback,
4647             load_perl_callback,
4648             load_perl_callback,
4649             load_perl_callback,
4650             load_perl_callback,
4651             load_perl_callback,
4652             load_perl_callback,
4653             load_perl_callback,
4654             load_perl_callback,
4655             load_perl_callback,
4656             load_perl_callback,
4657             load_perl_callback,
4658             load_perl_callback,
4659             load_perl_callback,
4660             load_perl_callback,
4661             load_perl_callback
4662             };
4663             static loader_callback processing_callbacks[nytp_tag_max] =
4664             {
4665             0,
4666             0, /* version */
4667             load_attribute_callback,
4668             load_option_callback,
4669             0, /* comment */
4670             load_time_callback,
4671             load_time_callback,
4672             load_discount_callback,
4673             load_new_fid_callback,
4674             load_src_line_callback,
4675             load_sub_info_callback,
4676             load_sub_callers_callback,
4677             load_pid_start_callback,
4678             load_pid_end_callback,
4679             0, /* string */
4680             0, /* string utf8 */
4681             0, /* sub entry */
4682             0, /* sub return */
4683             0 /* start deflate */
4684             };
4685              
4686             /**
4687             * Process a profile output file and return the results in a hash like
4688             * { fid_fileinfo => [ [file, other...info ], ... ], # index by [fid]
4689             * fid_line_time => [ [...],[...],.. ] # index by [fid][line]
4690             * }
4691             * The value of each [fid][line] is an array ref containing:
4692             * [ number of calls, total time spent ]
4693             * lines containing string evals also get an extra element
4694             * [ number of calls, total time spent, [...] ]
4695             * which is an reference to an array containing the [calls,time]
4696             * data for each line of the string eval.
4697             */
4698             static void
4699 1343           load_profile_data_from_stream(pTHX_ loader_callback *callbacks,
4700             Loader_state_base *state, NYTP_file in)
4701             {
4702             int file_major, file_minor;
4703              
4704 1343           SV *tmp_str1_sv = newSVpvn("",0);
4705 1343           SV *tmp_str2_sv = newSVpvn("",0);
4706              
4707 1343           size_t buffer_len = MAXPATHLEN * 2;
4708 1343           char *buffer = (char *)safemalloc(buffer_len);
4709              
4710             if (1) {
4711 1343 50         if (!NYTP_gets(in, &buffer, &buffer_len))
4712 0           croak("NYTProf data format error while reading header");
4713 1343 50         if (2 != sscanf(buffer, "NYTProf %d %d\n", &file_major, &file_minor))
4714 0           croak("NYTProf data format error while parsing header");
4715 1343 50         if (file_major != NYTP_FILE_MAJOR_VERSION)
4716 0           croak("NYTProf data format version %d.%d is not supported by NYTProf %s (which expects version %d.%d)",
4717             file_major, file_minor, XS_VERSION, NYTP_FILE_MAJOR_VERSION, NYTP_FILE_MINOR_VERSION);
4718              
4719 1343 50         if (file_minor > NYTP_FILE_MINOR_VERSION)
4720 0           warn("NYTProf data format version %d.%d is newer than that understood by this NYTProf %s, so errors are likely",
4721             file_major, file_minor, XS_VERSION);
4722             }
4723              
4724 1343 100         if (callbacks[nytp_version])
4725 349           callbacks[nytp_version](state, nytp_version, file_major, file_minor);
4726              
4727             while (1) {
4728             /* Loop "forever" until EOF. We can only check the EOF flag *after* we
4729             attempt a read. */
4730             char c;
4731              
4732 2373295 100         if (NYTP_read_unchecked(in, &c, sizeof(c)) != sizeof(c)) {
4733 1343 50         if (NYTP_eof(in))
4734 1343           break;
4735 0           croak("Profile format error '%s' whilst reading tag at %ld (see TROUBLESHOOTING in NYTProf docs)",
4736             NYTP_fstrerror(in), NYTP_tell(in));
4737             }
4738              
4739 2371952           state->input_chunk_seqn++;
4740 2371952 50         if (trace_level >= 9)
4741 0           logwarn("Chunk %lu token is %d ('%c') at %ld%s\n",
4742 0           state->input_chunk_seqn, c, c, NYTP_tell(in)-1,
4743             NYTP_type_of_offset(in));
4744              
4745 2371952           switch (c) {
4746             case NYTP_TAG_DISCOUNT:
4747             {
4748 419324           callbacks[nytp_discount](state, nytp_discount);
4749 2371952           break;
4750             }
4751              
4752             case NYTP_TAG_TIME_LINE: /*FALLTHRU*/
4753             case NYTP_TAG_TIME_BLOCK:
4754             {
4755 1812610           I32 ticks = read_i32(in);
4756 1812610           unsigned int file_num = read_u32(in);
4757 1812610           unsigned int line_num = read_u32(in);
4758 1812610           unsigned int block_line_num = 0;
4759 1812610           unsigned int sub_line_num = 0;
4760 1812610           nytp_tax_index tag = nytp_time_line;
4761              
4762 1812610 50         if (c == NYTP_TAG_TIME_BLOCK) {
4763 1812610           block_line_num = read_u32(in);
4764 1812610           sub_line_num = read_u32(in);
4765 1812610           tag = nytp_time_block;
4766             }
4767              
4768             /* Because it happens that the two "optional" arguments are
4769             last, a single call will work. */
4770 1812610           callbacks[tag](state, tag, ticks, file_num, line_num,
4771             block_line_num, sub_line_num);
4772 1812610           break;
4773             }
4774              
4775             case NYTP_TAG_NEW_FID: /* file */
4776             {
4777             SV *filename_sv;
4778 3251           unsigned int file_num = read_u32(in);
4779 3251           unsigned int eval_file_num = read_u32(in);
4780 3251           unsigned int eval_line_num = read_u32(in);
4781 3251           unsigned int fid_flags = read_u32(in);
4782 3251           unsigned int file_size = read_u32(in);
4783 3251           unsigned int file_mtime = read_u32(in);
4784              
4785 3251           filename_sv = read_str(aTHX_ in, NULL);
4786              
4787 3251           callbacks[nytp_new_fid](state, nytp_new_fid, file_num,
4788             eval_file_num, eval_line_num,
4789             fid_flags, file_size, file_mtime,
4790             filename_sv);
4791 3251           break;
4792             }
4793              
4794             case NYTP_TAG_SRC_LINE:
4795             {
4796 37999           unsigned int file_num = read_u32(in);
4797 37999           unsigned int line_num = read_u32(in);
4798 37999           SV *src = read_str(aTHX_ in, NULL);
4799              
4800 37999           callbacks[nytp_src_line](state, nytp_src_line, file_num,
4801             line_num, src);
4802 37999           break;
4803             }
4804              
4805             case NYTP_TAG_SUB_ENTRY:
4806             {
4807 9247           unsigned int file_num = read_u32(in);
4808 9247           unsigned int line_num = read_u32(in);
4809              
4810 9247 100         if (callbacks[nytp_sub_entry])
4811 2389           callbacks[nytp_sub_entry](state, nytp_sub_entry, file_num, line_num);
4812 9247           break;
4813             }
4814              
4815             case NYTP_TAG_SUB_RETURN:
4816             {
4817 28021           unsigned int depth = read_u32(in);
4818 28021           NV incl_time = read_nv(in);
4819 28021           NV excl_time = read_nv(in);
4820 28021           SV *subname = read_str(aTHX_ in, tmp_str1_sv);
4821              
4822 28021 100         if (callbacks[nytp_sub_return])
4823 7165           callbacks[nytp_sub_return](state, nytp_sub_return, depth, incl_time, excl_time, subname);
4824 28021           break;
4825             }
4826              
4827             case NYTP_TAG_SUB_INFO:
4828             {
4829 9591           unsigned int fid = read_u32(in);
4830 9591           SV *subname_sv = read_str(aTHX_ in, tmp_str1_sv);
4831 9591           unsigned int first_line = read_u32(in);
4832 9591           unsigned int last_line = read_u32(in);
4833              
4834 9591           callbacks[nytp_sub_info](state, nytp_sub_info, fid,
4835             first_line, last_line, subname_sv);
4836 9591           break;
4837             }
4838              
4839             case NYTP_TAG_SUB_CALLERS:
4840             {
4841 10109           unsigned int fid = read_u32(in);
4842 10109           unsigned int line = read_u32(in);
4843 10109           SV *caller_subname_sv = read_str(aTHX_ in, tmp_str2_sv);
4844 10109           unsigned int count = read_u32(in);
4845 10109           NV incl_time = read_nv(in);
4846 10109           NV excl_time = read_nv(in);
4847 10109           NV reci_time = read_nv(in);
4848 10109           unsigned int rec_depth = read_u32(in);
4849 10109           SV *called_subname_sv = read_str(aTHX_ in, tmp_str1_sv);
4850              
4851 10109           callbacks[nytp_sub_callers](state, nytp_sub_callers, fid,
4852             line, count, incl_time, excl_time,
4853             reci_time, rec_depth,
4854             called_subname_sv,
4855             caller_subname_sv);
4856 10109           break;
4857             }
4858              
4859             case NYTP_TAG_PID_START:
4860             {
4861 1343           unsigned int pid = read_u32(in);
4862 1343           unsigned int ppid = read_u32(in);
4863 1343           NV start_time = read_nv(in);
4864              
4865 1343           callbacks[nytp_pid_start](state, nytp_pid_start, pid, ppid,
4866             start_time);
4867 1343           break;
4868             }
4869              
4870             case NYTP_TAG_PID_END:
4871             {
4872 1343           unsigned int pid = read_u32(in);
4873 1343           NV end_time = read_nv(in);
4874              
4875 1343           callbacks[nytp_pid_end](state, nytp_pid_end, pid, end_time);
4876 1343           break;
4877             }
4878              
4879             case NYTP_TAG_ATTRIBUTE:
4880             {
4881             char *value, *key_end;
4882 12087           char *end = NYTP_gets(in, &buffer, &buffer_len);
4883 12087 50         if (NULL == end)
4884             /* probably EOF */
4885 0           croak("Profile format error reading attribute (see TROUBLESHOOTING in NYTProf docs)");
4886 12087           --end; /* End, as returned, points 1 after the \n */
4887 12087 50         if ((NULL == (value = (char *)memchr(buffer, '=', end - buffer)))) {
4888 0           logwarn("attribute malformed '%s'\n", buffer);
4889 0           continue;
4890             }
4891 12087           key_end = value++;
4892              
4893 12087           callbacks[nytp_attribute](state, nytp_attribute, buffer,
4894 12087           (unsigned long)(key_end - buffer),
4895             0, value,
4896 12087           (unsigned long)(end - value), 0);
4897              
4898 12087 100         if (memEQs(buffer, key_end - buffer, "ticks_per_sec")) {
    50          
4899 1343           ticks_per_sec = (unsigned int)atoi(value);
4900             }
4901 10744 100         else if (memEQs(buffer, key_end - buffer, "nv_size")) {
    50          
4902 1343 50         if (sizeof(NV) != atoi(value))
4903 0           croak("Profile data created by incompatible perl config (NV size %d but ours is %d)",
4904             atoi(value), (int)sizeof(NV));
4905             }
4906            
4907 12087           break;
4908             }
4909              
4910             case NYTP_TAG_OPTION:
4911             {
4912             char *value, *key_end;
4913 24174           char *end = NYTP_gets(in, &buffer, &buffer_len);
4914 24174 50         if (NULL == end)
4915             /* probably EOF */
4916 0           croak("Profile format error reading attribute (see TROUBLESHOOTING in NYTProf docs)");
4917 24174           --end; /* end, as returned, points 1 after the \n */
4918 24174 50         if ((NULL == (value = (char *)memchr(buffer, '=', end - buffer)))) {
4919 0           logwarn("option malformed '%s'\n", buffer);
4920 0           continue;
4921             }
4922 24174           key_end = value++;
4923              
4924 24174           callbacks[nytp_option](state, nytp_option, buffer,
4925 24174           (unsigned long)(key_end - buffer),
4926             0, value,
4927 24174           (unsigned long)(end - value), 0);
4928 24174           break;
4929             }
4930              
4931             case NYTP_TAG_COMMENT:
4932             {
4933 2098           char *end = NYTP_gets(in, &buffer, &buffer_len);
4934 2098 50         if (!end)
4935             /* probably EOF */
4936 0           croak("Profile format error reading comment (see TROUBLESHOOTING in NYTProf docs)");
4937              
4938 2098 100         if (callbacks[nytp_comment])
4939 582           callbacks[nytp_comment](state, nytp_comment, buffer,
4940 582           (unsigned long)(end - buffer), 0);
4941              
4942 2098 50         if (trace_level >= 1)
4943 0           logwarn("# %s", buffer); /* includes \n */
4944 2098           break;
4945             }
4946              
4947             case NYTP_TAG_START_DEFLATE:
4948             {
4949             #ifdef HAS_ZLIB
4950 755 100         if (callbacks[nytp_start_deflate]) {
4951 233           callbacks[nytp_start_deflate](state, nytp_start_deflate);
4952             }
4953 755           NYTP_start_inflate(in);
4954             #else
4955             croak("File uses compression but compression is not supported by this build of NYTProf");
4956             #endif
4957 755           break;
4958             }
4959              
4960             default:
4961 0           croak("Profile format error: token %d ('%c'), chunk %lu, pos %ld%s (see TROUBLESHOOTING in NYTProf docs)",
4962 0           c, c, state->input_chunk_seqn, NYTP_tell(in)-1,
4963             NYTP_type_of_offset(in));
4964             }
4965 2371952           }
4966              
4967 1343           sv_free(tmp_str1_sv);
4968 1343           sv_free(tmp_str2_sv);
4969 1343           Safefree(buffer);
4970 1343           }
4971              
4972             static HV*
4973 994           load_profile_to_hv(pTHX_ NYTP_file in)
4974             {
4975             Loader_state_profiler state;
4976             HV *profile_hv;
4977             HV *profile_modes;
4978              
4979 994           Zero(&state, 1, Loader_state_profiler);
4980 994           state.total_stmts_duration = 0.0;
4981 994           state.profiler_start_time = 0.0;
4982 994           state.profiler_end_time = 0.0;
4983 994           state.profiler_duration = 0.0;
4984             #ifdef MULTIPLICITY
4985             state.interp = my_perl;
4986             #endif
4987 994           state.fid_line_time_av = newAV();
4988 994           state.fid_srclines_av = newAV();
4989 994           state.fid_fileinfo_av = newAV();
4990 994           state.sub_subinfo_hv = newHV();
4991 994           state.live_pids_hv = newHV();
4992 994           state.attr_hv = newHV();
4993 994           state.option_hv = newHV();
4994 994           state.file_info_stash = gv_stashpv("Devel::NYTProf::FileInfo", GV_ADDWARN);
4995              
4996 994           av_extend(state.fid_fileinfo_av, 64); /* grow them up front. */
4997 994           av_extend(state.fid_srclines_av, 64);
4998 994           av_extend(state.fid_line_time_av, 64);
4999              
5000 994           load_profile_data_from_stream(aTHX_ processing_callbacks,
5001             (Loader_state_base *)&state, in);
5002              
5003              
5004 994 50         if (HvKEYS(state.live_pids_hv)) {
    50          
5005 0           logwarn("Profile data incomplete, no terminator for %" IVdf " pids %s\n",
5006 0 0         (IV)HvKEYS(state.live_pids_hv),
5007             "(refer to TROUBLESHOOTING in the NYTProf documentation)");
5008 0           store_attrib_sv(aTHX_ state.attr_hv, STR_WITH_LEN("complete"),
5009             &PL_sv_no);
5010             }
5011             else {
5012 994           store_attrib_sv(aTHX_ state.attr_hv, STR_WITH_LEN("complete"),
5013             &PL_sv_yes);
5014             }
5015              
5016 994           sv_free((SV*)state.live_pids_hv);
5017              
5018 994 100         if (state.statement_discount) /* discard unused statement_discount */
5019 212           state.total_stmts_discounted -= state.statement_discount;
5020 994           store_attrib_sv(aTHX_ state.attr_hv, STR_WITH_LEN("total_stmts_measured"),
5021 994           newSVnv(state.total_stmts_measured));
5022 994           store_attrib_sv(aTHX_ state.attr_hv, STR_WITH_LEN("total_stmts_discounted"),
5023 994           newSVnv(state.total_stmts_discounted));
5024 994           store_attrib_sv(aTHX_ state.attr_hv, STR_WITH_LEN("total_stmts_duration"),
5025             newSVnv(state.total_stmts_duration));
5026 994           store_attrib_sv(aTHX_ state.attr_hv, STR_WITH_LEN("total_sub_calls"),
5027 994           newSVnv(state.total_sub_calls));
5028              
5029             if (1) {
5030 994           int show_summary_stats = (trace_level >= 1);
5031              
5032 994 50         if (state.profiler_end_time
5033 994 50         && state.total_stmts_duration > state.profiler_duration * 1.1
5034             /* GetSystemTimeAsFiletime/gettimeofday_nv on Win32 have 15.625 ms resolution
5035             by default. 1 ms best case scenario if you use special options which Perl
5036             land doesn't use, and MS strongly discourages in
5037             "Timers, Timer Resolution, and Development of Efficient Code". So for short
5038             programs profiler_duration winds up being 0. If necessery, in the future
5039             profiler_duration could be set to 15.625 ms automatically on NYTProf start
5040             because of the argument that a process can not execute in 0 ms according to
5041             the laws of space and time, or at "the end" if profiler_duration is 0.0, set
5042             it to 15.625 ms*/
5043             #ifdef HAS_QPC
5044             && state.profiler_duration != 0.0
5045             #endif
5046             ) {
5047 0           logwarn("The sum of the statement timings is %.1" NVff "%% of the total time profiling."
5048             " (Values slightly over 100%% can be due simply to cumulative timing errors,"
5049             " whereas larger values can indicate a problem with the clock used.)\n",
5050 0           state.total_stmts_duration / state.profiler_duration * 100);
5051 0           show_summary_stats = 1;
5052             }
5053              
5054 994 50         if (show_summary_stats)
5055 0           logwarn("Summary: statements profiled %lu (=%lu-%lu), sum of time %" NVff "s, profile spanned %" NVff "s\n",
5056 0           (unsigned long)(state.total_stmts_measured - state.total_stmts_discounted),
5057 0           (unsigned long)state.total_stmts_measured, (unsigned long)state.total_stmts_discounted,
5058             state.total_stmts_duration,
5059 0           state.profiler_end_time - state.profiler_start_time);
5060             }
5061              
5062 994           profile_hv = newHV();
5063 994           profile_modes = newHV();
5064 994           (void)hv_stores(profile_hv, "attribute",
5065             newRV_noinc((SV*)state.attr_hv));
5066 994           (void)hv_stores(profile_hv, "option",
5067             newRV_noinc((SV*)state.option_hv));
5068 994           (void)hv_stores(profile_hv, "fid_fileinfo",
5069             newRV_noinc((SV*)state.fid_fileinfo_av));
5070 994           (void)hv_stores(profile_hv, "fid_srclines",
5071             newRV_noinc((SV*)state.fid_srclines_av));
5072 994           (void)hv_stores(profile_hv, "fid_line_time",
5073             newRV_noinc((SV*)state.fid_line_time_av));
5074 994           (void)hv_stores(profile_modes, "fid_line_time", newSVpvs("line"));
5075 994 100         if (state.fid_block_time_av) {
5076 966           (void)hv_stores(profile_hv, "fid_block_time",
5077             newRV_noinc((SV*)state.fid_block_time_av));
5078 966           (void)hv_stores(profile_modes, "fid_block_time", newSVpvs("block"));
5079             }
5080 994 100         if (state.fid_sub_time_av) {
5081 966           (void)hv_stores(profile_hv, "fid_sub_time",
5082             newRV_noinc((SV*)state.fid_sub_time_av));
5083 966           (void)hv_stores(profile_modes, "fid_sub_time", newSVpvs("sub"));
5084             }
5085 994           (void)hv_stores(profile_hv, "sub_subinfo",
5086             newRV_noinc((SV*)state.sub_subinfo_hv));
5087 994           (void)hv_stores(profile_hv, "profile_modes",
5088             newRV_noinc((SV*)profile_modes));
5089 994           return profile_hv;
5090             }
5091              
5092             static void
5093 349           load_profile_to_callback(pTHX_ NYTP_file in, SV *cb)
5094             {
5095             Loader_state_callback state;
5096             int i;
5097 349           HV *cb_hv = NULL;
5098 349           CV *default_cb = NULL;
5099              
5100 349 100         if (SvTYPE(cb) == SVt_PVHV) {
5101             /* A default callback is stored with an empty key. */
5102             SV **svp;
5103              
5104 348           cb_hv = (HV *)cb;
5105 348           svp = hv_fetch(cb_hv, "", 0, 0);
5106              
5107 348 50         if (svp) {
5108 0 0         if (!SvROK(*svp) && SvTYPE(SvRV(*svp)) != SVt_PVCV)
    0          
5109 0           croak("Default callback is not a CODE reference");
5110 348           default_cb = (CV *)SvRV(*svp);
5111             }
5112 1 50         } else if (SvTYPE(cb) == SVt_PVCV) {
5113 1           default_cb = (CV *) cb;
5114             } else
5115 0           croak("Not a CODE or HASH reference");
5116              
5117             #ifdef MULTIPLICITY
5118             state.interp = my_perl;
5119             #endif
5120              
5121 349           state.base_state.input_chunk_seqn = 0;
5122              
5123 349           state.input_chunk_seqn_sv = save_scalar(gv_fetchpv(".", GV_ADD, SVt_IV));
5124              
5125 349           i = C_ARRAY_LENGTH(state.tag_names);
5126 6631 100         while (--i) {
5127 6282 100         if (callback_info[i].args) {
5128             state.tag_names[i]
5129 5584           = newSVpvn_flags(callback_info[i].description,
5130             callback_info[i].len, SVs_TEMP);
5131 5584           SvREADONLY_on(state.tag_names[i]);
5132             /* Don't steal the string buffer. */
5133 5584           SvTEMP_off(state.tag_names[i]);
5134             } else
5135 698           state.tag_names[i] = NULL;
5136              
5137 6282 100         if (cb_hv) {
5138 6264           SV **svp = hv_fetch(cb_hv, callback_info[i].description,
5139             (I32)(callback_info[i].len), 0);
5140              
5141 6264 100         if (svp) {
5142 1044 50         if (!SvROK(*svp) && SvTYPE(SvRV(*svp)) != SVt_PVCV)
    0          
5143 0           croak("Callback for %s is not a CODE reference",
5144             callback_info[i].description);
5145 1044           state.cb[i] = (CV *)SvRV(*svp);
5146             } else
5147 6264           state.cb[i] = default_cb;
5148             } else
5149 18           state.cb[i] = default_cb;
5150             }
5151 4188 100         for (i = 0; i < C_ARRAY_LENGTH(state.cb_args); i++)
5152 3839           state.cb_args[i] = sv_newmortal();
5153              
5154 349           load_profile_data_from_stream(aTHX_ perl_callbacks, (Loader_state_base *)&state,
5155             in);
5156 349           }
5157              
5158             struct int_constants_t {
5159             const char *name;
5160             int value;
5161             };
5162              
5163             static struct int_constants_t int_constants[] = {
5164             /* NYTP_FIDf_* */
5165             {"NYTP_FIDf_IS_PMC", NYTP_FIDf_IS_PMC},
5166             {"NYTP_FIDf_VIA_STMT", NYTP_FIDf_VIA_STMT},
5167             {"NYTP_FIDf_VIA_SUB", NYTP_FIDf_VIA_SUB},
5168             {"NYTP_FIDf_IS_AUTOSPLIT", NYTP_FIDf_IS_AUTOSPLIT},
5169             {"NYTP_FIDf_HAS_SRC", NYTP_FIDf_HAS_SRC},
5170             {"NYTP_FIDf_SAVE_SRC", NYTP_FIDf_SAVE_SRC},
5171             {"NYTP_FIDf_IS_ALIAS", NYTP_FIDf_IS_ALIAS},
5172             {"NYTP_FIDf_IS_FAKE", NYTP_FIDf_IS_FAKE},
5173             {"NYTP_FIDf_IS_EVAL", NYTP_FIDf_IS_EVAL},
5174             /* NYTP_FIDi_* */
5175             {"NYTP_FIDi_FILENAME", NYTP_FIDi_FILENAME},
5176             {"NYTP_FIDi_EVAL_FID", NYTP_FIDi_EVAL_FID},
5177             {"NYTP_FIDi_EVAL_LINE", NYTP_FIDi_EVAL_LINE},
5178             {"NYTP_FIDi_FID", NYTP_FIDi_FID},
5179             {"NYTP_FIDi_FLAGS", NYTP_FIDi_FLAGS},
5180             {"NYTP_FIDi_FILESIZE", NYTP_FIDi_FILESIZE},
5181             {"NYTP_FIDi_FILEMTIME", NYTP_FIDi_FILEMTIME},
5182             {"NYTP_FIDi_PROFILE", NYTP_FIDi_PROFILE},
5183             {"NYTP_FIDi_EVAL_FI", NYTP_FIDi_EVAL_FI},
5184             {"NYTP_FIDi_HAS_EVALS", NYTP_FIDi_HAS_EVALS},
5185             {"NYTP_FIDi_SUBS_DEFINED", NYTP_FIDi_SUBS_DEFINED},
5186             {"NYTP_FIDi_SUBS_CALLED", NYTP_FIDi_SUBS_CALLED},
5187             {"NYTP_FIDi_elements", NYTP_FIDi_elements},
5188             /* NYTP_SIi_* */
5189             {"NYTP_SIi_FID", NYTP_SIi_FID},
5190             {"NYTP_SIi_FIRST_LINE", NYTP_SIi_FIRST_LINE},
5191             {"NYTP_SIi_LAST_LINE", NYTP_SIi_LAST_LINE},
5192             {"NYTP_SIi_CALL_COUNT", NYTP_SIi_CALL_COUNT},
5193             {"NYTP_SIi_INCL_RTIME", NYTP_SIi_INCL_RTIME},
5194             {"NYTP_SIi_EXCL_RTIME", NYTP_SIi_EXCL_RTIME},
5195             {"NYTP_SIi_SUB_NAME", NYTP_SIi_SUB_NAME},
5196             {"NYTP_SIi_PROFILE", NYTP_SIi_PROFILE},
5197             {"NYTP_SIi_REC_DEPTH", NYTP_SIi_REC_DEPTH},
5198             {"NYTP_SIi_RECI_RTIME", NYTP_SIi_RECI_RTIME},
5199             {"NYTP_SIi_CALLED_BY", NYTP_SIi_CALLED_BY},
5200             {"NYTP_SIi_elements", NYTP_SIi_elements},
5201             /* NYTP_SCi_* */
5202             {"NYTP_SCi_CALL_COUNT", NYTP_SCi_CALL_COUNT},
5203             {"NYTP_SCi_INCL_RTIME", NYTP_SCi_INCL_RTIME},
5204             {"NYTP_SCi_EXCL_RTIME", NYTP_SCi_EXCL_RTIME},
5205             {"NYTP_SCi_INCL_TICKS", NYTP_SCi_INCL_TICKS},
5206             {"NYTP_SCi_EXCL_TICKS", NYTP_SCi_EXCL_TICKS},
5207             {"NYTP_SCi_RECI_RTIME", NYTP_SCi_RECI_RTIME},
5208             {"NYTP_SCi_REC_DEPTH", NYTP_SCi_REC_DEPTH},
5209             {"NYTP_SCi_CALLING_SUB", NYTP_SCi_CALLING_SUB},
5210             {"NYTP_SCi_elements", NYTP_SCi_elements},
5211             /* others */
5212             {"NYTP_DEFAULT_COMPRESSION", default_compression_level},
5213             {"NYTP_FILE_MAJOR_VERSION", NYTP_FILE_MAJOR_VERSION},
5214             {"NYTP_FILE_MINOR_VERSION", NYTP_FILE_MINOR_VERSION},
5215             };
5216              
5217             /***********************************
5218             * Perl XS Code Below Here *
5219             ***********************************/
5220              
5221             MODULE = Devel::NYTProf PACKAGE = Devel::NYTProf::Constants
5222              
5223             PROTOTYPES: DISABLE
5224              
5225             BOOT:
5226             {
5227 1348           HV *stash = gv_stashpv("Devel::NYTProf::Constants", GV_ADDWARN);
5228 1348           struct int_constants_t *constant = int_constants;
5229 1348           const struct int_constants_t *end = constant + C_ARRAY_LENGTH(int_constants);
5230              
5231             do {
5232             /* 5.8.x and earlier don't declare newCONSTSUB() as const char *, even
5233             though it is. */
5234 62008           newCONSTSUB(stash, (char *) constant->name, newSViv(constant->value));
5235 62008 100         } while (++constant < end);
5236 1348           newCONSTSUB(stash, "NYTP_ZLIB_VERSION", newSVpv(ZLIB_VERSION, 0));
5237             }
5238              
5239              
5240             MODULE = Devel::NYTProf PACKAGE = Devel::NYTProf::Util
5241              
5242             PROTOTYPES: DISABLE
5243              
5244             void
5245             trace_level()
5246             PPCODE:
5247 32435 50         XSRETURN_IV(trace_level);
5248              
5249              
5250             MODULE = Devel::NYTProf PACKAGE = Devel::NYTProf::Test
5251              
5252             PROTOTYPES: DISABLE
5253              
5254             void
5255             example_xsub(const char *unused="", SV *action=Nullsv, SV *arg=Nullsv)
5256             CODE:
5257             PERL_UNUSED_VAR(unused);
5258 46114 100         if (!action)
5259 46097 50         XSRETURN(0);
5260 17 100         if (SvROK(action) && SvTYPE(SvRV(action))==SVt_PVCV) {
    50          
5261             /* perl <= 5.8.8 doesn't use OP_ENTERSUB so won't be seen by NYTProf */
5262 16 50         PUSHMARK(SP);
5263 16           call_sv(action, G_VOID|G_DISCARD);
5264             }
5265 1 50         else if (strEQ(SvPV_nolen(action),"eval"))
    50          
5266 0 0         eval_pv(SvPV_nolen(arg), TRUE);
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
5267 1 50         else if (strEQ(SvPV_nolen(action),"die"))
    50          
5268 1           croak("example_xsub(die)");
5269 0 0         logwarn("example_xsub: unknown action '%s'\n", SvPV_nolen(action));
5270              
5271             void
5272             example_xsub_eval(...)
5273             CODE:
5274             PERL_UNUSED_VAR(items);
5275             /* to enable testing of string evals in embedded environments
5276             * where there's no caller file information available.
5277             * Only it doesn't actually do that because perl knows
5278             * what it's executing at the time eval_pv() gets called.
5279             * We need a better test, closer to true embedded.
5280             */
5281 0 0         eval_pv("Devel::NYTProf::Test::example_xsub()", 1);
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
5282              
5283              
5284             void
5285             set_errno(int e)
5286             CODE:
5287 1           SETERRNO(e, 0);
5288              
5289              
5290             void
5291             ticks_for_usleep(long u_seconds)
5292             PPCODE:
5293 0           NV elapsed = -1;
5294 0           NV overflow = -1;
5295             #ifdef HAS_SELECT
5296             time_of_day_t s_time;
5297             time_of_day_t e_time;
5298             struct timeval timebuf;
5299 0           timebuf.tv_sec = (long)(u_seconds / 1000000);
5300 0           timebuf.tv_usec = u_seconds - (timebuf.tv_sec * 1000000);
5301 0 0         if (!last_pid)
5302 0           _init_profiler_clock(aTHX);
5303 0           get_time_of_day(s_time);
5304 0           PerlSock_select(0, 0, 0, 0, &timebuf);
5305 0           get_time_of_day(e_time);
5306 0           get_NV_ticks_between(s_time, e_time, elapsed, overflow);
5307             #else
5308             PERL_UNUSED_VAR(u_seconds);
5309             #endif
5310 0 0         EXTEND(SP, 4);
5311 0           PUSHs(sv_2mortal(newSVnv(elapsed)));
5312 0           PUSHs(sv_2mortal(newSVnv(overflow)));
5313 0           PUSHs(sv_2mortal(newSVnv(ticks_per_sec)));
5314 0           PUSHs(sv_2mortal(newSViv(profile_clock)));
5315              
5316              
5317             MODULE = Devel::NYTProf PACKAGE = DB
5318              
5319             PROTOTYPES: DISABLE
5320              
5321             void
5322             DB_profiler(...)
5323             CODE:
5324             /* this sub gets aliased as "DB::DB" by NYTProf.pm if use_db_sub is true */
5325             PERL_UNUSED_VAR(items);
5326 260480 50         if (opt_use_db_sub)
5327 260480           DB_stmt(aTHX_ NULL, PL_op);
5328             else
5329 0           logwarn("DB::DB called unexpectedly\n");
5330              
5331             void
5332             set_option(const char *opt, const char *value)
5333             C_ARGS:
5334             aTHX_ opt, value
5335              
5336             int
5337             init_profiler()
5338             C_ARGS:
5339             aTHX
5340              
5341             int
5342             enable_profile(char *file = NULL)
5343             C_ARGS:
5344             aTHX_ file
5345             POSTCALL:
5346             /* if profiler was previously disabled */
5347             /* then arrange for the enable_profile call to be noted */
5348 64 50         if (!RETVAL) {
5349 64           DB_stmt(aTHX_ PL_curcop, PL_op);
5350             }
5351              
5352              
5353             int
5354             disable_profile()
5355             C_ARGS:
5356             aTHX
5357              
5358             void
5359             finish_profile(...)
5360             ALIAS:
5361             _finish = 1
5362             C_ARGS:
5363             aTHX
5364             INIT:
5365             PERL_UNUSED_ARG(ix);
5366             PERL_UNUSED_ARG(items);
5367              
5368             void
5369             _INIT()
5370             CODE:
5371 537 50         if (profile_start == NYTP_START_INIT) {
5372 537           enable_profile(aTHX_ NULL);
5373             }
5374 0 0         else if (profile_start == NYTP_START_END) {
5375 0           SV *enable_profile_sv = (SV *)get_cv("DB::enable_profile", GV_ADDWARN);
5376 0 0         if (trace_level >= 1)
5377 0           logwarn("~ enable_profile deferred until END\n");
5378 0 0         if (!PL_endav)
5379 0           PL_endav = newAV();
5380 0           av_unshift(PL_endav, 1); /* we want to be first */
5381 0           av_store(PL_endav, 0, SvREFCNT_inc(enable_profile_sv));
5382             }
5383 537           av_extend(PL_endav, av_len(PL_endav)+20); /* see PL_endav in init_profiler() */
5384 537 50         if (trace_level >= 1)
5385 0           logwarn("~ INIT done\n");
5386              
5387             void
5388             _END()
5389             ALIAS:
5390             _CHECK = 1
5391             CODE:
5392             /* we want to END { finish_profile() } but we want it to be the last END
5393             * block run, so we don't push it into PL_endav until END phase has started,
5394             * so it's likely to be the last thing run. Do this once, else we could end
5395             * up in an infinite loop arms race with something else trying the same
5396             * strategy.
5397             */
5398 630           CV *finish_profile_cv = get_cv("DB::finish_profile", GV_ADDWARN);
5399             if (1) { /* defer */
5400 630 50         if (!PL_checkav) PL_checkav = newAV();
5401 630 50         if (!PL_endav) PL_endav = newAV();
5402 630 50         av_push((ix == 1 ? PL_checkav : PL_endav), SvREFCNT_inc(finish_profile_cv));
5403             }
5404             else { /* immediate */
5405             call_sv((SV *)finish_profile_cv, G_VOID);
5406             }
5407 630 50         if (trace_level >= 1)
5408 0 0         logwarn("~ %s done\n", ix == 1 ? "CHECK" : "END");
5409              
5410              
5411              
5412             MODULE = Devel::NYTProf PACKAGE = Devel::NYTProf::Data
5413              
5414             PROTOTYPES: DISABLE
5415              
5416             HV*
5417             load_profile_data_from_file(file,cb=NULL)
5418             char *file;
5419             SV* cb;
5420             PREINIT:
5421             int result;
5422             NYTP_file in;
5423             CODE:
5424 1343 50         if (trace_level)
5425 0           logwarn("reading profile data from file %s\n", file);
5426 1343           in = NYTP_open(file, "rb");
5427 1343 50         if (in == NULL) {
5428 0           croak("Failed to open input '%s': %s", file, strerror(errno));
5429             }
5430 1343 50         if (cb && SvROK(cb)) {
    100          
5431 349           load_profile_to_callback(aTHX_ in, SvRV(cb));
5432 349           RETVAL = (HV*) &PL_sv_undef;
5433             }
5434             else {
5435 994           RETVAL = load_profile_to_hv(aTHX_ in);
5436             }
5437              
5438 1343 50         if ((result = NYTP_close(in, 0)))
5439 0           logwarn("Error closing profile data file: %s\n", strerror(result));
5440              
5441             OUTPUT:
5442             RETVAL