e8898cb97b41e0acc02cd01854b99d8fc41b4234
[p5sagit/p5-mst-13.2.git] / ext / Devel / DProf / DProf.xs
1 /* XXX DProf could use some cleanups for PERL_IMPLICIT_CONTEXT */
2
3 #define PERL_POLLUTE
4
5 #include "EXTERN.h"
6 #include "perl.h"
7 #include "XSUB.h"
8
9 /* For older Perls */
10 #ifndef dTHR
11 #  define dTHR int dummy_thr
12 #endif  /* dTHR */ 
13
14 /*#define DBG_SUB 1      */
15 /*#define DBG_TIMER 1    */
16
17 #ifdef DBG_SUB
18 #  define DBG_SUB_NOTIFY(A,B) warn( A, B )
19 #else
20 #  define DBG_SUB_NOTIFY(A,B)  /* nothing */
21 #endif
22
23 #ifdef DBG_TIMER
24 #  define DBG_TIMER_NOTIFY(A) warn( A )
25 #else
26 #  define DBG_TIMER_NOTIFY(A)  /* nothing */
27 #endif
28
29 static U32 dprof_ticks;
30
31 /* HZ == clock ticks per second */
32 #ifdef VMS
33 #  define HZ ((I32)CLK_TCK)
34 #  define DPROF_HZ HZ
35 #  include <starlet.h>  /* prototype for sys$gettim() */
36    clock_t dprof_times(struct tms *bufptr) {
37         clock_t retval;
38         dTHX;
39         /* Get wall time and convert to 10 ms intervals to
40          * produce the return value dprof expects */
41 #  if defined(__DECC) && defined (__ALPHA)
42 #    include <ints.h>
43         uint64 vmstime;
44         _ckvmssts(sys$gettim(&vmstime));
45         vmstime /= 100000;
46         retval = vmstime & 0x7fffffff;
47 #  else
48         /* (Older hw or ccs don't have an atomic 64-bit type, so we
49          * juggle 32-bit ints (and a float) to produce a time_t result
50          * with minimal loss of information.) */
51         long int vmstime[2],remainder,divisor = 100000;
52         _ckvmssts(sys$gettim((unsigned long int *)vmstime));
53         vmstime[1] &= 0x7fff;  /* prevent overflow in EDIV */
54         _ckvmssts(lib$ediv(&divisor,vmstime,(long int *)&retval,&remainder));
55 #  endif
56         /* Fill in the struct tms using the CRTL routine . . .*/
57         times((tbuffer_t *)bufptr);
58         return (clock_t) retval;
59    }
60 #  define Times(ptr) (dprof_times(ptr))
61 #else
62 #  ifndef HZ
63 #    ifdef CLK_TCK
64 #      define HZ ((I32)CLK_TCK)
65 #    else
66 #      define HZ 60
67 #    endif
68 #  endif
69 #  ifdef OS2                            /* times() has significant overhead */
70 #    define Times(ptr) (dprof_times(ptr))
71 #    define INCL_DOSPROFILE
72 #    define INCL_DOSERRORS
73 #    include <os2.h>
74 #    define toLongLong(arg) (*(long long*)&(arg))
75 #    define DPROF_HZ dprof_ticks
76
77 static ULONG frequ;
78 static long long start_cnt;
79 clock_t
80 dprof_times(struct tms *t)
81 {
82     ULONG rc;
83     QWORD cnt;
84     
85     if (!frequ) {
86         if (CheckOSError(DosTmrQueryFreq(&frequ)))
87             croak("DosTmrQueryFreq: %s", SvPV(perl_get_sv("!",TRUE),na));
88         else
89             frequ = frequ/DPROF_HZ;     /* count per tick */
90         if (CheckOSError(DosTmrQueryTime(&cnt)))
91             croak("DosTmrQueryTime: %s",
92                   SvPV(perl_get_sv("!",TRUE),na));
93         start_cnt = toLongLong(cnt);
94     }
95
96     if (CheckOSError(DosTmrQueryTime(&cnt)))
97             croak("DosTmrQueryTime: %s", SvPV(perl_get_sv("!",TRUE),na));
98     t->tms_stime = 0;
99     return (t->tms_utime = (toLongLong(cnt) - start_cnt)/frequ);
100 }
101 #  else
102 #    define Times(ptr) (times(ptr))
103 #    define DPROF_HZ HZ
104 #  endif 
105 #endif
106
107 XS(XS_Devel__DProf_END);        /* used by prof_mark() */
108
109 static PerlIO *fp;      /* pointer to tmon.out file */
110
111 /* Added -JH */
112 static long TIMES_LOCATION=42;/* Where in the file to store the time totals */
113 static int SAVE_STACK = 1<<14;          /* How much data to buffer until */
114                                         /* end of run */
115
116 static int prof_pid;    /* pid of profiled process */
117
118 /* Everything is built on times(2).  See its manpage for a description
119  * of the timings.
120  */
121
122 static
123 struct tms      prof_start,
124                 prof_end;
125
126 static
127 clock_t         rprof_start, /* elapsed real time, in ticks */
128                 rprof_end,
129                 wprof_u, wprof_s, wprof_r;
130
131 union prof_any {
132         clock_t tms_utime;  /* cpu time spent in user space */
133         clock_t tms_stime;  /* cpu time spent in system */
134         clock_t realtime;   /* elapsed real time, in ticks */
135         char *name;
136         U32 id;
137         opcode ptype;
138 };
139
140 typedef union prof_any PROFANY;
141
142 static PROFANY  *profstack;
143 static int      profstack_max = 128;
144 static int      profstack_ix = 0;
145
146 static void
147 prof_dump(opcode ptype, char *name)
148 {
149     if(ptype == OP_LEAVESUB){
150         PerlIO_printf(fp,"- & %s\n", name );
151     } else if(ptype == OP_ENTERSUB) {
152         PerlIO_printf(fp,"+ & %s\n", name );
153     } else if(ptype == OP_DIE) {
154         PerlIO_printf(fp,"/ & %s\n", name );
155     } else {
156         PerlIO_printf(fp,"Profiler unknown prof code %d\n", ptype);
157     }
158     safefree(name);
159 }   
160
161 static void
162 prof_dumpa(opcode ptype, U32 id)
163 {
164     if(ptype == OP_LEAVESUB){
165         PerlIO_printf(fp,"- %"UVxf"\n", (UV)id );
166     } else if(ptype == OP_ENTERSUB) {
167         PerlIO_printf(fp,"+ %"UVxf"\n", (UV)id );
168     } else if(ptype == OP_GOTO) {
169         PerlIO_printf(fp,"* %"UVxf"\n", (UV)id );
170     } else if(ptype == OP_DIE) {
171         PerlIO_printf(fp,"/ %"UVxf"\n", (UV)id );
172     } else {
173         PerlIO_printf(fp,"Profiler unknown prof code %d\n", ptype);
174     }
175 }   
176
177 static void
178 prof_dumps(U32 id, char *pname, char *gname)
179 {
180     PerlIO_printf(fp,"& %"UVxf" %s %s\n", (UV)id, pname, gname);
181 }   
182
183 static clock_t otms_utime, otms_stime, orealtime;
184
185 static void
186 prof_dumpt(long tms_utime, long tms_stime, long realtime)
187 {
188     PerlIO_printf(fp,"@ %ld %ld %ld\n", tms_utime, tms_stime, realtime);
189 }   
190
191 static void
192 prof_dump_until(long ix)
193 {
194     long base = 0;
195     struct tms t1, t2;
196     clock_t realtime1, realtime2;
197
198     realtime1 = Times(&t1);
199
200     while( base < ix ){
201         opcode ptype = profstack[base++].ptype;
202         if (ptype == OP_TIME) {
203             long tms_utime = profstack[base++].tms_utime;
204             long tms_stime = profstack[base++].tms_stime;
205             long realtime = profstack[base++].realtime;
206
207             prof_dumpt(tms_utime, tms_stime, realtime);
208         } else if (ptype == OP_GV) {
209             U32 id = profstack[base++].id;
210             char *pname = profstack[base++].name;
211             char *gname = profstack[base++].name;
212
213             prof_dumps(id, pname, gname);
214         } else {
215 #ifdef PERLDBf_NONAME
216             U32 id = profstack[base++].id;
217             prof_dumpa(ptype, id);
218 #else
219             char *name = profstack[base++].name;
220             prof_dump(ptype, name);
221 #endif 
222         }
223     }
224     PerlIO_flush(fp);
225     realtime2 = Times(&t2);
226     if (realtime2 != realtime1 || t1.tms_utime != t2.tms_utime
227         || t1.tms_stime != t2.tms_stime) {
228         wprof_r += realtime2 - realtime1;
229         wprof_u += t2.tms_utime - t1.tms_utime;
230         wprof_s += t2.tms_stime - t1.tms_stime;
231
232         PerlIO_printf(fp,"+ & Devel::DProf::write\n" );
233         PerlIO_printf(fp,"@ %"IVdf" %"IVdf" %"IVdf"\n", 
234                       /* The (IV) casts are one possibility:
235                        * the Painfully Correct Way would be to
236                        * have Clock_t_f. */
237                       (IV)(t2.tms_utime - t1.tms_utime),
238                       (IV)(t2.tms_stime - t1.tms_stime), 
239                       (IV)(realtime2 - realtime1));
240         PerlIO_printf(fp,"- & Devel::DProf::write\n" );
241         otms_utime = t2.tms_utime;
242         otms_stime = t2.tms_stime;
243         orealtime = realtime2;
244         PerlIO_flush(fp);
245     }
246 }
247
248 static HV* cv_hash;
249 static U32 total = 0;
250
251 static void
252 prof_mark( opcode ptype )
253 {
254         struct tms t;
255         clock_t realtime, rdelta, udelta, sdelta;
256         char *name, *pv;
257         char *hvname;
258         STRLEN len;
259         SV *sv;
260         U32 id;
261         SV *Sub = GvSV(DBsub);       /* name of current sub */
262
263         if( SAVE_STACK ){
264                 if( profstack_ix + 5 > profstack_max ){
265                         profstack_max = profstack_max * 3 / 2;
266                         Renew( profstack, profstack_max, PROFANY );
267                 }
268         }
269
270         realtime = Times(&t);
271         rdelta = realtime - orealtime;
272         udelta = t.tms_utime - otms_utime;
273         sdelta = t.tms_stime - otms_stime;
274         if (rdelta || udelta || sdelta) {
275             if (SAVE_STACK) {
276                 profstack[profstack_ix++].ptype = OP_TIME;
277                 profstack[profstack_ix++].tms_utime = udelta;
278                 profstack[profstack_ix++].tms_stime = sdelta;
279                 profstack[profstack_ix++].realtime = rdelta;
280             } else { /* Write it to disk now so's not to eat up core */
281                 if (prof_pid == (int)getpid()) {
282                     prof_dumpt(udelta, sdelta, rdelta);
283                     PerlIO_flush(fp);
284                 }
285             }
286             orealtime = realtime;
287             otms_stime = t.tms_stime;
288             otms_utime = t.tms_utime;
289         }
290
291 #ifdef PERLDBf_NONAME
292         {
293             dTHX;
294             SV **svp;
295             char *gname, *pname;
296             static U32 lastid;
297             CV *cv;
298
299             cv = INT2PTR(CV*,SvIVX(Sub));
300             svp = hv_fetch(cv_hash, (char*)&cv, sizeof(CV*), TRUE);
301             if (!SvOK(*svp)) {
302                 GV *gv = CvGV(cv);
303                     
304                 sv_setiv(*svp, id = ++lastid);
305                 pname = ((GvSTASH(gv) && HvNAME(GvSTASH(gv))) 
306                          ? HvNAME(GvSTASH(gv)) 
307                          : "(null)");
308                 gname = GvNAME(gv);
309                 if (CvXSUB(cv) == XS_Devel__DProf_END)
310                     return;
311                 if (SAVE_STACK) { /* Store it for later recording  -JH */
312                     profstack[profstack_ix++].ptype = OP_GV;
313                     profstack[profstack_ix++].id = id;
314                     profstack[profstack_ix++].name = pname;
315                     profstack[profstack_ix++].name = gname;
316                 } else { /* Write it to disk now so's not to eat up core */
317
318                     /* Only record the parent's info */
319                     if (prof_pid == (int)getpid()) {
320                         prof_dumps(id, pname, gname);
321                         PerlIO_flush(fp);
322                     } else
323                         perldb = 0;             /* Do not debug the kid. */
324                 }
325             } else {
326                 id = SvIV(*svp);
327             }
328         }
329 #else
330         pv = SvPV( Sub, len );
331
332         if( SvROK(Sub) ){
333                 /* Attempt to make CODE refs slightly identifiable by
334                  * including their package name.
335                  */
336                 sv = (SV*)SvRV(Sub);
337                 if( sv && SvTYPE(sv) == SVt_PVCV ){
338                         if( CvSTASH(sv) ){
339                                 hvname = HvNAME(CvSTASH(sv));
340                         }
341                         else if( CvXSUB(sv) == &XS_Devel__DProf_END ){
342                                 /*warn( "prof_mark() found dprof::end");*/
343                                 return; /* don't profile Devel::DProf::END */
344                         }
345                         else{
346                     croak( "DProf prof_mark() lost on CODE ref %s\n", pv );
347                         }
348                         len += strlen( hvname ) + 2;  /* +2 for ::'s */
349
350                 }
351                 else{
352         croak( "DProf prof_mark() lost on supposed CODE ref %s.\n", pv );
353                 }
354                 name = (char *)safemalloc( len * sizeof(char) + 1 );
355                 strcpy( name, hvname );
356                 strcat( name, "::" );
357                 strcat( name, pv );
358         }
359         else{
360                 if( *(pv+len-1) == 'D' ){
361                         /* It could be an &AUTOLOAD. */
362
363                         /* I measured a bunch of *.pl and *.pm (from Perl
364                          * distribution and other misc things) and found
365                          * 780 fully-qualified names.  They averaged
366                          * about 19 chars each.  Only 1 of those names
367                          * ended with 'D' and wasn't an &AUTOLOAD--it
368                          * was &overload::OVERLOAD.
369                          *    --dmr 2/19/96
370                          */
371
372                         if( strcmp( pv+len-9, ":AUTOLOAD" ) == 0 ){
373                                 /* The sub name is in $AUTOLOAD */
374                                 sv = perl_get_sv( pv, 0 );
375                                 if( sv == NULL ){
376                 croak("DProf prof_mark() lost on AUTOLOAD (%s).\n", pv );
377                                 }
378                                 pv = SvPV( sv, na );
379                                 DBG_SUB_NOTIFY( "  AUTOLOAD(%s)\n", pv );
380                         }
381                 }
382                 name = savepv( pv );
383         }
384 #endif /* PERLDBf_NONAME */
385
386         total++;
387         if (SAVE_STACK) { /* Store it for later recording  -JH */
388             profstack[profstack_ix++].ptype = ptype;
389 #ifdef PERLDBf_NONAME
390             profstack[profstack_ix++].id = id;
391 #else
392             profstack[profstack_ix++].name = name;
393 #endif 
394             /* Only record the parent's info */
395             if (SAVE_STACK < profstack_ix) {
396                 if (prof_pid == (int)getpid())
397                     prof_dump_until(profstack_ix);
398                 else
399                     perldb = 0;         /* Do not debug the kid. */
400                 profstack_ix = 0;
401             }
402         } else { /* Write it to disk now so's not to eat up core */
403
404             /* Only record the parent's info */
405             if (prof_pid == (int)getpid()) {
406 #ifdef PERLDBf_NONAME
407                 prof_dumpa(ptype, id);
408 #else
409                 prof_dump(ptype, name);
410 #endif 
411                 PerlIO_flush(fp);
412             } else
413                 perldb = 0;             /* Do not debug the kid. */
414         }
415 }
416
417 static U32 default_perldb;
418
419 #ifdef PL_NEEDED
420 #  define defstash PL_defstash
421 #endif
422
423 /* Counts overhead of prof_mark and extra XS call. */
424 static void
425 test_time(clock_t *r, clock_t *u, clock_t *s)
426 {
427     dTHR;
428     dTHX;
429     CV *cv = perl_get_cv("Devel::DProf::NONESUCH_noxs", FALSE);
430     int i, j, k = 0;
431     HV *oldstash = curstash;
432     struct tms t1, t2;
433     clock_t realtime1, realtime2;
434     U32 ototal = total;
435     U32 ostack = SAVE_STACK;
436     U32 operldb = perldb;
437
438     SAVE_STACK = 1000000;
439     realtime1 = Times(&t1);
440     
441     while (k < 2) {
442         i = 0;
443             /* Disable debugging of perl_call_sv on second pass: */
444         curstash = (k == 0 ? defstash : debstash);
445         perldb = default_perldb;
446         while (++i <= 100) {
447             j = 0;
448             profstack_ix = 0;           /* Do not let the stack grow */
449             while (++j <= 100) {
450 /*              prof_mark( OP_ENTERSUB ); */
451
452                 PUSHMARK( stack_sp );
453                 perl_call_sv( (SV*)cv, G_SCALAR );
454                 stack_sp--;
455 /*              prof_mark( OP_LEAVESUB ); */
456             }
457         }
458         curstash = oldstash;
459         if (k == 0) {                   /* Put time with debugging */
460             realtime2 = Times(&t2);
461             *r = realtime2 - realtime1;
462             *u = t2.tms_utime - t1.tms_utime;
463             *s = t2.tms_stime - t1.tms_stime;
464         } else {                        /* Subtract time without debug */
465             realtime1 = Times(&t1);
466             *r -= realtime1 - realtime2;
467             *u -= t1.tms_utime - t2.tms_utime;
468             *s -= t1.tms_stime - t2.tms_stime;      
469         }
470         k++;
471     }
472     total = ototal;
473     SAVE_STACK = ostack;
474     perldb = operldb;
475 }
476
477 static void
478 prof_recordheader(void)
479 {
480         clock_t r, u, s;
481
482         /* fp is opened in the BOOT section */
483         PerlIO_printf(fp, "#fOrTyTwO\n" );
484         PerlIO_printf(fp, "$hz=%"IVdf";\n", (IV)DPROF_HZ );
485         PerlIO_printf(fp, "$XS_VERSION='DProf %s';\n", XS_VERSION );
486         PerlIO_printf(fp, "# All values are given in HZ\n" );
487         test_time(&r, &u, &s);
488         PerlIO_printf(fp,
489                       "$over_utime=%"IVdf"; $over_stime=%"IVdf"; $over_rtime=%"IVdf";\n",
490                       /* The (IV) casts are one possibility:
491                        * the Painfully Correct Way would be to
492                        * have Clock_t_f. */
493                       (IV)u, (IV)s, (IV)r);
494         PerlIO_printf(fp, "$over_tests=10000;\n");
495
496         TIMES_LOCATION = PerlIO_tell(fp);
497
498         /* Pad with whitespace. */
499         /* This should be enough even for very large numbers. */
500         PerlIO_printf(fp, "%*s\n", 240 , "");
501
502         PerlIO_printf(fp, "\n");
503         PerlIO_printf(fp, "PART2\n" );
504
505         PerlIO_flush(fp);
506 }
507
508 static void
509 prof_record(void)
510 {
511         /* fp is opened in the BOOT section */
512
513         /* Now that we know the runtimes, fill them in at the recorded
514            location -JH */
515
516         clock_t r, u, s;
517     
518         if(SAVE_STACK){
519             prof_dump_until(profstack_ix);
520         }
521         PerlIO_seek(fp, TIMES_LOCATION, SEEK_SET);
522         /* Write into reserved 240 bytes: */
523         PerlIO_printf(fp,
524                       "$rrun_utime=%"IVdf"; $rrun_stime=%"IVdf"; $rrun_rtime=%"IVdf";",
525                       /* The (IV) casts are one possibility:
526                        * the Painfully Correct Way would be to
527                        * have Clock_t_f. */
528                       (IV)(prof_end.tms_utime-prof_start.tms_utime-wprof_u),
529                       (IV)(prof_end.tms_stime-prof_start.tms_stime-wprof_s),
530                       (IV)(rprof_end-rprof_start-wprof_r) );
531         PerlIO_printf(fp, "\n$total_marks=%"IVdf, (IV)total);
532         
533         PerlIO_close( fp );
534 }
535
536 #define NONESUCH()
537
538 static U32 depth = 0;
539
540 static void
541 check_depth(pTHX_ void *foo)
542 {
543     U32 need_depth = (U32)foo;
544     if (need_depth != depth) {
545         if (need_depth > depth) {
546             warn("garbled call depth when profiling");
547         } else {
548             I32 marks = depth - need_depth;
549
550 /*          warn("Check_depth: got %d, expected %d\n", depth, need_depth); */
551             while (marks--) {
552                 prof_mark( OP_DIE );
553             }
554             depth = need_depth;
555         }
556     }
557 }
558
559 #define for_real
560 #ifdef for_real
561
562 XS(XS_DB_sub)
563 {
564         dXSARGS;
565         dORIGMARK;
566         HV *oldstash = curstash;
567         SV *Sub = GvSV(DBsub);       /* name of current sub */
568
569         SP -= items;
570
571         DBG_SUB_NOTIFY( "XS DBsub(%s)\n", SvPV(Sub, na) );
572
573 #ifndef PERLDBf_NONAME                  /* Was needed on older Perls */
574         sv_setiv( DBsingle, 0 ); /* disable DB single-stepping */
575 #endif 
576
577         SAVEDESTRUCTOR_X(check_depth, (void*)depth);
578         depth++;
579
580         prof_mark( OP_ENTERSUB );
581         PUSHMARK( ORIGMARK );
582
583 #ifdef G_NODEBUG
584         perl_call_sv( INT2PTR(SV*,SvIV(Sub)), GIMME | G_NODEBUG);
585 #else
586         curstash = debstash;    /* To disable debugging of perl_call_sv */
587 #ifdef PERLDBf_NONAME
588         perl_call_sv( (SV*)SvIV(Sub), GIMME );
589 #else
590         perl_call_sv( Sub, GIMME );
591 #endif 
592         curstash = oldstash;
593 #endif 
594
595         prof_mark( OP_LEAVESUB );
596         depth--;
597
598         SPAGAIN;
599         PUTBACK;
600         return;
601 }
602
603 XS(XS_DB_goto)
604 {
605         prof_mark( OP_GOTO );
606         return;
607 }
608
609 #endif /* for_real */
610
611 #ifdef testing
612
613         MODULE = Devel::DProf           PACKAGE = DB
614
615         void
616         sub(...)
617                 PPCODE:
618
619                 dORIGMARK;
620                 HV *oldstash = curstash;
621                 SV *Sub = GvSV(DBsub);       /* name of current sub */
622                 /* SP -= items;  added by xsubpp */
623                 DBG_SUB_NOTIFY( "XS DBsub(%s)\n", SvPV(Sub, na) );
624
625                 sv_setiv( DBsingle, 0 ); /* disable DB single-stepping */
626
627                 prof_mark( OP_ENTERSUB );
628                 PUSHMARK( ORIGMARK );
629
630                 curstash = debstash;    /* To disable debugging of perl_call_sv
631 */
632                 perl_call_sv( Sub, GIMME );
633                 curstash = oldstash;
634
635                 prof_mark( OP_LEAVESUB );
636                 SPAGAIN;
637                 /* PUTBACK;  added by xsubpp */
638
639 #endif /* testing */
640
641 MODULE = Devel::DProf           PACKAGE = Devel::DProf
642
643 void
644 END()
645         PPCODE:
646         if( DBsub ){
647                 /* maybe the process forked--we want only
648                  * the parent's profile.
649                  */
650                 if( prof_pid == (int)getpid() ){
651                         rprof_end = Times(&prof_end);
652                         DBG_TIMER_NOTIFY("Profiler timer is off.\n");
653                         prof_record();
654                 }
655         }
656
657 void
658 NONESUCH()
659
660 BOOT:
661         /* Before we go anywhere make sure we were invoked
662          * properly, else we'll dump core.
663          */
664         if( ! DBsub )
665                 croak("DProf: run perl with -d to use DProf.\n");
666
667         /* When we hook up the XS DB::sub we'll be redefining
668          * the DB::sub from the PM file.  Turn off warnings
669          * while we do this.
670          */
671         {
672                 I32 warn_tmp = dowarn;
673                 dowarn = 0;
674                 newXS("DB::sub", XS_DB_sub, file);
675                 newXS("DB::goto", XS_DB_goto, file);
676                 dowarn = warn_tmp;
677         }
678
679         sv_setiv( DBsingle, 0 ); /* disable DB single-stepping */
680
681         {
682             char *buffer = getenv("PERL_DPROF_BUFFER");
683
684             if (buffer) {
685                 SAVE_STACK = atoi(buffer);
686             }
687
688             buffer = getenv("PERL_DPROF_TICKS");
689
690             if (buffer) {
691                 dprof_ticks = atoi(buffer); /* Used under OS/2 only */
692             } else {
693                 dprof_ticks = HZ;
694             }
695         }
696
697         if( (fp = PerlIO_open( "tmon.out", "w" )) == NULL )
698                 croak("DProf: unable to write tmon.out, errno = %d\n", errno );
699 #ifdef PERLDBf_NONAME
700         default_perldb = PERLDBf_NONAME | PERLDBf_SUB; /* no name needed. */
701 #ifdef PERLDBf_GOTO
702         default_perldb = default_perldb | PERLDBf_GOTO;
703 #endif 
704         cv_hash = newHV();
705 #else
706 #  ifdef PERLDBf_SUB
707         default_perldb = PERLDBf_SUB;           /* debug subroutines only. */
708 #  endif
709 #endif
710         prof_pid = (int)getpid();
711
712         New( 0, profstack, profstack_max, PROFANY );
713
714         prof_recordheader();
715
716         DBG_TIMER_NOTIFY("Profiler timer is on.\n");
717         orealtime = rprof_start = Times(&prof_start);
718         otms_utime = prof_start.tms_utime;
719         otms_stime = prof_start.tms_stime;
720         perldb = default_perldb;