[kaffe] CVS kaffe (robilad): Small cleanup

Kaffe CVS cvs-commits at kaffe.org
Mon Dec 26 14:14:50 PST 2005


PatchSet 7058 
Date: 2005/12/26 20:06:30
Author: robilad
Branch: HEAD
Tag: (none) 
Log:
Small cleanup

2005-12-26  Dalibor Topic  <robilad at kaffe.org>

        * kaffe/kaffe/main.c,
        kaffe/kaffevm/classMethod.c,
        kaffe/kaffevm/gcFuncs.c,
        kaffe/kaffevm/jit3/machine.c,
        kaffe/xprof/feedback.c,
        kaffe/xprof/xprofiler.c,
        libraries/clib/management/JIT.c:
        Don't include methodCache.h.

Members: 
	ChangeLog:1.4576->1.4577 
	kaffe/kaffe/main.c:1.96->1.97 
	kaffe/kaffevm/classMethod.c:1.150->1.151 
	kaffe/kaffevm/gcFuncs.c:1.81->1.82 
	kaffe/kaffevm/jit3/machine.c:1.79->1.80 
	kaffe/xprof/feedback.c:INITIAL->1.6 
	kaffe/xprof/xprofiler.c:INITIAL->1.9 
	libraries/clib/management/JIT.c:1.9->1.10 

Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.4576 kaffe/ChangeLog:1.4577
--- kaffe/ChangeLog:1.4576	Mon Dec 26 18:31:35 2005
+++ kaffe/ChangeLog	Mon Dec 26 20:06:30 2005
@@ -1,3 +1,14 @@
+2005-12-26  Dalibor Topic  <robilad at kaffe.org>
+
+	* kaffe/kaffe/main.c,
+	kaffe/kaffevm/classMethod.c,
+	kaffe/kaffevm/gcFuncs.c,
+	kaffe/kaffevm/jit3/machine.c,
+	kaffe/xprof/feedback.c,
+	kaffe/xprof/xprofiler.c,
+	libraries/clib/management/JIT.c:
+	Don't include methodCache.h.
+
 2005-12-26  Guilhem Lavaux  <guilhem at kaffe.org>
 
 	* replace/ifaddrs_bsd.c: Initialize ifap in case of error.
Index: kaffe/kaffe/kaffe/main.c
diff -u kaffe/kaffe/kaffe/main.c:1.96 kaffe/kaffe/kaffe/main.c:1.97
--- kaffe/kaffe/kaffe/main.c:1.96	Sun Dec 18 17:35:42 2005
+++ kaffe/kaffe/kaffe/main.c	Mon Dec 26 20:06:33 2005
@@ -36,7 +36,6 @@
 #if defined(KAFFE_FEEDBACK)
 #include "feedback.h"
 #endif
-#include "methodCache.h"
 #include "external.h"
 #include "kaffe_jni.h"
 
Index: kaffe/kaffe/kaffevm/classMethod.c
diff -u kaffe/kaffe/kaffevm/classMethod.c:1.150 kaffe/kaffe/kaffevm/classMethod.c:1.151
--- kaffe/kaffe/kaffevm/classMethod.c:1.150	Thu Dec 22 17:51:23 2005
+++ kaffe/kaffe/kaffevm/classMethod.c	Mon Dec 26 20:06:34 2005
@@ -42,7 +42,6 @@
 #include "md.h"
 #include "jni.h"
 #include "soft.h"
-#include "methodCache.h"
 #include "gcj/gcj.h"
 #include "xprofiler.h"
 #include "debugFile.h"
Index: kaffe/kaffe/kaffevm/gcFuncs.c
diff -u kaffe/kaffe/kaffevm/gcFuncs.c:1.81 kaffe/kaffe/kaffevm/gcFuncs.c:1.82
--- kaffe/kaffe/kaffevm/gcFuncs.c:1.81	Sun Dec 18 17:54:31 2005
+++ kaffe/kaffe/kaffevm/gcFuncs.c	Mon Dec 26 20:06:34 2005
@@ -46,7 +46,6 @@
 #include "jni.h"
 #include "soft.h"
 #include "thread.h"
-#include "methodCache.h"
 #include "jvmpi_kaffe.h"
 #include "methodcalls.h"
 
Index: kaffe/kaffe/kaffevm/jit3/machine.c
diff -u kaffe/kaffe/kaffevm/jit3/machine.c:1.79 kaffe/kaffe/kaffevm/jit3/machine.c:1.80
--- kaffe/kaffe/kaffevm/jit3/machine.c:1.79	Mon Dec 26 18:01:47 2005
+++ kaffe/kaffe/kaffevm/jit3/machine.c	Mon Dec 26 20:06:36 2005
@@ -51,7 +51,6 @@
 #include "soft.h"
 #include "thread.h"
 #include "itypes.h"
-#include "methodCache.h"
 #include "support.h"
 #include "xprofiler.h"
 #if defined(KAFFE_FEEDBACK)
===================================================================
Checking out kaffe/kaffe/xprof/feedback.c
RCS:  /home/cvs/kaffe/kaffe/kaffe/xprof/feedback.c,v
VERS: 1.6
***************
--- /dev/null	Sun Aug  4 19:57:58 2002
+++ kaffe/kaffe/xprof/feedback.c	Mon Dec 26 22:14:49 2005
@@ -0,0 +1,304 @@
+/*
+ * feedback.c
+ * Routines for generating information that can be fed back into kaffe for
+ * future runs.
+ *
+ * Copyright (c) 2000 University of Utah and the Flux Group.
+ * All rights reserved.
+ *
+ * This file is licensed under the terms of the GNU Public License.
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Contributed by the Flux Research Group, Department of Computer Science,
+ * University of Utah, http://www.cs.utah.edu/flux/
+ */
+
+#include "config.h"
+
+#if defined(KAFFE_FEEDBACK)
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "gtypes.h"
+#include "access.h"
+#include "classMethod.h"
+#include "lookup.h"
+#include "support.h"
+#include "debug.h"
+#include "stringSupport.h"
+#include "thread.h"
+#include "external.h"
+
+#include "feedback.h"
+#include "fileSections.h"
+
+/* XXX Temporary for now until we define interface header file that
+ * declares "translate"
+ */
+#if defined(TRANSLATOR)
+#if defined(JIT3)
+#include "jit3/machine.h"
+#else
+#include "jit/machine.h"
+#endif
+#endif
+
+#define FEEDBACKSTACKSIZE 4096
+
+struct section_file *kaffe_feedback_file = 0;
+char *feedback_filename = 0;
+
+int feedbackFile(char *filename)
+{
+	int retval = 0;
+
+	/* Create a section file object to store the feedback information */
+	if( (kaffe_feedback_file = createSectionFile()) )
+	{
+		setSectionFileName(kaffe_feedback_file, filename);
+		/*
+		 * Add an atexit call to syncFeedback so we know the
+		 * information got out
+		 */
+		if( !atexit((void (*)(void))syncFeedback) )
+			retval = 1;
+		else
+		{
+			deleteSectionFile(kaffe_feedback_file);
+			kaffe_feedback_file = 0;
+		}
+	}
+	return( retval );
+}
+
+int syncFeedback(void)
+{
+	int retval = 0;
+
+	if( kaffe_feedback_file && syncSectionFile(kaffe_feedback_file) )
+	{
+		retval = 1;
+	}
+	return( retval );
+}
+
+/*
+ * Function that is called by the sections walker
+ */
+static int feedbackWalker(void *arg,
+			  struct section_file *sf,
+			  struct section_file_data *sfd)
+{
+	int retval = 1;
+
+	/* Check for library section */
+	if( sfd->sfd_type == &lib_section )
+	{
+		struct lib_section_data *lsd = (struct lib_section_data *)sfd;
+
+		if( lsd->lsd_flags & LSDF_PRELOAD )
+			loadNativeLibrary2(sfd->sfd_name, 0, 0, 0);
+	}
+	/* Check for jit-code section */
+	else if( sfd->sfd_type == &jit_section )
+	{
+#if defined(TRANSLATOR)
+		struct jit_section_data *jsd = (struct jit_section_data *)sfd;
+
+		if( jsd->jsd_flags & JSDF_PRECOMPILE )
+		{
+			int len, lpc, sig_start = -1, meth_start = -1;
+			Utf8Const *u8cname, *u8mname, *u8sig;
+			Hjava_lang_Class *cls;
+			char *full_name;
+
+			/*
+			 * Parse the name of the section to get the class,
+			 * method, and signature
+			 */
+			full_name = sfd->sfd_name;
+			len = strlen(full_name);
+			for( lpc = len - 1;
+			     (lpc >= 0) && (meth_start < 0);
+			     lpc-- )
+			{
+				switch( full_name[lpc] )
+				{
+				case '(':
+					sig_start = lpc;
+					break;
+				case '/':
+					if( sig_start > 0 )
+						meth_start = lpc + 1;
+					break;
+				}
+			}
+			if( (sig_start > 0) && (meth_start > 0) )
+			{
+				jobject loader = 0;
+				errorInfo info;
+
+				/* Get the right strings and find the class */
+				u8cname = utf8ConstNew(full_name,
+						       meth_start - 1);
+				u8mname = utf8ConstNew(&full_name[meth_start],
+						       sig_start - meth_start);
+				u8sig = utf8ConstNew(&full_name[sig_start],
+						     len - sig_start);
+				if( u8cname && u8mname && u8sig &&
+				    (cls = loadClass(u8cname, loader, &info)) )
+				{
+					Method *meth;
+
+					if( (meth = findMethodLocal(cls,
+								    u8mname,
+								    u8sig)) &&
+					    !(meth->accflags & ACC_NATIVE) )
+					{
+						if( translate(meth, &info) )
+						{
+						}
+						else
+						{
+							dprintf(
+								"Feedback: "
+								" Precompile "
+								"failed for "
+								"%s!\n",
+								full_name);
+						}
+					}
+					else if( !meth )
+					{
+						dprintf(
+							"Feedback: Didn't "
+							"find method"
+							" %s\n",
+							full_name);
+					}
+				}
+				else
+				{
+					dprintf(
+						"Feedback: Couldn't load "
+						"class %s\n",
+						u8cname->data);
+				}
+				utf8ConstRelease(u8cname);
+				utf8ConstRelease(u8mname);
+				utf8ConstRelease(u8sig);
+			}
+			else
+			{
+				dprintf(
+					"Feedback: Malformed method `%s'\n",
+					full_name);
+			}
+		}
+#else
+		{
+			static int precompile_msg = 0;
+
+			if( !precompile_msg )
+			{
+				precompile_msg = 1;
+				dprintf(
+					"Feedback: Cannot precompile java for "
+					"the interpreter\n");
+			}
+		}
+#endif
+	}
+	return( retval );
+}
+
+static void feedbackRunnable(void *arg)
+{
+	/* Walk over the sections with our function */
+	walkFileSections(kaffe_feedback_file, feedbackWalker, 0);
+}
+
+int processFeedback(void)
+{
+	int retval = 1;
+
+	if( kaffe_feedback_file )
+	{
+		feedbackRunnable(0);
+		retval = 1;
+	}
+	return( retval );
+}
+
+int feedbackJITMethod(char *method, char *address, int size, int precompile)
+{
+	struct section_file_data *sfd;
+	struct jit_section_data *jsd;
+	int retval = 0;
+
+	if( !kaffe_feedback_file )
+		return( 0 );
+	lockMutex(kaffe_feedback_file);
+	if( !(sfd = findSectionInFile(kaffe_feedback_file,
+				      &jit_section, method)) )
+	{
+		/*
+		 * If the section doesn't exist we need to create and add it.
+		 * We only set precompile here since the user might've changed
+		 * the file to specify otherwise.
+		 */
+		if( (sfd = createFileSection(jit_section.fs_name, method,
+					     "precompile", precompile ?
+					     "true" : "false",
+					     NULL)) )
+		{
+			addSectionToFile(kaffe_feedback_file, sfd);
+		}
+	}
+	if( sfd )
+	{
+		/* Set whatever attributes are interesting */
+		jsd = (struct jit_section_data *)sfd;
+		jsd->jsd_address = address;
+		jsd->jsd_size = size;
+		retval = 1;
+	}
+	unlockMutex(kaffe_feedback_file);
+	return( retval );
+}
+
+int feedbackLibrary(char *name, int preload)
+{
+	struct section_file_data *sfd;
+	int retval = 0;
+
+	if( !kaffe_feedback_file )
+		return( 0 );
+	lockMutex(kaffe_feedback_file);
+	if( !(sfd = findSectionInFile(kaffe_feedback_file,
+				      &lib_section, name)) )
+	{
+		/*
+		 * If the section doesn't exist we need to create and add it.
+		 * We only set preload here since the user might've changed
+		 * the file to specify otherwise.
+		 */
+		if( (sfd = createFileSection(lib_section.fs_name, name,
+					     "preload", preload ?
+					     "true" : "false",
+					     NULL)) )
+		{
+			addSectionToFile(kaffe_feedback_file, sfd);
+			retval = 1;
+		}
+	}
+	else
+		retval = 1;
+	unlockMutex(kaffe_feedback_file);
+	return( retval );
+}
+
+#endif /* KAFFE_FEEDBACK */
===================================================================
Checking out kaffe/kaffe/xprof/xprofiler.c
RCS:  /home/cvs/kaffe/kaffe/kaffe/xprof/xprofiler.c,v
VERS: 1.9
***************
--- /dev/null	Sun Aug  4 19:57:58 2002
+++ kaffe/kaffe/xprof/xprofiler.c	Mon Dec 26 22:14:50 2005
@@ -0,0 +1,714 @@
+/*
+ * xprofiler.c
+ * Interface functions to the profiling code
+ *
+ * Copyright (c) 2000, 2001 University of Utah and the Flux Group.
+ * All rights reserved.
+ *
+ * This file is licensed under the terms of the GNU Public License.
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Contributed by the Flux Research Group, Department of Computer Science,
+ * University of Utah, http://www.cs.utah.edu/flux/
+ */
+
+#include "config.h"
+
+#if defined(KAFFE_XPROFILER)
+
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/gmon.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/gmon.h>
+#include <sys/sysctl.h>
+
+#include "gtypes.h"
+#include "md.h"
+#include "xprofile-md.h"
+#include "exception.h"
+#include "kaffe/jmalloc.h"
+
+#include "memorySamples.h"
+#include "feedback.h"
+#include "debugFile.h"
+#include "fileSections.h"
+#include "gmonFile.h"
+#include "callGraph.h"
+#include "xprofiler.h"
+
+/* Variables for figuring out the start and end of the program text */
+extern char _start;
+extern char etext;
+
+int xProfFlag = 0;
+/* Flag used to determine whether or not we should record `hits' */
+static volatile int xProfRecord = 1;
+
+/*
+ * This variable is part of a nasty hack to keep the call graph accounting
+ * code from being credited with time.  The accounting function should set
+ * this variable while its working so that if a profiling interrupt happens
+ * while its executing the appropriate function will be credited.
+ */
+static char * volatile profiler_sample_override_pc = NULL;
+volatile int profiler_sample_overrides = 0;
+
+/* Structures used to hold the profiling information */
+struct memory_samples *kaffe_memory_samples = NULL;
+struct call_graph *kaffe_call_graph = NULL;
+
+/* The name of the output files */
+const char *kaffe_gmon_filename = "xgmon.out";
+const char *kaffe_syms_filename = "kaffe-jit-symbols.s";
+
+/* Debugging file for profiler symbols */
+struct debug_file *profiler_debug_file = NULL;
+static int extraProfileCount = 0;
+
+/* Number of call_arc structures to preallocate */
+#define XPROFILE_ARCS (1024 * 64)
+
+/*
+ * The gutter threshold is used to determine if the gap between two chunks of
+ * observed memory is too large to put into the file.  Since the resulting gap
+ * would just be a bunch of zeros, we split them into different files.
+ */
+#define SAMPLE_GUTTER_THRESHOLD 1024 * 1024 * 5
+
+/* Structure used to track the current gmon file for our walker */
+struct profiler_gmon_file {
+	char *pgf_stage;		/* The name of the current stage */
+	struct gmon_file *pgf_file;	/* The active gmon file structure */
+	long pgf_record;		/* The index of the hist record */
+};
+
+/*
+ * A walker function for walkMemorySamples.  This does a little more than
+ * the one provided by the gmon code since it will create a new gmon file
+ * if theres a large gap in observed memory.
+ */
+static int profilerSampleWalker(void *handle, char *addr,
+				short *bins, size_t size)
+{
+	struct profiler_gmon_file *pgf = handle;
+	struct gmon_file *gf = pgf->pgf_file;
+	int retval = 0;
+
+	/* Check if we need to dump these samples in another file */
+	if( (addr - gf->gf_addr) > SAMPLE_GUTTER_THRESHOLD )
+	{
+		char *filename, *old_high;
+		size_t len;
+
+		old_high = gf->gf_high;
+		/* Rewrite the old record with the new high address */
+		writeGmonRecord(gf,
+				GRA_Rewrite, pgf->pgf_record,
+				GRA_Type, GMON_TAG_TIME_HIST,
+				GRA_LowPC, gf->gf_low,
+				GRA_HighPC, gf->gf_addr,
+				GRA_DONE);
+		writeCallGraph(kaffe_call_graph, gf);
+		/* Close down the file */
+		deleteGmonFile(gf);
+		pgf->pgf_file = 0;
+		gf = 0;
+
+		/*
+		 * Make up the filename for the new file, we'll just use the
+		 * starting address for this range to make it unique
+		 */
+		len = strlen(kaffe_gmon_filename) +
+			1 + /* `.' */
+			2 + (sizeof(void *) * 2) + /* `0x...' */
+			(pgf->pgf_stage ? strlen(pgf->pgf_stage) + 1 : 0) +
+			1;
+		if( (filename = (char *)KMALLOC(len)) )
+		{
+			/* Construct the new file name */
+			sprintf(filename,
+				"%s.%p%s%s",
+				kaffe_gmon_filename,
+				addr,
+				pgf->pgf_stage ? "." : "",
+				pgf->pgf_stage ? pgf->pgf_stage : "");
+			if( (pgf->pgf_file = createGmonFile(filename)) )
+			{
+				gf = pgf->pgf_file;
+				/* Write out another hist record */
+				pgf->pgf_record = writeGmonRecord(
+					gf,
+					GRA_Type, GMON_TAG_TIME_HIST,
+					GRA_LowPC, addr,
+					GRA_HighPC, old_high,
+					GRA_DONE);
+			}
+		}
+	}
+	if( gf )
+	{
+		/* Let the gmon walker do its thing */
+		retval = gmonSampleWalker(gf, addr, bins, size);
+	}
+	memset(bins, 0, size * sizeof(short));
+	return( retval );
+}
+
+/*
+ * Handles any post processing
+ */
+static void profilerAtExit(void)
+{
+	if( !xProfFlag )
+		return;
+	/* We don't care about profiling anymore */
+	disableProfileTimer();
+	/* This is the final stage, write out any data */
+	xProfileStage(0);
+	/* Release everything else */
+	disableXProfiling();
+}
+
+int enableXCallGraph(void)
+{
+	int retval = false;
+
+	if( (kaffe_call_graph = createCallGraph(XPROFILE_ARCS)) )
+	{
+		retval = true;
+	}
+	return( retval );
+}
+
+#if defined(KAFFE_CPROFILER)
+/*
+ * Return the minimum cycles per second for the machine
+ */
+static int hertz(void)
+{
+	struct itimerval value, ovalue;
+	int retval = 0;
+	
+	timerclear(&value.it_interval);
+	timerclear(&value.it_value);
+	timerclear(&ovalue.it_interval);
+	timerclear(&ovalue.it_value);
+	value.it_interval.tv_usec = 1;
+	setitimer(ITIMER_REAL, &value, 0);
+	getitimer(ITIMER_REAL, &ovalue);
+	timerclear(&value.it_interval);
+	timerclear(&value.it_value);
+	setitimer(ITIMER_REAL, &value, 0);
+	if( ovalue.it_interval.tv_usec >= 2 )
+		retval = 1000000 / ovalue.it_interval.tv_usec;
+	return( retval );
+}
+
+#if defined(KAFFE_STD_PROF_RATE)
+KAFFE_STD_PROF_RATE
+#endif
+#endif
+
+int enableXProfiling(void)
+{
+	int retval = false;
+
+	xProfilingOff();
+	/* Start up our profiler and set it to observe the main executable */
+	if( xProfFlag &&
+	    enableProfileTimer() &&
+	    (kaffe_memory_samples = createMemorySamples()) &&
+	    observeMemory(kaffe_memory_samples, &_start, &etext - &_start) &&
+	    (profiler_debug_file = createDebugFile(kaffe_syms_filename)) &&
+	    !atexit(profilerAtExit) )
+	{
+#if defined(KAFFE_CPROFILER)
+		struct gmonparam *gp = getGmonParam();
+		int prof_rate;
+#endif
+		
+#if defined(KAFFE_CPROFILER)
+		/* Turn off any other profiling */
+		profil(0, 0, 0, 0);
+#if defined(KAFFE_STD_PROF_RATE)
+		if( !(prof_rate = kaffeStdProfRate()) )
+#endif
+			prof_rate = hertz(); /* Just guess */
+		if( !prof_rate )
+			prof_rate = 100;
+		/* Copy the hits leading up to now into our own counters */
+		if( gp && gp->kcountsize > 0 )
+		{
+			int lpc, len = gp->kcountsize / sizeof(HISTCOUNTER);
+			HISTCOUNTER *hist = gp->kcount;
+			int scale;
+
+			scale = (gp->highpc - gp->lowpc) / len;
+			for( lpc = 0; lpc < len; lpc++ )
+			{
+				if( hist[lpc] )
+				{
+					char *pc = ((char *)gp->lowpc) +
+						(lpc * scale);
+
+					memoryHitCount(kaffe_memory_samples,
+						       pc,
+						       (100 * hist[lpc]) /
+						       prof_rate);
+				}
+			}
+		}
+#endif
+		retval = true;
+	}
+	else
+	{
+		xProfFlag = 0;
+		disableXProfiling();
+	}
+	xProfilingOn();
+	return( retval );
+}
+
+void disableXProfiling(void)
+{
+	/* Shutoff the timer and delete any structures */
+	disableProfileTimer();
+	xProfilingOff();
+	deleteMemorySamples(kaffe_memory_samples);
+	kaffe_memory_samples = 0;
+	deleteCallGraph(kaffe_call_graph);
+	kaffe_call_graph = 0;
+	deleteDebugFile(profiler_debug_file);
+	profiler_debug_file = 0;
+}
+
+void xProfilingOn(void)
+{
+	xProfRecord++;
+#if defined(KAFFE_CPROFILER)
+	{
+		struct gmonparam *gp = getGmonParam();
+		
+		if( xProfRecord && gp )
+			gp->state = GMON_PROF_ON;
+	}
+#endif
+}
+
+void xProfilingOff(void)
+{
+	xProfRecord--;
+#if defined(KAFFE_CPROFILER)
+	{
+		struct gmonparam *gp = getGmonParam();
+		
+		if( !xProfRecord && gp )
+			gp->state = GMON_PROF_OFF;
+	}
+#endif
+}
+
+void xProfileStage(char *stage_name)
+{
+	char *low, *high, *filename;
+	struct gmon_file *gf;
+	size_t len;
+
+	if( !xProfFlag )
+		return;
+	xProfilingOff();
+	low = kaffe_memory_samples->ms_low;
+	high = kaffe_memory_samples->ms_high +
+		(extraProfileCount * HISTFRACTION);
+	KTHREAD(suspendall)();
+	len = strlen(kaffe_gmon_filename) +
+		(stage_name ? strlen(stage_name) + 1 : 0) +
+		1;
+	if( (filename = (char *)KMALLOC(len)) )
+	{
+		sprintf(filename,
+			"%s%s%s",
+			kaffe_gmon_filename,
+			stage_name ? "." : "",
+			stage_name ? stage_name : "");
+		/* Create and write out the gmon file */
+		if( (gf = createGmonFile(filename)) )
+		{
+			struct profiler_gmon_file pgf;
+			
+			/* Initialize the profiler_gmon_files state */
+			pgf.pgf_stage = stage_name;
+			pgf.pgf_file = gf;
+			/* Write out the samples */
+			pgf.pgf_record =
+				writeGmonRecord(gf,
+						GRA_Type, GMON_TAG_TIME_HIST,
+						GRA_LowPC, low,
+						GRA_HighPC, high,
+						GRA_DONE);
+			/* The low/high might be aligned by writeGmonRecord */
+			low = gf->gf_low;
+			high = gf->gf_high;
+			walkMemorySamples(kaffe_memory_samples,
+					  low,
+					  high -
+					  (extraProfileCount * HISTFRACTION),
+					  &pgf,
+					  profilerSampleWalker);
+			if( pgf.pgf_file )
+			{
+				/* Dump out the call graph data */
+				writeCallGraph(kaffe_call_graph, pgf.pgf_file);
+				deleteGmonFile(pgf.pgf_file);
+			}
+			else
+			{
+				resetMemorySamples(kaffe_memory_samples);
+			}
+		}
+		else
+		{
+			fprintf(stderr,
+				"XProf Notice: Cannot create gmon file %s\n",
+				filename);
+			KFREE(filename);
+			resetMemorySamples(kaffe_memory_samples);
+		}
+	}
+	else
+	{
+		fprintf(stderr,
+			"XProf Notice: Not enough memory to write "
+			"profiling data\n");
+		resetMemorySamples(kaffe_memory_samples);
+	}
+	resetCallGraph(kaffe_call_graph);
+	xProfilingOn();
+	KTHREAD(unsuspendall)();
+}
+
+int profileGmonFile(char *name)
+{
+	/* Just set the file for now, we'll make it at exit */
+	kaffe_gmon_filename = name;
+	return( true );
+}
+
+int profileSymbolFile(char *name)
+{
+	kaffe_syms_filename = name;
+	return( true );
+}
+
+#if defined(KAFFE_XPROFILER)
+
+struct sigaction oldSigAction;
+
+static void profileTimerHandler(SIGNAL_ARGS(sig UNUSED, sc))
+{
+	SIGNAL_CONTEXT_POINTER(scp) = GET_SIGNAL_CONTEXT_POINTER(sc);
+	char *addr = (char *)SIGNAL_PC(scp);
+
+	if( kaffe_memory_samples && xProfRecord )
+	{
+		if( profiler_sample_override_pc )
+		{
+			profiler_sample_overrides++;
+			/* Use the override address */
+			addr = profiler_sample_override_pc;
+			/* Null it out to stop false positives */
+			profiler_sample_override_pc = 0;
+		}
+		memoryHit(kaffe_memory_samples, addr);
+	}
+}
+
+int enableProfileTimer(void)
+{
+	struct sigaction sa;
+	int retval = false;
+
+	/* Setup our signal handler */
+	sa.sa_handler = (SIG_T)profileTimerHandler;
+	sigfillset(&sa.sa_mask);
+	sa.sa_flags = 0;
+#if 0
+	if( sigaction(SIGALRM, &sa, &oldSigAction) >= 0 )
+	{
+		struct itimerval new_value;
+		
+		/* Setup a 10ms timer */
+		new_value.it_interval.tv_sec = 0;
+		new_value.it_interval.tv_usec = 10000;
+		new_value.it_value.tv_sec = 0;
+		new_value.it_value.tv_usec = 10000;
+		if( setitimer(ITIMER_REAL, &new_value, 0) >= 0 )
+		{
+			retval = true;
+		}
+	}
+#endif
+	retval = 1;
+	return( retval );
+}
+
+void disableProfileTimer(void)
+{
+	struct itimerval disable_value;
+
+	timerclear(&disable_value.it_interval);
+	timerclear(&disable_value.it_value);
+	setitimer(ITIMER_REAL, &disable_value, 0);
+}
+#else
+int enableProfileTimer(void)
+{
+	return( 1 );
+}
+
+void disableProfileTimer(void)
+{
+}
+#endif
+
+/* The rest of these are just wrappers for other code */
+
+int profileFunction(struct mangled_method *mm, char *code, int codelen)
+{
+	int retval = false;
+
+	if( xProfFlag && kaffe_memory_samples )
+	{
+		/*
+		 * Add the function name to the symbol file and observe the
+		 * memory
+		 */
+		xProfilingOff();
+		if( observeMemory(kaffe_memory_samples, code, codelen) &&
+		    addDebugInfo(profiler_debug_file,
+				 DIA_FunctionSymbol, mm, code, codelen,
+				 DIA_DONE) )
+		{
+			retval = true;
+		}
+		xProfilingOn();
+	}
+	else
+	{
+		retval = true;
+	}
+	return( retval );
+}
+
+int profileMemory(char *code, int codelen)
+{
+	int retval = false;
+	
+	if( xProfFlag )
+	{
+		xProfilingOff();
+		if( observeMemory(kaffe_memory_samples, code, codelen) )
+		{
+			retval = true;
+		}
+		xProfilingOn();
+	}
+	else
+	{
+		retval = true;
+	}
+	return( retval );
+}
+
+int profileSymbol(struct mangled_method *mm, char *addr, int size)
+{
+	int retval = false;
+	
+	if( xProfFlag )
+	{
+		if( addDebugInfo(profiler_debug_file,
+				 DIA_FunctionSymbol, mm, addr, size,
+				 DIA_DONE) )
+		{
+			retval = true;
+		}
+	}
+	else
+	{
+		retval = true;
+	}
+	return( retval );
+}
+
+void profileArcHit(char *frompc, char *selfpc)
+{
+	char *old_override = profiler_sample_override_pc;
+	
+	/*
+	 * profiler_sample_override_pc is a nasty hack to keep the
+	 * accounting function from being counted as a hit when it
+	 * should really be the caller.
+	 */
+	profiler_sample_override_pc = selfpc;
+	if( kaffe_call_graph && xProfRecord )
+	{
+		arcHit(kaffe_call_graph, frompc, selfpc);
+	}
+	profiler_sample_override_pc = old_override;
+}
+
+#if defined(KAFFE_XPROFILER) && defined(KAFFE_CPROFILER) && defined(_KAFFE_OVERRIDE_MCOUNT_DEF)
+_KAFFE_OVERRIDE_MCOUNT_DEF;
+_KAFFE_OVERRIDE_MCOUNT_DEF
+{
+	char *old_override = profiler_sample_override_pc;
+	
+	/*
+	 * profiler_sample_override_pc is a nasty hack to keep the
+	 * accounting function from being counted as a hit when it
+	 * should really be the caller.
+	 */
+	profiler_sample_override_pc = (char *)selfpc;
+	if( kaffe_call_graph )
+	{
+		register struct gmonparam *gp = getGmonParam();
+		
+		if( !xProfRecord || (gp && (gp->state != GMON_PROF_ON)) )
+			goto fini;

*** Patch too long, truncated ***




More information about the kaffe mailing list