I've ported my additional DTrace probes to blead perl, and have attached a patch.

This patch adds
**new-sv and del-sv to track Perl allocations,
**main-enter and main-exit to show what part of Perl's execution phase we're in
**load-module-entry and load-module-return to instrument use, require, do.

As you can see from the code in op.c, I have not worked out howto get all the desired information from perl yet - the staggering amount of TLA's is blowing this 1week old Perl hacker's mind a bit.

Any tips and pointers would be appreciated - I'd like to get this merged :)

I've started to document the probes at http://wikis.sun.com/display/DTrace/perl+Provider


Cheers

Sven

--
Professional Wiki Innovation and Support Sven Dowideit - http://DistributedINFORMATION.com A WikiRing Partner http://wikiring.com
Index: perl.c
===================================================================
--- perl.c	(revision 125)
+++ perl.c	(working copy)
@@ -270,11 +270,16 @@
 perl_alloc(void)
 {
     PerlInterpreter *my_perl;
+    
+    MAIN_ENTER_PROBE();
 
     /* Newx() needs interpreter, so call malloc() instead */
     my_perl = (PerlInterpreter*)PerlMem_malloc(sizeof(PerlInterpreter));
 
     S_init_tls_and_interp(my_perl);
+    
+    MAIN_EXIT_PROBE();
+
 #ifndef PERL_TRACK_MEMPOOL
     return (PerlInterpreter *) ZeroD(my_perl, 1, PerlInterpreter);
 #else
@@ -300,6 +305,8 @@
 
     PERL_ARGS_ASSERT_PERL_CONSTRUCT;
 
+    MAIN_ENTER_PROBE();
+
 #ifdef MULTIPLICITY
     init_interp();
     PL_perl_destruct_level = 1;
@@ -456,6 +463,7 @@
     PL_timesbase.tms_cutime = 0;
     PL_timesbase.tms_cstime = 0;
 #endif
+    MAIN_EXIT_PROBE();
 
     ENTER;
 }
@@ -593,6 +601,7 @@
 #ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
     pid_t child;
 #endif
+    MAIN_ENTER_PROBE();
 
     PERL_ARGS_ASSERT_PERL_DESTRUCT;
 #ifndef MULTIPLICITY
@@ -632,7 +641,8 @@
 
     if (CALL_FPTR(PL_threadhook)(aTHX)) {
         /* Threads hook has vetoed further cleanup */
-	PL_veto_cleanup = TRUE;
+        PL_veto_cleanup = TRUE;
+        MAIN_EXIT_PROBE();
         return STATUS_EXIT;
     }
 
@@ -647,12 +657,14 @@
 
 	if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
 	    perror("Debug leaking scalars socketpair failed");
+        MAIN_EXIT_PROBE();
 	    abort();
 	}
 
 	child = fork();
 	if(child == -1) {
 	    perror("Debug leaking scalars fork failed");
+        MAIN_EXIT_PROBE();
 	    abort();
 	}
 	if (!child) {
@@ -681,6 +693,7 @@
 	    f = sysconf(_SC_OPEN_MAX);
 	    if(f < 0) {
 		where = "sysconf failed";
+        MAIN_EXIT_PROBE();
 		goto abort;
 	    }
 	    while (f--) {
@@ -764,6 +777,7 @@
 		    goto abort;
 		}
 	    }
+        MAIN_EXIT_PROBE();
 	    _exit(0);
 	abort:
 	    {
@@ -781,6 +795,7 @@
 		   So sleep a bit to give the parent a fighting chance of
 		   reading the data.  */
 		sleep(2);
+        MAIN_EXIT_PROBE();
 		_exit((got == -1) ? errno : 0);
 	    }
 	    /* End of child.  */
@@ -884,6 +899,7 @@
 	CopSTASH_free(&PL_compiling);
 
 	/* The exit() function will do everything that needs doing. */
+        MAIN_EXIT_PROBE();
         return STATUS_EXIT;
     }
 
@@ -1347,6 +1363,7 @@
 	Safefree(PL_mess_sv);
 	PL_mess_sv = NULL;
     }
+    MAIN_EXIT_PROBE();
     return STATUS_EXIT;
 }
 
@@ -1508,6 +1525,8 @@
     I32 oldscope;
     int ret;
     dJMPENV;
+    
+    MAIN_ENTER_PROBE();
 
     PERL_ARGS_ASSERT_PERL_PARSE;
 #ifndef MULTIPLICITY
@@ -1641,6 +1660,7 @@
 	S_set_caret_X(aTHX);
 	TAINT_NOT;
 	init_postdump_symbols(argc,argv,env);
+    MAIN_EXIT_PROBE();
 	return 0;
     }
 
@@ -1687,6 +1707,7 @@
 	break;
     }
     JMPENV_POP;
+    MAIN_EXIT_PROBE();
     return ret;
 }
 
@@ -2293,6 +2314,7 @@
     int ret = 0;
     dJMPENV;
 
+    MAIN_ENTER_PROBE();
     PERL_ARGS_ASSERT_PERL_RUN;
 #ifndef MULTIPLICITY
     PERL_UNUSED_ARG(my_perl);
@@ -2338,6 +2360,7 @@
     }
 
     JMPENV_POP;
+    MAIN_EXIT_PROBE();
     return ret;
 }
 
@@ -2394,6 +2417,7 @@
 	PL_op = PL_main_start;
 	CALLRUNOPS(aTHX);
     }
+
     my_exit(0);
     /* NOTREACHED */
 }
Index: Makefile.SH
===================================================================
--- Makefile.SH	(revision 125)
+++ Makefile.SH	(working copy)
@@ -624,8 +624,8 @@
 	case "$dtrace_o" in
 	?*)
 		$spitshell >>Makefile <<'!NO!SUBS!'
-$(DTRACE_O): perldtrace.d
-	$(DTRACE) -G -s perldtrace.d -o $(DTRACE_O) $(ndt_obj)
+$(DTRACE_O): perldtrace.d $(DTRACE_H) $(ndt_obj) opmini.o
+	$(DTRACE) -G -s perldtrace.d -o $(DTRACE_O) $(ndt_obj) opmini.o
 
 !NO!SUBS!
 		;;
Index: perldtrace.d
===================================================================
--- perldtrace.d	(revision 125)
+++ perldtrace.d	(working copy)
@@ -1,9 +1,45 @@
 /*
- * Written by Alan Burlinson -- taken from his blog post
+ * Begun by Alan Burlinson -- taken from his blog post
  * at <http://blogs.sun.com/alanbur/date/20050909>.
+ * added to by Sven Dowideit -- 
+ * <http://distributedinformation.com/>
  */
 
 provider perl {
+    /* function, filename, line number */
 	probe sub__entry(char *, char *, int);
+    /* filename, line number */
     probe sub__return(char *, char *, int);
+
+    /* new & delete (perl uses reference counting gc, so there is no 'gc sweep') */
+	/* function, SV* */
+    probe new__sv(void*);
+	/* function, SV* */
+    probe del__sv(void*);
+
+	/* Perl main processing (adds a probe to perl_alloc, perl_construct, perl_parse, perl_run, perl_deconstruct ) */
+	probe main__enter();
+	probe main__exit();
+
+    /* use, require, do */
+	/* function, char* module_name */
+    probe load__module__entry(char *);
+	/* function, char* module_name */
+    probe load__module__return(char *);
 };
+
+
+
+
+
+
+
+
+
+/* need to read up & set..
+#pragma D attributes Evolving/Evolving/Common provider perl provider
+#pragma D attributes Private/Private/Common provider perl module
+#pragma D attributes Private/Private/Common provider perl function
+#pragma D attributes Evolving/Evolving/Common provider perl name
+#pragma D attributes Evolving/Evolving/Common provider perl args
+*/
Index: op.c
===================================================================
--- op.c	(revision 125)
+++ op.c	(working copy)
@@ -3805,6 +3805,19 @@
     OP *pegop = newOP(OP_NULL,0);
 #endif
 
+    char probe_output[256];
+    if (PERL_LOAD_MODULE_ENTRY_ENABLED() || PERL_LOAD_MODULE_RETURN_ENABLED()) {
+        SV * sv = ((SVOP*)idop)->op_sv;
+        if (SvTYPE(sv) == SVt_PV) {
+            snprintf(probe_output, 255,"%s\0",  SvPVX(sv));
+        } else if (SvTYPE(sv) == SVt_NV) { /*looks like this has changed dramatically since 5.8*/
+            /* require 5.6 etc*/
+            snprintf(probe_output, 255,"%f\0",  SvNVX(sv));
+        } else {
+            snprintf(probe_output, 255,"TODO: SV not a ptr/number, its a 0x%x\0",  SvTYPE(sv));
+        }
+    }
+    LOAD_MODULE_ENTRY_PROBE(probe_output);
     PERL_ARGS_ASSERT_UTILIZE;
 
     if (idop->op_type != OP_CONST)
@@ -3904,6 +3917,7 @@
     PL_parser->expect = XSTATE;
     PL_cop_seqmax++; /* Purely for B::*'s benefit */
 
+    LOAD_MODULE_RETURN_PROBE(probe_output);
 #ifdef PERL_MAD
     if (!PL_madskills) {
 	/* FIXME - don't allocate pegop if !PL_madskills */
@@ -3962,6 +3976,7 @@
     OP *veop, *imop;
     OP * const modname = newSVOP(OP_CONST, 0, name);
 
+    LOAD_MODULE_ENTRY_PROBE(SvPVX(name));
     PERL_ARGS_ASSERT_VLOAD_MODULE;
 
     modname->op_private |= OPpCONST_BARE;
@@ -3998,6 +4013,7 @@
     utilize(!(flags & PERL_LOADMOD_DENY), start_subparse(FALSE, 0),
 	    veop, modname, imop);
     LEAVE;
+    LOAD_MODULE_RETURN_PROBE(SvPVX(name));
 }
 
 OP *
@@ -4007,6 +4023,17 @@
     OP *doop;
     GV *gv = NULL;
 
+    char probe_output[256];
+    if (PERL_LOAD_MODULE_ENTRY_ENABLED() || PERL_LOAD_MODULE_RETURN_ENABLED()) {
+        if (term->op_type == OP_CONST) {
+            SV * const sv = ((SVOP*)term)->op_sv;
+            snprintf(probe_output, 255,"%s\0",  SvPVX(sv));
+        } else {
+            /* TODO: the above crashed when its an OP_PADSV (9) */
+            snprintf(probe_output, 255, "TODO: modname not an OP_CONST, its a (%u)", term->op_type);
+        }
+    }
+    LOAD_MODULE_ENTRY_PROBE(probe_output);
     PERL_ARGS_ASSERT_DOFILE;
 
     if (!force_builtin) {
@@ -4026,6 +4053,7 @@
     else {
 	doop = newUNOP(OP_DOFILE, 0, scalar(term));
     }
+    LOAD_MODULE_RETURN_PROBE(probe_output);
     return doop;
 }
 
@@ -7468,6 +7496,21 @@
     dVAR;
     GV* gv = NULL;
 
+
+    char probe_output[256];
+    if (PERL_LOAD_MODULE_ENTRY_ENABLED() || PERL_LOAD_MODULE_RETURN_ENABLED()) {
+        SVOP * const kid = (SVOP*)cUNOPo->op_first;
+        SV * sv = ((SVOP*)kid)->op_sv;
+        if (SvTYPE(sv) == SVt_PV) {
+            snprintf(probe_output, 255,"%s\0",  SvPVX(sv));
+        } else if (SvTYPE(sv) == SVt_NV) { /*looks like this has changed dramatically since 5.8*/
+            /* require 5.6 etc*/
+            snprintf(probe_output, 255,"%f\0",  SvNVX(sv));
+        } else {
+            snprintf(probe_output, 255,"TODO: SV not a ptr/number, its a 0x%x\0",  SvTYPE(sv));
+        }
+    }
+    LOAD_MODULE_ENTRY_PROBE(probe_output);
     PERL_ARGS_ASSERT_CK_REQUIRE;
 
     if (o->op_flags & OPf_KIDS) {	/* Shall we supply missing .pm? */
@@ -7529,9 +7572,11 @@
 							   newGVOP(OP_GV, 0,
 								   gv))))));
 	op_getmad(o,newop,'O');
+        LOAD_MODULE_RETURN_PROBE(probe_output);
 	return newop;
     }
 
+    LOAD_MODULE_RETURN_PROBE(probe_output);
     return ck_fun(o);
 }
 
Index: sv.c
===================================================================
--- sv.c	(revision 125)
+++ sv.c	(working copy)
@@ -259,6 +259,7 @@
     sv->sv_debug_inpad = 0;
     sv->sv_debug_cloned = 0;
     sv->sv_debug_file = PL_curcop ? savepv(CopFILE(PL_curcop)): NULL;
+    NEW_SV_PROBE((sv));
     
     return sv;
 }
@@ -269,11 +270,12 @@
     STMT_START {					\
 	if (PL_sv_root)					\
 	    uproot_SV(p);				\
-	else						\
-	    (p) = S_more_sv(aTHX);			\
+	else                            \
+	    (p) = S_more_sv(aTHX);		\
 	SvANY(p) = 0;					\
 	SvREFCNT(p) = 1;				\
 	SvFLAGS(p) = 0;					\
+    NEW_SV_PROBE((p));               \
     } STMT_END
 #endif
 
@@ -284,6 +286,7 @@
 
 #define del_SV(p) \
     STMT_START {					\
+    DEL_SV_PROBE(p);                 \
 	if (DEBUG_D_TEST)				\
 	    del_sv(p);					\
 	else						\
@@ -321,7 +324,11 @@
 
 #else /* ! DEBUGGING */
 
-#define del_SV(p)   plant_SV(p)
+#define del_SV(p)                   \
+    STMT_START {                    \
+    DEL_SV_PROBE(p);                 \
+    plant_SV(p);                     \
+    } STMT_END
 
 #endif /* DEBUGGING */
 
Index: mydtrace.h
===================================================================
--- mydtrace.h	(revision 125)
+++ mydtrace.h	(working copy)
@@ -23,11 +23,48 @@
 	PERL_SUB_RETURN(func, file, line); 	\
     }
 
+#  define NEW_SV_PROBE(probe_sv_ptr)          \
+    if (PERL_NEW_SV_ENABLED()) {    \
+    	PERL_NEW_SV((void*)(probe_sv_ptr));            \
+    }
+
+#  define DEL_SV_PROBE(probe_sv_ptr)          \
+    if (PERL_DEL_SV_ENABLED()) {    \
+    	PERL_DEL_SV((void*)(probe_sv_ptr));            \
+    }
+
+#  define MAIN_ENTER_PROBE()            \
+    if (PERL_MAIN_ENTER_ENABLED()) {    \
+    	PERL_MAIN_ENTER();              \
+	}
+
+#  define MAIN_EXIT_PROBE()            \
+    if (PERL_MAIN_EXIT_ENABLED()) {    \
+    	PERL_MAIN_EXIT();              \
+	}
+
+#  define LOAD_MODULE_ENTRY_PROBE(probe_module_name_ptr)          \
+    if (PERL_LOAD_MODULE_ENTRY_ENABLED()) {    \
+    	PERL_LOAD_MODULE_ENTRY((probe_module_name_ptr));            \
+    }
+
+#  define LOAD_MODULE_RETURN_PROBE(probe_module_name_ptr)          \
+    if (PERL_LOAD_MODULE_RETURN_ENABLED()) {    \
+    	PERL_LOAD_MODULE_RETURN((probe_module_name_ptr));            \
+    }
+
+
 #else
 
 /* NOPs */
 #  define ENTRY_PROBE(func, file, line)
 #  define RETURN_PROBE(func, file, line)
+#  define NEW_SV_PROBE(probe_sv_ptr)
+#  define DEL_SV_PROBE(probe_sv_ptr)
+#  define MAIN_ENTER_PROBE()
+#  define MAIN_EXIT_PROBE()
+#  define LOAD_MODULE_ENTRY_PROBE(probe_module_name_ptr)
+#  define LOAD_MODULE_RETURN_PROBE(probe_module_name_ptr)
 
 #endif
 
_______________________________________________
dtrace-discuss mailing list
[email protected]

Reply via email to