File Coverage

NYTProf.xs
Criterion Covered Total %
statement 1645 2129 77.2
branch 998 1940 51.4
condition n/a
subroutine n/a
pod n/a
total 2643 4069 64.9


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