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  <[EMAIL PROTECTED]>
+
+       * kaffe/xprof/callGraph.c
+       (writeCallGraph): Fixlet for call graph dump.
+
 2005-05-04  Guilhem Lavaux  <[EMAIL PROTECTED]>
 
        * 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

_______________________________________________
kaffe mailing list
[email protected]
http://kaffe.org/cgi-bin/mailman/listinfo/kaffe

Reply via email to