|  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
 | 
99134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 read_str(pTHX_ NYTP_file ifile, SV *sv) {  | 
| 
626
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     STRLEN len;  | 
| 
627
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     char *buf;  | 
| 
628
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     unsigned char tag;  | 
| 
629
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
630
 | 
99134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     NYTP_read(ifile, &tag, sizeof(tag), "string prefix");  | 
| 
631
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
632
 | 
99134
 | 
  
 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
 | 
99134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     len = read_u32(ifile);  | 
| 
637
 | 
99134
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (sv) {  | 
| 
638
 | 
57884
 | 
  
 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
 | 
99134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     SvPOK_on(sv);  | 
| 
644
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
645
 | 
99134
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     buf = SvPV_nolen(sv);  | 
| 
646
 | 
99134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     NYTP_read(ifile, buf, len, "string");  | 
| 
647
 | 
99134
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     SvCUR_set(sv, len);  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
648
 | 
99134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     *SvEND(sv) = '\0';  | 
| 
649
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
650
 | 
99134
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (NYTP_TAG_STRING_UTF8 == tag)  | 
| 
651
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         SvUTF8_on(sv);  | 
| 
652
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
653
 | 
99134
 | 
  
 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
 | 
99134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
1670422
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     while (len--) {  | 
| 
678
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         /* hash * 33 + c */  | 
| 
679
 | 
1627911
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         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
 | 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 eval_prefix(const char *filename, const char *prefix, STRLEN prefix_len) {  | 
| 
690
 | 
214
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (memEQ(filename, prefix, prefix_len)  | 
| 
691
 | 
184
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         && isdigit((int)filename[prefix_len])) {  | 
| 
692
 | 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         const char *s = filename + prefix_len + 1;  | 
| 
693
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
694
 | 
240
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         while (isdigit((int)*s))  | 
| 
695
 | 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             ++s;  | 
| 
696
 | 
184
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (s[0] == ')')  | 
| 
697
 | 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             return s;  | 
| 
698
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
699
 | 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return NULL;  | 
| 
700
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
701
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
702
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 /**  | 
| 
703
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  * Return true if filename looks like an eval  | 
| 
704
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
  */  | 
| 
705
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 static int  | 
| 
706
 | 
4061
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 filename_is_eval(const char *filename, STRLEN filename_len)  | 
| 
707
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
708
 | 
4061
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (filename_len < 6)  | 
| 
709
 | 
157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return 0;  | 
| 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     /* typically "(eval N)[...]" sometimes just "(eval N)" */  | 
| 
711
 | 
3904
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (filename[filename_len - 1] != ']' && filename[filename_len - 1] != ')')  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
712
 | 
3705
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return 0;  | 
| 
713
 | 
199
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (eval_prefix(filename, "(eval ", 6))  | 
| 
714
 | 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return 1;  | 
| 
715
 | 
15
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (eval_prefix(filename, "(re_eval ", 9))  | 
| 
716
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return 1;  | 
| 
717
 | 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
1371648
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 dopopcx_at(pTHX_ PERL_CONTEXT *cxstk, I32 startingblock, UV cx_type_mask)  | 
| 
1279
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
1280
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     I32 i;  | 
| 
1281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     PERL_CONTEXT *cx;  | 
| 
1282
 | 
1371648
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     for (i = startingblock; i >= 0; i--) {  | 
| 
1283
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         UV type_bit;  | 
| 
1284
 | 
1371648
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         cx = &cxstk[i];  | 
| 
1285
 | 
1371648
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         type_bit = 1 << CxTYPE(cx);  | 
| 
1286
 | 
1371648
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (type_bit & cx_type_mask)  | 
| 
1287
 | 
1371648
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             return i;  | 
| 
1288
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1289
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return i;                                     /* == -1 */  | 
| 
1290
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1291
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 static COP *  | 
| 
1294
 | 
1465325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 start_cop_of_context(pTHX_ PERL_CONTEXT *cx)  | 
| 
1295
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
1296
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     OP *start_op, *o;  | 
| 
1297
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     int type;  | 
| 
1298
 | 
1465325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     int trace = 6;  | 
| 
1299
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1300
 | 
1465325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
711165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             start_op = CvSTART(cx->blk_sub.cv);  | 
| 
1309
 | 
711165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             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
 | 
746416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             start_op = cx->blk_loop.my_op->op_redoop;  | 
| 
1331
 | 
746416
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             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
 | 
1465325
 | 
  
 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
 | 
1465325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     o = start_op;  | 
| 
1354
 | 
1465325
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     while ( o && (type = (o->op_type) ? o->op_type : (int)o->op_targ) ) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1355
 | 
1465325
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (type == OP_NEXTSTATE ||  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #if PERL_VERSION < 11  | 
| 
1357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             type == OP_SETSTATE ||  | 
| 
1358
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #endif  | 
| 
1359
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             type == OP_DBSTATE)  | 
| 
1360
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         {  | 
| 
1361
 | 
1399070
 | 
  
 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
 | 
1399070
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             return (COP*)o;  | 
| 
1366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
1367
 | 
66255
 | 
  
 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
 | 
66255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         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
 | 
715171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 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
 | 
715171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     I32 cxix = cxstack_ix;  | 
| 
1408
 | 
715171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     PERL_CONTEXT *cx = NULL;  | 
| 
1409
 | 
715171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     PERL_CONTEXT *ccstack = cxstack;  | 
| 
1410
 | 
715171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     PERL_SI *top_si = PL_curstackinfo;  | 
| 
1411
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1412
 | 
715171
 | 
  
 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
 | 
2086819
 | 
  
 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
 | 
2086819
 | 
  
 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
 | 
2084397
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         cx = &ccstack[cxix];  | 
| 
1435
 | 
2084397
 | 
  
 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
 | 
2084397
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (callback(aTHX_ cx, &cx_type_mask))  | 
| 
1439
 | 
712749
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             return cx;  | 
| 
1440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         /* no joy, look further */  | 
| 
1441
 | 
1371648
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         cxix = dopopcx_at(aTHX_ ccstack, cxix - 1, cx_type_mask);  | 
| 
1442
 | 
1371648
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1443
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return NULL;                                  /* not reached */  | 
| 
1444
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1445
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1446
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1447
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 static int  | 
| 
1448
 | 
1399070
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 _cop_in_same_file(COP *a, COP *b)  | 
| 
1449
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
1450
 | 
1399070
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     int same = 0;  | 
| 
1451
 | 
1399070
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     char *a_file = OutCopFILE(a);  | 
| 
1452
 | 
1399070
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     char *b_file = OutCopFILE(b);  | 
| 
1453
 | 
1399070
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (a_file == b_file)  | 
| 
1454
 | 
797478
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         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
 | 
1399070
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return same;  | 
| 
1460
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1461
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1462
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1463
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 static int  | 
| 
1464
 | 
2084397
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 _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
 | 
2084397
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (CxTYPE(cx) == CXt_SUB) {  | 
| 
1470
 | 
711165
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (PL_debstash && CvSTASH(cx->blk_sub.cv) == PL_debstash)  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1471
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             return 0;                             /* skip subs in DB package */  | 
| 
1472
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1473
 | 
711165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         near_cop = start_cop_of_context(aTHX_ cx);  | 
| 
1474
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1475
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         /* only use the cop if it's in the same file */  | 
| 
1476
 | 
711165
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (_cop_in_same_file(near_cop, PL_curcop_nytprof)) {  | 
| 
1477
 | 
111157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             last_sub_line = CopLINE(near_cop);  | 
| 
1478
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             /* treat sub as a block if we've not found a block yet */  | 
| 
1479
 | 
111157
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             if (!last_block_line)  | 
| 
1480
 | 
25040
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 last_block_line = last_sub_line;  | 
| 
1481
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
1482
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1483
 | 
711165
 | 
  
 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
 | 
711165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return 1;                                 /* stop looking */  | 
| 
1493
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1494
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1495
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     /* NULL, EVAL, LOOP, SUBST, BLOCK context */  | 
| 
1496
 | 
1373232
 | 
  
 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
 | 
1373232
 | 
  
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
 | 
754160
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if ((near_cop = start_cop_of_context(aTHX_ cx)) == NULL)  | 
| 
1505
 | 
66255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return 0;  | 
| 
1506
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1507
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     /* if this context is in a different file... */  | 
| 
1508
 | 
687905
 | 
  
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
 | 
686321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     last_block_line = CopLINE(near_cop);  | 
| 
1524
 | 
686321
 | 
  
 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
 | 
686321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
866752
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 DB_stmt(pTHX_ COP *cop, OP *op)  | 
| 
1564
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
1565
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     int saved_errno;  | 
| 
1566
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     char *file;  | 
| 
1567
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     long elapsed, overflow;  | 
| 
1568
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1569
 | 
866752
 | 
  
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
 | 
856277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     saved_errno = errno;  | 
| 
1577
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1578
 | 
856277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     get_time_of_day(end_time);  | 
| 
1579
 | 
856277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     get_ticks_between(long, start_time, end_time, elapsed, overflow);  | 
| 
1580
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1581
 | 
856277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
856277
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (last_executed_fid) {  | 
| 
1587
 | 
855640
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (profile_blocks)  | 
| 
1588
 | 
715287
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             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
 | 
855640
 | 
  
 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
 | 
856277
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (!cop)  | 
| 
1602
 | 
856213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         cop = PL_curcop_nytprof;  | 
| 
1603
 | 
856277
 | 
  
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
 | 
856277
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     file = OutCopFILE(cop);  | 
| 
1632
 | 
856277
 | 
  
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
 | 
856277
 | 
  
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
 | 
856277
 | 
  
 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
 | 
856277
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (profile_blocks) {  | 
| 
1648
 | 
715896
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         last_block_line = 0;  | 
| 
1649
 | 
715896
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         last_sub_line   = 0;  | 
| 
1650
 | 
715896
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (op) {  | 
| 
1651
 | 
715171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             visit_contexts(aTHX_ ~0, &_check_context);  | 
| 
1652
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
1653
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         /* if we didn't find block or sub scopes then use current line */  | 
| 
1654
 | 
715896
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (!last_block_line) last_block_line = last_executed_line;  | 
| 
1655
 | 
715896
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (!last_sub_line)   last_sub_line   = last_executed_line;  | 
| 
1656
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1657
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1658
 | 
856277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     get_time_of_day(start_time);  | 
| 
1659
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1660
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     /* measure time we've spent measuring so we can discount it */  | 
| 
1661
 | 
856277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     get_ticks_between(long, end_time, start_time, elapsed, overflow);  | 
| 
1662
 | 
856277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     cumulative_overhead_ticks += elapsed;  | 
| 
1663
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1664
 | 
856277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     SETERRNO(saved_errno, 0);  | 
| 
1665
 | 
856277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return;  | 
| 
1666
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
1667
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1668
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1669
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 static void  | 
| 
1670
 | 
243094
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 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
 | 
243094
 | 
  
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
 | 
240935
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     saved_errno = errno;  | 
| 
1691
 | 
240935
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     prev_last_executed_fid  = last_executed_fid;  | 
| 
1692
 | 
240935
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
240935
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
240935
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
240935
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     NYTP_write_discount(out);  | 
| 
1715
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1716
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     /* special cases */  | 
| 
1717
 | 
240935
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (last_executed_line == prev_last_executed_line  | 
| 
1718
 | 
190243
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     &&  last_executed_fid  == prev_last_executed_fid  | 
| 
1719
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     ) {  | 
| 
1720
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         /* XXX OP_UNSTACK needs help */  | 
| 
1721
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
1722
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1723
 | 
240935
 | 
  
 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
 | 
240935
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
857104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 reinit_if_forked(pTHX)  | 
| 
1901
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
1902
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     int open_new_file;  | 
| 
1903
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
1904
 | 
857104
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (getpid() == last_pid)  | 
| 
1905
 | 
857073
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         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
 | 
131103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 subr_entry_destroy(pTHX_ subr_entry_t *subr_entry)  | 
| 
2060
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
2061
 | 
131103
 | 
  
 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
 | 
131103
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (subr_entry->caller_subnam_sv) {  | 
| 
2074
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         sv_free(subr_entry->caller_subnam_sv);  | 
| 
2075
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         subr_entry->caller_subnam_sv = Nullsv;  | 
| 
2076
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
2077
 | 
131103
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (subr_entry->called_subnam_sv) {  | 
| 
2078
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         sv_free(subr_entry->called_subnam_sv);  | 
| 
2079
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         subr_entry->called_subnam_sv = Nullsv;  | 
| 
2080
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
2081
 | 
131103
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (subr_entry->prev_subr_entry_ix <= subr_entry_ix)  | 
| 
2082
 | 
131103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         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
 | 
131103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
2087
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2088
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2089
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 static void  | 
| 
2090
 | 
131103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 incr_sub_inclusive_time(pTHX_ subr_entry_t *subr_entry)  | 
| 
2091
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
2092
 | 
131103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     int saved_errno = errno;  | 
| 
2093
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     char called_subname_pv[NYTP_MAX_SUB_NAME_LEN];  | 
| 
2094
 | 
131103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
131103
 | 
  
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
 | 
131103
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (subr_entry->already_counted) {  | 
| 
2117
 | 
65513
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         subr_entry_destroy(aTHX_ subr_entry);  | 
| 
2118
 | 
65513
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         return;  | 
| 
2119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
2120
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     subr_entry->already_counted++;  | 
| 
2121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     /* statement overheads we've accumulated since we entered the sub */  | 
| 
2123
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     overhead_ticks = cumulative_overhead_ticks - subr_entry->initial_overhead_ticks;  | 
| 
2124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     /* ticks spent in subroutines called by this subroutine */  | 
| 
2125
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     called_sub_ticks = cumulative_subr_ticks - subr_entry->initial_subr_ticks;  | 
| 
2126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2127
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     /* calculate ticks since we entered the sub */  | 
| 
2128
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     get_time_of_day(sub_end_time);  | 
| 
2129
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     get_ticks_between(NV, subr_entry->initial_call_timeofday, sub_end_time, ticks, overflow);  | 
| 
2130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2131
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     incl_subr_ticks = (overflow*ticks_per_sec) + ticks;  | 
| 
2132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     /* subtract statement measurement overheads */  | 
| 
2133
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     incl_subr_ticks -= overhead_ticks;  | 
| 
2134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2135
 | 
65590
 | 
  
 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
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     excl_subr_ticks = incl_subr_ticks - called_sub_ticks;  | 
| 
2147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2148
 | 
65590
 | 
  
 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
 | 
65590
 | 
  
 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
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         p = subr_entry->called_subpkg_pv;  | 
| 
2161
 | 
1127584
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         while (*p)  | 
| 
2162
 | 
1061994
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             *called_subname_pv_end++ = *p++;  | 
| 
2163
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         *called_subname_pv_end++ = ':';  | 
| 
2164
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         *called_subname_pv_end++ = ':';  | 
| 
2165
 | 
65590
 | 
  
 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
 | 
65590
 | 
  
 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
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         memcpy(called_subname_pv_end, p, len + 1);  | 
| 
2175
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         called_subname_pv_end += len;  | 
| 
2176
 | 
65590
 | 
  
 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
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sv_tmp = *hv_fetch(sub_callers_hv, called_subname_pv, (I32)(called_subname_pv_end - called_subname_pv), 1);  | 
| 
2182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2183
 | 
65590
 | 
  
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
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sv_tmp = *hv_fetch((HV*)SvRV(sv_tmp), subr_call_key, subr_call_key_len, 1);  | 
| 
2213
 | 
65590
 | 
  
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
 | 
60737
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         subr_call_av = (AV *)SvRV(sv_tmp);  | 
| 
2230
 | 
60737
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         sv_inc(AvARRAY(subr_call_av)[NYTP_SCi_CALL_COUNT]);  | 
| 
2231
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
2232
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2233
 | 
65590
 | 
  
 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
 | 
65590
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (subr_entry->called_cv_depth <= 1) {  | 
| 
2247
 | 
65558
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         incl_time_sv = *av_fetch(subr_call_av, NYTP_SCi_INCL_TICKS, 1);  | 
| 
2248
 | 
65558
 | 
  
 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
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     excl_time_sv = *av_fetch(subr_call_av, NYTP_SCi_EXCL_TICKS, 1);  | 
| 
2260
 | 
65590
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sv_setnv(excl_time_sv, SvNV(excl_time_sv)+excl_subr_ticks);  | 
| 
2261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2262
 | 
65590
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (opt_calls && out) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2263
 | 
60899
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         NYTP_write_call_return(out, subr_entry->subr_prof_depth, called_subname_pv, incl_subr_ticks, excl_subr_ticks);  | 
| 
2264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
2265
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2266
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     subr_entry_destroy(aTHX_ subr_entry);  | 
| 
2267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2268
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     cumulative_subr_ticks += excl_subr_ticks;  | 
| 
2269
 | 
65590
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     SETERRNO(saved_errno, 0);  | 
| 
2270
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
2271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2272
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 static void         /* wrapper called at scope exit due to save_destructor below */  | 
| 
2273
 | 
81853
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 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
 | 
81853
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     SSize_t save_ix = (SSize_t)PTR2IV(subr_entry_ix_void);  | 
| 
2277
 | 
81853
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     incr_sub_inclusive_time(aTHX_ subr_entry_ix_ptr(save_ix));  | 
| 
2278
 | 
81853
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
2279
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2280
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 static CV *  | 
| 
2282
 | 
109410
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 resolve_sub_to_cv(pTHX_ SV *sv, GV **subname_gv_ptr)  | 
| 
2283
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
2284
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     GV *dummy_gv;  | 
| 
2285
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     HV *stash;  | 
| 
2286
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     CV *cv;  | 
| 
2287
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2288
 | 
109410
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (!subname_gv_ptr)  | 
| 
2289
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         subname_gv_ptr = &dummy_gv;  | 
| 
2290
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     else  | 
| 
2291
 | 
109410
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         *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
 | 
109410
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
4529
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             cv = (CV*)sv;  | 
| 
2333
 | 
4529
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             break;  | 
| 
2334
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         case SVt_PVGV:  | 
| 
2335
 | 
103405
 | 
  
 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
 | 
103405
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             if (!cv)                              /* would autoload in this situation */  | 
| 
2338
 | 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 return NULL;  | 
| 
2339
 | 
103389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             break;  | 
| 
2340
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
2341
 | 
109390
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (cv && !*subname_gv_ptr && CvGV(cv) && isGV_with_GP(CvGV(cv))) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2342
 | 
109390
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         *subname_gv_ptr = CvGV(cv);  | 
| 
2343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
2344
 | 
109410
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 subr_entry_setup(pTHX_ COP *prev_cop, subr_entry_t *clone_subr_entry, OPCODE op_type, SV *subr_sv)  | 
| 
2395
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
2396
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     prev_subr_entry_ix = subr_entry_ix;  | 
| 
2406
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     subr_entry_ix = SSNEWa(sizeof(*subr_entry), MEM_ALIGNBYTES);  | 
| 
2407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2408
 | 
65594
 | 
  
 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
 | 
65594
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     subr_entry = subr_entry_ix_ptr(subr_entry_ix);  | 
| 
2417
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Zero(subr_entry, 1, subr_entry_t);  | 
| 
2418
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2419
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     subr_entry->prev_subr_entry_ix = prev_subr_entry_ix;  | 
| 
2420
 | 
65594
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     caller_subr_entry = subr_entry_ix_ptr(prev_subr_entry_ix);  | 
| 
2421
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     subr_entry->subr_prof_depth = (caller_subr_entry)  | 
| 
2422
 | 
65594
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ? caller_subr_entry->subr_prof_depth+1 : 1;  | 
| 
2423
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2424
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     get_time_of_day(subr_entry->initial_call_timeofday);  | 
| 
2425
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     subr_entry->initial_overhead_ticks = cumulative_overhead_ticks;  | 
| 
2426
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     subr_entry->initial_subr_ticks     = cumulative_subr_ticks;  | 
| 
2427
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
128455
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (op_type == OP_ENTERSUB || op_type == OP_GOTO) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2434
 | 
62861
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         GV *called_gv = Nullgv;  | 
| 
2435
 | 
62861
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         subr_entry->called_cv = resolve_sub_to_cv(aTHX_ subr_sv, &called_gv);  | 
| 
2436
 | 
62861
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (called_gv) {  | 
| 
2437
 | 
62857
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             char *p = HvNAME(GvSTASH(called_gv));  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2438
 | 
62857
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             subr_entry->called_subpkg_pv = p;  | 
| 
2439
 | 
62857
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             subr_entry->called_subnam_sv = newSVpv(GvNAME(called_gv), 0);  | 
| 
2440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2441
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             /* detect calls to POSIX::_exit */  | 
| 
2442
 | 
62857
 | 
  
 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
 | 
62857
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     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
 | 
62861
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         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
 | 
65594
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     file = OutCopFILE(prev_cop);  | 
| 
2507
 | 
131188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     subr_entry->caller_fid = (file == last_executed_fileptr)  | 
| 
2508
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ? last_executed_fid  | 
| 
2509
 | 
65594
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         : get_file_id(aTHX_ file, strlen(file), NYTP_FIDf_VIA_SUB);  | 
| 
2510
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     subr_entry->caller_line = CopLINE(prev_cop);  | 
| 
2511
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2512
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     /* Gather details about the calling subroutine */  | 
| 
2513
 | 
65594
 | 
  
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
 | 
65426
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (profile_findcaller             /* user wants us to calculate each time */  | 
| 
2524
 | 
65426
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     || !caller_subr_entry                     /* we don't have a caller struct */  | 
| 
2525
 | 
63631
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     || !caller_subr_entry->called_subpkg_pv   /* we don't have caller details  */  | 
| 
2526
 | 
63631
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     || !caller_subr_entry->called_subnam_sv  | 
| 
2527
 | 
63631
 | 
  
 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
 | 
63631
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         subr_entry_t *caller_se = caller_subr_entry;  | 
| 
2587
 | 
63631
 | 
  
 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
 | 
63631
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             subr_entry->caller_subpkg_pv = caller_se->called_subpkg_pv;  | 
| 
2600
 | 
63631
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             subr_entry->caller_subnam_sv = SvREFCNT_inc(caller_se->called_subnam_sv);  | 
| 
2601
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
2602
 | 
63631
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         found_caller_by = "(inherited)";  | 
| 
2603
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
2604
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2605
 | 
65594
 | 
  
 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
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     save_destructor_x(incr_sub_inclusive_time_ix, INT2PTR(void *, (IV)subr_entry_ix));  | 
| 
2623
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2624
 | 
65594
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (opt_calls >= 2 && out) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2625
 | 
4625
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         NYTP_write_call_entry(out, subr_entry->caller_fid, subr_entry->caller_line);  | 
| 
2626
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
2627
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2628
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     SETERRNO(saved_errno, 0);  | 
| 
2629
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2630
 | 
65594
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return subr_entry_ix;  | 
| 
2631
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
2632
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2633
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2634
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 static OP *  | 
| 
2635
 | 
68882
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 pp_entersub_profiler(pTHX)  | 
| 
2636
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
2637
 | 
68882
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
76393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 pp_subcall_profiler(pTHX_ int is_slowop)  | 
| 
2648
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
2649
 | 
76393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     int saved_errno = errno;  | 
| 
2650
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     OP *op;  | 
| 
2651
 | 
76393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     COP *prev_cop = PL_curcop;                    /* not PL_curcop_nytprof here */  | 
| 
2652
 | 
76393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
76393
 | 
  
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
 | 
76393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     dSP;  | 
| 
2658
 | 
76393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
76393
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (!profile_subs   /* not profiling subs */  | 
| 
2665
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         /* don't profile if currently disabled */  | 
| 
2666
 | 
76393
 | 
  
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
 | 
66836
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     || (op_type==OP_ENTERSUB && (sub_sv == &PL_sv_yes || sub_sv == DB_CHECK_cv || sub_sv == DB_INIT_cv  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2670
 | 
63881
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                                  || sub_sv == DB_END_cv || sub_sv == DB_fin_cv))  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2671
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         /* don't profile other kinds of goto */  | 
| 
2672
 | 
65626
 | 
  
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
 | 
65594
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (!profile_stmts) {  | 
| 
2684
 | 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         reinit_if_forked(aTHX);  | 
| 
2685
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         CHECK_SAWAMPERSAND(last_executed_fid, last_executed_line);  | 
| 
2686
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
2687
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2688
 | 
65594
 | 
  
 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
 | 
65594
 | 
  
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
 | 
65426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         called_cv = NULL;  | 
| 
2713
 | 
65426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         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
 | 
65426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         SETERRNO(saved_errno, 0);  | 
| 
2723
 | 
65426
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         op = run_original_op(op_type);  | 
| 
2724
 | 
65373
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         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
 | 
65541
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     subr_entry = subr_entry_ix_ptr(this_subr_entry_ix);  | 
| 
2774
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2775
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     /* detect wierdness/corruption */  | 
| 
2776
 | 
65541
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     assert(subr_entry);  | 
| 
2777
 | 
65541
 | 
  
 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
 | 
65541
 | 
  
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
 | 
65509
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (is_slowop) {  | 
| 
2797
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         /* already fully handled by subr_entry_setup */  | 
| 
2798
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
2799
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     else {  | 
| 
2800
 | 
62824
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         char *stash_name = NULL;  | 
| 
2801
 | 
62824
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         const char *is_xs = NULL;  | 
| 
2802
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2803
 | 
62824
 | 
  
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
 | 
62656
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (op != next_op) {   /* have entered a sub */  | 
| 
2809
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             /* use cv of sub we've just entered to get name */  | 
| 
2810
 | 
16107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             called_cv = cxstack[cxstack_ix].blk_sub.cv;  | 
| 
2811
 | 
16107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             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
 | 
62824
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (called_cv && CvGV(called_cv)) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2831
 | 
62824
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             GV *gv = CvGV(called_cv);  | 
| 
2832
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             /* Class::MOP can create CvGV where SvTYPE of GV is SVt_NULL */  | 
| 
2833
 | 
62824
 | 
  
 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
 | 
62824
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 stash_name = HvNAME(GvSTASH(gv));  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2838
 | 
62824
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 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
 | 
62824
 | 
  
 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
 | 
62824
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         subr_entry->called_subpkg_pv = stash_name;  | 
| 
2872
 | 
62824
 | 
  
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
 | 
62824
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         subr_entry->called_cv_depth = (called_cv) ? CvDEPTH(called_cv)+(is_xs?1:0) : 0;  | 
| 
2877
 | 
62824
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         subr_entry->called_cv = called_cv;  | 
| 
2878
 | 
62824
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         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
 | 
65509
 | 
  
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
 | 
65509
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (!profile_subs)  | 
| 
2897
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         subr_entry->already_counted++;  | 
| 
2898
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2899
 | 
65509
 | 
  
 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
 | 
65509
 | 
  
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
 | 
16259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         save_destructor_x(incr_sub_inclusive_time_ix, INT2PTR(void *, (IV)this_subr_entry_ix));  | 
| 
2926
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
2927
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2928
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     skip_sub_profile:  | 
| 
2929
 | 
65541
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     SETERRNO(saved_errno, 0);  | 
| 
2930
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2931
 | 
65541
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return op;  | 
| 
2932
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
2933
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2934
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2935
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 static OP *  | 
| 
2936
 | 
364966
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 pp_stmt_profiler(pTHX)                            /* handles OP_DBSTATE, OP_SETSTATE, etc */  | 
| 
2937
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
2938
 | 
364966
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     OP *op = run_original_op(PL_op->op_type);  | 
| 
2939
 | 
364966
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     DB_stmt(aTHX_ NULL, op);  | 
| 
2940
 | 
364966
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return op;  | 
| 
2941
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
2942
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
2943
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 static OP *  | 
| 
2944
 | 
243070
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 pp_leave_profiler(pTHX)                           /* handles OP_LEAVESUB, OP_LEAVEEVAL, etc */  | 
| 
2945
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
2946
 | 
243070
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     OP *prev_op = PL_op;  | 
| 
2947
 | 
243070
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     OP *op = run_original_op(PL_op->op_type);  | 
| 
2948
 | 
243070
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     DB_leave(aTHX_ op, prev_op);  | 
| 
2949
 | 
243070
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
4012320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 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
 | 
4012320
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     unsigned int fid = (eval_line_num) ? eval_file_num : file_num;  | 
| 
3304
 | 
4012320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     SV *line_time_rvav = *av_fetch(dest_av, fid, 1);  | 
| 
3305
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3306
 | 
4012320
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (!SvROK(line_time_rvav))                   /* autoviv */  | 
| 
3307
 | 
6762
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         sv_setsv(line_time_rvav, newRV_noinc((SV*)newAV()));  | 
| 
3308
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3309
 | 
4012320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     store_profile_line_entry(aTHX_ line_time_rvav, line_num, time, count, fid);  | 
| 
3310
 | 
4012320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
3311
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3313
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 static AV *  | 
| 
3314
 | 
4012320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 store_profile_line_entry(pTHX_ SV *rvav, unsigned int line_num, NV time,  | 
| 
3315
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 int count, unsigned int fid)  | 
| 
3316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
3317
 | 
4012320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     SV *time_rvav = *av_fetch((AV*)SvRV(rvav), line_num, 1);  | 
| 
3318
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     AV *line_av;  | 
| 
3319
 | 
4012320
 | 
  
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
 | 
3986614
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         line_av = (AV*)SvRV(time_rvav);  | 
| 
3333
 | 
3986614
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         time_sv = *av_fetch(line_av, 0, 1);  | 
| 
3334
 | 
3986614
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         sv_setnv(time_sv, time + SvNV(time_sv));  | 
| 
3335
 | 
3986614
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (count) {  | 
| 
3336
 | 
3033284
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             SV *sv = *av_fetch(line_av, 1, 1);  | 
| 
3337
 | 
3033284
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             (count == 1) ? sv_inc(sv) : sv_setiv(sv, (IV)time + SvIV(sv));  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3338
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
3339
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
3340
 | 
4012320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     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
 | 
4458
 | 
  
 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
 | 
4458
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             if (filename_len > 0  | 
| 
3488
 | 
3933
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             &&  filename_is_eval(cached_filename, cached_len)  | 
| 
3489
 | 
110
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             && !filename_is_eval(filename, filename_len)  | 
| 
3490
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             ) {  | 
| 
3491
 | 
52
 | 
  
 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
 | 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 sv_setpvn(pkg_filename_sv, filename, filename_len);  | 
| 
3498
 | 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 continue;  | 
| 
3499
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
3500
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3501
 | 
4406
 | 
  
 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
 | 
4458
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             continue;  | 
| 
3514
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
3515
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3516
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         /* ignore if filename is empty (eg xs) */  | 
| 
3517
 | 
1002
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (!filename_len) {  | 
| 
3518
 | 
260
 | 
  
 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
 | 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             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
 | 
318018
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 load_discount_callback(Loader_state_base *cb_data, const int tag, ...)  | 
| 
3961
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
3962
 | 
318018
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Loader_state_profiler *state = (Loader_state_profiler *)cb_data;  | 
| 
3963
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     PERL_UNUSED_ARG(tag);  | 
| 
3964
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3965
 | 
318018
 | 
  
 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
 | 
318018
 | 
  
 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
 | 
318018
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     ++state->statement_discount;  | 
| 
3972
 | 
318018
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     ++state->total_stmts_discounted;  | 
| 
3973
 | 
318018
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
3974
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3975
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 static void  | 
| 
3976
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 load_time_callback(Loader_state_base *cb_data, const int tag, ...)  | 
| 
3977
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 {  | 
| 
3978
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     Loader_state_profiler *state = (Loader_state_profiler *)cb_data;  | 
| 
3979
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     dTHXa(state->interp);  | 
| 
3980
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     va_list args;  | 
| 
3981
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     char trace_note[80] = "";  | 
| 
3982
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     SV *fid_info_rvav;  | 
| 
3983
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     NV seconds;  | 
| 
3984
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     unsigned int eval_file_num = 0;  | 
| 
3985
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     unsigned int eval_line_num = 0;  | 
| 
3986
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     I32 ticks;  | 
| 
3987
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     unsigned int file_num;  | 
| 
3988
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     unsigned int line_num;  | 
| 
3989
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3990
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     va_start(args, tag);  | 
| 
3991
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3992
 | 
1337440
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     ticks = va_arg(args, I32);  | 
| 
3993
 | 
1337440
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     file_num = va_arg(args, unsigned int);  | 
| 
3994
 | 
1337440
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     line_num = va_arg(args, unsigned int);  | 
| 
3995
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3996
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     seconds = (NV)ticks / ticks_per_sec;  | 
| 
3997
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3998
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     fid_info_rvav = *av_fetch(state->fid_fileinfo_av, file_num, 1);  | 
| 
3999
 | 
1337440
 | 
  
 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
 | 
1337440
 | 
  
 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
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     add_entry(aTHX_ state->fid_line_time_av, file_num, line_num,  | 
| 
4015
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
               seconds, eval_file_num, eval_line_num,  | 
| 
4016
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
               1 - state->statement_discount  | 
| 
4017
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         );  | 
| 
4018
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4019
 | 
1337440
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (tag == nytp_time_block) {  | 
| 
4020
 | 
1337440
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         unsigned int block_line_num = va_arg(args, unsigned int);  | 
| 
4021
 | 
1337440
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         unsigned int sub_line_num = va_arg(args, unsigned int);  | 
| 
4022
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4023
 | 
1337440
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (!state->fid_block_time_av)  | 
| 
4024
 | 
966
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             state->fid_block_time_av = newAV();  | 
| 
4025
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         add_entry(aTHX_ state->fid_block_time_av, file_num, block_line_num,  | 
| 
4026
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 seconds, eval_file_num, eval_line_num,  | 
| 
4027
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 1 - state->statement_discount  | 
| 
4028
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         );  | 
| 
4029
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4030
 | 
1337440
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (!state->fid_sub_time_av)  | 
| 
4031
 | 
966
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             state->fid_sub_time_av = newAV();  | 
| 
4032
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         add_entry(aTHX_ state->fid_sub_time_av, file_num, sub_line_num,  | 
| 
4033
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 seconds, eval_file_num, eval_line_num,  | 
| 
4034
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 1 - state->statement_discount  | 
| 
4035
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         );  | 
| 
4036
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4037
 | 
1337440
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if (trace_level >= 8)  | 
| 
4038
 | 
  
0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             logwarn("\tblock %u, sub %u\n", block_line_num, sub_line_num);  | 
| 
4039
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
4040
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4041
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     va_end(args);  | 
| 
4042
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4043
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     state->total_stmts_measured++;  | 
| 
4044
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     state->total_stmts_duration += seconds;  | 
| 
4045
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     state->statement_discount = 0;  | 
| 
4046
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     state->last_file_num = file_num;  | 
| 
4047
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     state->last_line_num = line_num;  | 
| 
4048
 | 
1337440
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
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
 | 
2357143
 | 
  
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
 | 
2355800
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         state->input_chunk_seqn++;  | 
| 
4744
 | 
2355800
 | 
  
 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
 | 
2355800
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         switch (c) {  | 
| 
4750
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             case NYTP_TAG_DISCOUNT:  | 
| 
4751
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             {  | 
| 
4752
 | 
411164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 callbacks[nytp_discount](state, nytp_discount);  | 
| 
4753
 | 
2355800
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 break;  | 
| 
4754
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
4755
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4756
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             case NYTP_TAG_TIME_LINE:                       /*FALLTHRU*/  | 
| 
4757
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             case NYTP_TAG_TIME_BLOCK:  | 
| 
4758
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             {  | 
| 
4759
 | 
1804522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 I32 ticks = read_i32(in);  | 
| 
4760
 | 
1804522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 unsigned int file_num = read_u32(in);  | 
| 
4761
 | 
1804522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 unsigned int line_num = read_u32(in);  | 
| 
4762
 | 
1804522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 unsigned int block_line_num = 0;  | 
| 
4763
 | 
1804522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 unsigned int sub_line_num = 0;  | 
| 
4764
 | 
1804522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 nytp_tax_index tag = nytp_time_line;  | 
| 
4765
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4766
 | 
1804522
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 if (c == NYTP_TAG_TIME_BLOCK) {  | 
| 
4767
 | 
1804522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     block_line_num = read_u32(in);  | 
| 
4768
 | 
1804522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     sub_line_num = read_u32(in);  | 
| 
4769
 | 
1804522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     tag = nytp_time_block;  | 
| 
4770
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 }  | 
| 
4771
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4772
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 /* Because it happens that the two "optional" arguments are  | 
| 
4773
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                    last, a single call will work.  */  | 
| 
4774
 | 
1804522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 callbacks[tag](state, tag, ticks, file_num, line_num,  | 
| 
4775
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                                block_line_num, sub_line_num);  | 
| 
4776
 | 
1804522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 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
 | 
9289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 unsigned int file_num = read_u32(in);  | 
| 
4812
 | 
9289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 unsigned int line_num = read_u32(in);  | 
| 
4813
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4814
 | 
9289
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 if (callbacks[nytp_sub_entry])  | 
| 
4815
 | 
2389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     callbacks[nytp_sub_entry](state, nytp_sub_entry, file_num, line_num);  | 
| 
4816
 | 
9289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 break;  | 
| 
4817
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
4818
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4819
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             case NYTP_TAG_SUB_RETURN:  | 
| 
4820
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             {  | 
| 
4821
 | 
28075
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 unsigned int depth = read_u32(in);  | 
| 
4822
 | 
28075
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 NV incl_time       = read_nv(in);  | 
| 
4823
 | 
28075
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 NV excl_time       = read_nv(in);  | 
| 
4824
 | 
28075
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 SV *subname = read_str(aTHX_ in, tmp_str1_sv);  | 
| 
4825
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
4826
 | 
28075
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 if (callbacks[nytp_sub_return])  | 
| 
4827
 | 
7165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     callbacks[nytp_sub_return](state, nytp_sub_return, depth, incl_time, excl_time, subname);  | 
| 
4828
 | 
28075
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 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
 | 
2355800
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
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
 | 
32441
 | 
  
 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
 | 
260288
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     if (opt_use_db_sub)  | 
| 
5331
 | 
260288
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         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  |