[kaffe] CVS kaffe (guilhem): Profiler fixlet.

Kaffe CVS cvs-commits at kaffe.org
Fri May 6 08:40:35 PDT 2005


PatchSet 6439 
Date: 2005/05/06 15:33:07
Author: guilhem
Branch: HEAD
Tag: (none) 
Log:
Profiler fixlet.

        * kaffe/xprof/callGraph.c
        (writeCallGraph): Fixlet for call graph dump.

Members: 
	ChangeLog:1.3967->1.3968 
	kaffe/xprof/callGraph.c:INITIAL->1.7 

Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.3967 kaffe/ChangeLog:1.3968
--- kaffe/ChangeLog:1.3967	Fri May  6 15:24:20 2005
+++ kaffe/ChangeLog	Fri May  6 15:33:07 2005
@@ -1,3 +1,8 @@
+2005-05-06  Guilhem Lavaux  <guilhem at kaffe.org>
+
+	* kaffe/xprof/callGraph.c
+	(writeCallGraph): Fixlet for call graph dump.
+
 2005-05-04  Guilhem Lavaux  <guilhem at kaffe.org>
 
 	* kaffe/kaffevm/classMethod.c, 
===================================================================
Checking out kaffe/kaffe/xprof/callGraph.c
RCS:  /home/cvs/kaffe/kaffe/kaffe/xprof/callGraph.c,v
VERS: 1.7
***************
--- /dev/null	Sun Aug  4 19:57:58 2002
+++ kaffe/kaffe/xprof/callGraph.c	Fri May  6 15:40:32 2005
@@ -0,0 +1,238 @@
+/*
+ * callGraph.c
+ * Routines for tracking the call graph of jitted code
+ *
+ * Copyright (c) 2000, 2001, 2003 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 <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/gmon.h>
+
+#include "callGraph.h"
+#include "jthread.h"
+#include "xprofile-md.h"
+
+/*
+ * Hash function for an arc, obviously we need something that will spread them
+ * out quite a bit.
+ */
+#define HASH_ARC(frompc, selfpc) \
+	((((unsigned long)(frompc)) + ((unsigned long)(selfpc))) \
+	 % CALL_GRAPH_TABLE_SIZE)
+
+struct call_graph *createCallGraph(int count)
+{
+	struct call_graph *retval;
+	struct call_arc *arcs;
+
+	assert(count > 0);
+	
+	/*
+	 * Allocate the arcs and the root structure, this needs to be executed
+	 * early on since we use malloc.
+	 */
+	if( (retval = (struct call_graph *)
+	     malloc(sizeof(struct call_graph))) &&
+	    (arcs = (struct call_arc *)
+	     malloc(sizeof(struct call_arc) *
+		    (count + 8 /* Extra padding to be safe */))) )
+	{
+		int lpc;
+
+		/* Initialize everything */
+		retval->cg_misses = 0;
+		retval->cg_free = 0;
+		retval->cg_count = count;
+		retval->cg_arcs = arcs;
+		for( lpc = 0; lpc < CALL_GRAPH_TABLE_SIZE; lpc++ )
+		{
+			retval->cg_table[lpc] = 0;
+		}
+		for( lpc = 0; lpc < (count + 8); lpc++ )
+		{
+			arcs[lpc].ca_count = 0;
+		}
+	}
+	else
+	{
+		free(retval);
+		retval = 0;
+	}
+	return( retval );
+}
+
+void deleteCallGraph(struct call_graph *cg)
+{
+	if( cg )
+	{
+		free(cg->cg_arcs);
+		free(cg);
+	}
+}
+
+void resetCallGraph(struct call_graph *cg)
+{
+	int lpc;
+
+	assert(cg != 0);
+	
+	cg->cg_free = 0;
+	cg->cg_misses = 0;
+	/* Unlink the arcs */
+	for( lpc = 0; lpc < CALL_GRAPH_TABLE_SIZE; lpc++ )
+		cg->cg_table[lpc] = 0;
+}
+
+void arcHit(struct call_graph *cg, char *frompc, char *selfpc)
+{
+	struct call_arc *ca;
+	int _index;
+
+	/*
+	 * NOTE: This function isn't thread-safe since its would slow us down,
+	 * quite a bit.  Instead we just try to be resistant to any races
+	 * that might occur.
+	 */
+	
+	/* Get the index in the hash table for this arc */
+	_index = HASH_ARC(frompc, selfpc);
+	ca = cg->cg_table[_index];
+	/* Walk over the arcs in the table searching for a match */
+	while( ca )
+	{
+		if( (ca->ca_from == frompc) && (ca->ca_to == selfpc) )
+		{
+			/* Found a match, increase the count */
+			ca->ca_count++;
+			break;
+		}
+		ca = ca->ca_next;
+	}
+	if( !ca )
+	{
+		/*
+		 * No call_arc struct was found so this is the first time we've
+		 * seen this arc, get a new one and add it in.
+		 */
+		if( cg->cg_free < cg->cg_count )
+		{
+			ca = &cg->cg_arcs[cg->cg_free++];
+			ca->ca_count = 1;
+			ca->ca_next = cg->cg_table[_index];
+			cg->cg_table[_index] = ca;
+			ca->ca_from = frompc;
+			ca->ca_to = selfpc;
+		}
+		else
+		{
+			/* No more free call_arcs, record the miss */
+			cg->cg_misses++;
+		}
+	}
+}
+
+int writeCallGraph(struct call_graph *cg, struct gmon_file *gf)
+{
+#if defined(KAFFE_CPROFILER)
+	struct gmonparam *gp = getGmonParam();
+	int from_len;
+#endif
+	int retval = 1, lpc;
+
+	assert(cg != 0);
+	assert(gf != 0);
+	
+	/*
+	 * Walk over all of the arcs and output any that are non zero.
+	 *
+	 * NOTE: We're walking over the set of allocated arcs since the
+	 * cg_table might've dropped some of the arcs due to a race with
+	 * another thread.
+	 */
+	for( lpc = 0; (lpc < cg->cg_free) && retval; lpc++ )
+	{
+		if( cg->cg_arcs[lpc].ca_count )
+		{
+			struct call_arc *ca = &cg->cg_arcs[lpc];
+
+			/* Make sure its a valid arc */
+			if( (ca->ca_from < gf->gf_low) ||
+			    (ca->ca_to < gf->gf_low) ||
+			    (ca->ca_from > gf->gf_high) ||
+			    (ca->ca_to > gf->gf_high) )
+			{
+#if defined(KAFFE_VMDEBUG)
+			    /* FIXME: add debug code like Janos VM. */
+				dprintf("Out of bounds call arc "
+					"%p -> %p : %d\n"
+					"low: %p high: %p\n",
+					ca->ca_from,
+					ca->ca_to,
+					ca->ca_count,
+					gf->gf_low,
+					gf->gf_high);
+#endif
+			} else
+			retval = writeGmonRecord(gf,
+						 GRA_Type, GMON_TAG_CG_ARC,
+						 GRA_FromPC, ca->ca_from,
+						 GRA_SelfPC, ca->ca_to,
+						 GRA_Count, ca->ca_count,
+						 GRA_DONE);
+		}
+	}
+
+#if defined(KAFFE_CPROFILER)
+	if( gp )
+	{
+		/*
+		 * Here we write out any arcs that were generated by the C
+		 * compiler's mcount.
+		 */
+		from_len = gp->fromssize / sizeof(*gp->froms);
+		for( lpc = 0; (lpc < from_len) && retval; lpc++ )
+		{
+			if( gp->froms[lpc] )
+			{
+				char *frompc;
+				int to_index;
+				
+				frompc = (char *)(gp->lowpc +
+						  (lpc * gp->hashfraction *
+						   sizeof(*gp->froms)));
+				for( to_index = gp->froms[lpc];
+				     to_index != 0;
+				     to_index = gp->tos[to_index].link )
+				{
+					retval = writeGmonRecord(
+						gf,
+						GRA_Type, GMON_TAG_CG_ARC,
+						GRA_FromPC, frompc,
+						GRA_SelfPC,
+						gp->tos[to_index].selfpc,
+						GRA_Count,
+						gp->tos[to_index].count,
+						GRA_DONE);
+				}
+			}
+		}
+	}
+#endif
+	return( retval );
+}
+
+#endif




More information about the kaffe mailing list