* src/toolbox/list.hpp (DumpList): Made sort function accessible.
authorMichael Starzinger <michi@complang.tuwien.ac.at>
Tue, 1 Sep 2009 00:59:25 +0000 (02:59 +0200)
committerMichael Starzinger <michi@complang.tuwien.ac.at>
Tue, 1 Sep 2009 00:59:25 +0000 (02:59 +0200)
* src/vm/jit/code.cpp (code_codeinfo_free): Release memory for profiling.
* src/vm/jit/code.hpp (codeinfo): Basicblockcount only needed for profiling.
* src/vm/jit/codegen-common.cpp (codegen_emit): Adapted CPU cycle counting.
* src/vm/jit/emit-common.hpp: Likewise.
* src/vm/jit/jit.cpp (jit_compile): This is not the place to free resources.
* src/vm/jit/optimizing/Makefile.am (PROFILE_SOURCES): Moved to C++.
* src/vm/jit/optimizing/profile.cpp: Fixed and moved to C++.
* src/vm/jit/optimizing/profile.hpp: Likewise.
* src/vm/vm.cpp: Fixed includes.

* src/vm/jit/i386/emit.c: Added dummies for CPU cycle counting.
* src/vm/jit/powerpc/emit.c: Likewise.
* src/vm/jit/s390/emit.c: Likewise.
* src/vm/jit/x86_64/emit.c: Moved CPU cycle counting here.

18 files changed:
src/toolbox/list.hpp
src/vm/jit/code.cpp
src/vm/jit/code.hpp
src/vm/jit/codegen-common.cpp
src/vm/jit/emit-common.hpp
src/vm/jit/i386/emit.c
src/vm/jit/jit.cpp
src/vm/jit/optimizing/Makefile.am
src/vm/jit/optimizing/profile.c [deleted file]
src/vm/jit/optimizing/profile.cpp [new file with mode: 0644]
src/vm/jit/optimizing/profile.h [deleted file]
src/vm/jit/optimizing/profile.hpp [new file with mode: 0644]
src/vm/jit/powerpc/emit.c
src/vm/jit/s390/codegen.c
src/vm/jit/s390/codegen.h
src/vm/jit/s390/emit.c
src/vm/jit/x86_64/emit.c
src/vm/vm.cpp

index 53395be00ade144114205c63db0996e81018fdcc..59c9c55ce97e2ca33ea637bb87291b1e9012a690 100644 (file)
@@ -108,6 +108,7 @@ public:
        using std::list<T, DumpMemoryAllocator<T> >::remove;
        using std::list<T, DumpMemoryAllocator<T> >::rend;
        using std::list<T, DumpMemoryAllocator<T> >::size;
+       using std::list<T, DumpMemoryAllocator<T> >::sort;
 };
 
 #else
index 53dec1fd2485d6a1b2cedbbaf02b19869321a5a8..4946310d8d397af855895791e35a686cf1e2ba8a 100644 (file)
@@ -238,6 +238,13 @@ void code_codeinfo_free(codeinfo *code)
        replace_free_replacement_points(code);
 #endif
 
+#if defined(ENABLE_PROFILING)
+       /* Release memory for basic block profiling information. */
+
+       if (code->bbfrequency != NULL)
+               MFREE(code->bbfrequency, u4, code->basicblockcount);
+#endif
+
        FREE(code, codeinfo);
 
 #if defined(ENABLE_STATISTICS)
index 46530ebae7846fb7eec6d686eefcafeb464b7401..c32f53188344c53d0c3324bf8c57fb92bda6de49 100644 (file)
@@ -71,7 +71,6 @@ struct codeinfo {
        uint32_t      flags;                /* OR of CODE_FLAG_ constants         */
 
        u1            optlevel;             /* optimization level of this code    */
-       s4            basicblockcount;      /* number of basic blocks             */
 
        /* machine code */
        u1           *mcode;                /* pointer to machine code            */
@@ -108,9 +107,11 @@ struct codeinfo {
        u1           *savedmcode;           /* saved code under patches           */
 #endif
 
+       /* profiling information */
 #if defined(ENABLE_PROFILING)
        u4            frequency;            /* number of method invocations       */
-       u4           *bbfrequency;                  
+       s4            basicblockcount;      /* number of basic blocks             */
+       u4           *bbfrequency;          /* basic block profiling information  */
        s8            cycles;               /* number of cpu cycles               */
 #endif
 };
index b9dffac2d126f0a114f264966429fe90e3123258..76ec50c82438087d40a97895ed14fcc7443d1b92 100644 (file)
@@ -92,7 +92,7 @@
 #include "vm/jit/stacktrace.hpp"
 #include "vm/jit/trace.hpp"
 
-#include "vm/jit/optimizing/profile.h"
+#include "vm/jit/optimizing/profile.hpp"
 
 #if defined(ENABLE_SSA)
 # include "vm/jit/optimizing/lsra.h"
@@ -1098,10 +1098,8 @@ bool codegen_emit(jitdata *jd)
                // Count method frequency.
                emit_profile_method(cd, code);
 
-# if defined(__X86_64__)
                // Start CPU cycle counting.
-               emit_profile_cycle_start();
-# endif
+               emit_profile_cycle_start(cd, code);
        }
 #endif
 
@@ -1166,11 +1164,9 @@ bool codegen_emit(jitdata *jd)
                        // Count basicblock frequency.
                        emit_profile_basicblock(cd, code, bptr);
 
-# if defined(__X86_64__)
                        // If this is an exception handler, start profiling again.
                        if (bptr->type == BBTYPE_EXH)
-                               emit_profile_cycle_start();
-# endif
+                               emit_profile_cycle_start(cd, code);
                }
 #endif
 
index 24f6b15109fcdb3bd09ea842c0b01662a64789c7..0d467fc11658f096f1839254e6a34431cc925236 100644 (file)
@@ -221,8 +221,8 @@ void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset);
 #if defined(ENABLE_PROFILING)
 void emit_profile_method(codegendata* cd, codeinfo* code);
 void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr);
-void emit_profile_cycle_start();
-void emit_profile_cycle_stop();
+void emit_profile_cycle_start(codegendata* cd, codeinfo* code);
+void emit_profile_cycle_stop(codegendata* cd, codeinfo* code);
 #endif
 
 void emit_verbosecall_enter(jitdata *jd);
index d69217920db6745eda2d90baddd3ba1fbe284846..5751e5884d80b7e02729d34e5c6c6b4ebcab40db 100644 (file)
@@ -706,6 +706,28 @@ void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr)
 #endif
 
 
+/**
+ * Emit profiling code to start CPU cycle counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_cycle_start(codegendata* cd, codeinfo* code)
+{
+       // XXX Not implemented yet!
+}
+#endif
+
+
+/**
+ * Emit profiling code to stop CPU cycle counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_cycle_stop(codegendata* cd, codeinfo* code)
+{
+       // XXX Not implemented yet!
+}
+#endif
+
+
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
index 2da94922a2cccd49e8a876dcb7ae6a67ecb8ba07..a8ac2b160a196c7f7c1873db3e80bf196fab7e86 100644 (file)
@@ -389,14 +389,6 @@ u1 *jit_compile(methodinfo *m)
                /* release codeinfo */
 
                code_codeinfo_free(jd->code);
-
-#if defined(ENABLE_PROFILING)
-               /* Release memory for basic block profiling information. */
-
-               if (JITDATA_HAS_FLAG_INSTRUMENT(jd))
-                       if (jd->code->bbfrequency != NULL)
-                               MFREE(jd->code->bbfrequency, u4, jd->code->basicblockcount);
-#endif
        }
        else {
                DEBUG_JIT_COMPILEVERBOSE("Running: ");
@@ -774,8 +766,10 @@ static u1 *jit_compile_intern(jitdata *jd)
           _must_ be done after loop optimization and register allocation,
           since they can change the basic block count. */
 
-       if (JITDATA_HAS_FLAG_INSTRUMENT(jd))
+       if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
+               code->basicblockcount = jd->basicblockcount;
                code->bbfrequency = MNEW(u4, jd->basicblockcount);
+       }
 #endif
 
        DEBUG_JIT_COMPILEVERBOSE("Generating code: ");
index d725afc4dcab935461547a33580796c7f889250c..5ce18f6441afe1a95e855f54758b96b4d64da003 100644 (file)
@@ -33,8 +33,8 @@ endif
 
 if ENABLE_PROFILING
 PROFILE_SOURCES = \
-       profile.c \
-       profile.h
+       profile.cpp \
+       profile.hpp
 
 REORDER_SOURCES = \
        reorder.c \
diff --git a/src/vm/jit/optimizing/profile.c b/src/vm/jit/optimizing/profile.c
deleted file mode 100644 (file)
index 5268c8d..0000000
+++ /dev/null
@@ -1,326 +0,0 @@
-/* src/vm/jit/optimizing/profile.c - runtime profiling
-
-   Copyright (C) 1996-2005, 2006, 2007, 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.hpp"
-
-#include "threads/threadlist.hpp"
-#include "threads/thread.hpp"
-
-#include "vm/jit/builtin.hpp"
-#include "vm/class.hpp"
-#include "vm/classcache.hpp"
-#include "vm/method.hpp"
-#include "vm/options.h"
-#include "vm/string.hpp"
-
-#include "vm/jit/jit.hpp"
-#include "vm/jit/methodheader.h"
-#include "vm/jit/methodtree.h"
-
-#include "vm/jit/optimizing/recompiler.hpp"
-
-
-/* profile_init ****************************************************************
-
-   Initializes the profile global lock.
-
-*******************************************************************************/
-
-bool profile_init(void)
-{
-       /* everything's ok */
-
-       return true;
-}
-
-
-/* profile_thread **************************************************************
-
-   XXX
-
-*******************************************************************************/
-
-static s4 runs = 0;
-static s4 hits = 0;
-static s4 misses = 0;
-
-#if defined(ENABLE_THREADS)
-static void profile_thread(void)
-{
-       threadobject *t;
-       s4            nanos;
-       u1           *pc;
-       u1           *pv;
-       methodinfo   *m;
-       codeinfo     *code;
-
-       while (true) {
-               /* sleep thread for 0.5-1.0 ms */
-
-               nanos = 500 + (int) (500.0 * (rand() / (RAND_MAX + 1.0)));
-/*             fprintf(stderr, "%d\n", nanos); */
-
-               threads_sleep(0, nanos);
-               runs++;
-
-               // Lock the thread lists.
-               ThreadList_lock();
-
-#if 0
-               /* iterate over all started threads */
-
-               for (t = ThreadList_first(); t != NULL; t = ThreadList_next(t)) {
-                       /* is this a Java thread? */
-
-                       if (!(t->flags & THREAD_FLAG_JAVA))
-                               continue;
-
-                       /* send SIGUSR2 to thread to get the current PC */
-                       /* XXX write a threads-function for that */
-
-                       pthread_kill(t->tid, SIGUSR2);
-
-                       /* the thread object now contains the current thread PC */
-
-                       pc = t->pc;
-
-                       /* Get the PV for the current PC. */
-
-                       pv = methodtree_find_nocheck(pc);
-
-                       /* get methodinfo pointer from data segment */
-
-                       if (pv == NULL) {
-                               misses++;
-                       }
-                       else {
-                               code = *((codeinfo **) (pv + CodeinfoPointer));
-
-                               /* For asm_vm_call_method the codeinfo pointer is NULL
-                                  (which is also in the method tree). */
-
-                               if (code != NULL) {
-                                       m = code->m;
-
-                                       /* native methods are never recompiled */
-
-                                       if (!(m->flags & ACC_NATIVE)) {
-                                               /* increase the method incovation counter */
-
-                                               code->frequency++;
-                                               hits++;
-
-                                               if (code->frequency > 500) {
-                                                       /* clear frequency count before
-                                                          recompilation */
-
-                                                       code->frequency = 0;
-
-                                                       /* add this method to the method list and
-                                                          start recompilation */
-
-                                                       Recompiler_queue_method(m);
-                                               }
-                                       }
-                               }
-                       }
-               }
-#endif
-
-               // Unlock the thread lists.
-               ThreadList_unlock();
-       }
-}
-#endif
-
-
-/* profile_start_thread ********************************************************
-
-   Starts the profile sampling thread.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS)
-bool profile_start_thread(void)
-{
-       utf *name;
-
-       name = utf_new_char("Profiling Sampler");
-
-       if (!threads_thread_start_internal(name, profile_thread))
-               return false;
-
-       /* everything's ok */
-
-       return true;
-}
-#endif
-
-
-/* profile_printstats **********************************************************
-
-   Prints profiling statistics gathered during runtime.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void profile_printstats(void)
-{
-       classinfo              *c;
-       methodinfo             *m;
-       codeinfo               *code;
-       u4                      slot;
-       classcache_name_entry  *nmen;
-       classcache_class_entry *clsen;
-       s4                      i;
-       s4                      j;
-       u4                      frequency;
-       s8                      cycles;
-
-       frequency = 0;
-       cycles    = 0;
-
-#if 0
-       /* create new method list */
-       // TODO Use a sorted container.
-       List* l = List_new();
-
-       /* iterate through all classes and methods */
-
-       for (slot = 0; slot < hashtable_classcache.size; slot++) {
-               nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
-
-               for (; nmen; nmen = nmen->hashlink) {
-                       /* iterate over all class entries */
-
-                       for (clsen = nmen->classes; clsen; clsen = clsen->next) {
-                               c = clsen->classobj;
-
-                               if (c == NULL)
-                                       continue;
-
-                               /* interate over all class methods */
-
-                               for (i = 0; i < c->methodscount; i++) {
-                                       m = &(c->methods[i]);
-
-                                       code = m->code;
-
-                                       /* was this method actually called? */
-
-                                       if ((code != NULL) && (code->frequency > 0)) {
-                                               /* add to overall stats */
-
-                                               frequency += code->frequency;
-                                               cycles    += code->cycles;
-
-                                               /* sort the new entry into the list */
-                                               
-                                               if (List_empty(l) == NULL) {
-                                                       List_push_back(l, m);
-                                               }
-                                               else {
-                                                       for (; tlme != NULL; tlme = list_next(l, tlme)) {
-                                                               /* check the frequency */
-
-                                                               if (code->frequency > tlme->m->code->frequency) {
-                                                                       list_add_before(l, tlme, lme);
-                                                                       break;
-                                                               }
-                                                       }
-
-                                                       /* if we are at the end of the list, add
-                                                          it as last entry */
-
-                                                       if (tlme == NULL)
-                                                               list_add_last(l, lme);
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-
-       /* print all methods sorted */
-
-       printf(" frequency     ratio         cycles     ratio   method name\n");
-       printf("----------- --------- -------------- --------- -------------\n");
-
-       /* now iterate through the list and print it */
-
-       for (lme = list_first(l); lme != NULL; lme = list_next(l, lme)) {
-               /* get method of the list element */
-
-               m = lme->m;
-
-               code = m->code;
-
-               printf("%10d   %.5f   %12ld   %.5f   ",
-                          code->frequency,
-                          (double) code->frequency / (double) frequency,
-                          (long) code->cycles,
-                          (double) code->cycles / (double) cycles);
-
-               method_println(m);
-
-               /* print basic block frequencies */
-
-               if (opt_prof_bb) {
-                       for (j = 0; j < code->basicblockcount; j++)
-                               printf("                                                    L%03d: %10d\n",
-                                          j, code->bbfrequency[j]);
-               }
-       }
-#endif
-
-       printf("-----------           -------------- \n");
-       printf("%10d             %12ld\n", frequency, (long) cycles);
-
-       printf("\nruns  : %10d\n", runs);
-       printf("hits  : %10d\n", hits);
-       printf("misses: %10d\n", misses);
-}
-#endif /* !defined(NDEBUG) */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/src/vm/jit/optimizing/profile.cpp b/src/vm/jit/optimizing/profile.cpp
new file mode 100644 (file)
index 0000000..1ebc554
--- /dev/null
@@ -0,0 +1,323 @@
+/* src/vm/jit/optimizing/profile.cpp - runtime profiling
+
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2009 Theobroma Systems Ltd.
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.hpp"
+
+#include "threads/threadlist.hpp"
+#include "threads/thread.hpp"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/class.hpp"
+#include "vm/classcache.hpp"
+#include "vm/method.hpp"
+#include "vm/options.h"
+#include "vm/string.hpp"
+
+#include "vm/jit/jit.hpp"
+#include "vm/jit/methodheader.h"
+#include "vm/jit/methodtree.h"
+
+#include "vm/jit/optimizing/recompiler.hpp"
+
+
+/* profile_init ****************************************************************
+
+   Initializes the profile global lock.
+
+*******************************************************************************/
+
+bool profile_init(void)
+{
+       /* everything's ok */
+
+       return true;
+}
+
+
+/* profile_thread **************************************************************
+
+   XXX
+
+*******************************************************************************/
+
+static s4 runs = 0;
+static s4 hits = 0;
+static s4 misses = 0;
+
+#if defined(ENABLE_THREADS)
+static void profile_thread(void)
+{
+       threadobject *t;
+       s4            nanos;
+       u1           *pc;
+       u1           *pv;
+       methodinfo   *m;
+       codeinfo     *code;
+
+       while (true) {
+               /* sleep thread for 0.5-1.0 ms */
+
+               nanos = 500 + (int) (500.0 * (rand() / (RAND_MAX + 1.0)));
+/*             fprintf(stderr, "%d\n", nanos); */
+
+               threads_sleep(0, nanos);
+               runs++;
+
+               // Lock the thread lists.
+               ThreadList::lock();
+
+#if 0
+               /* iterate over all started threads */
+
+               for (t = ThreadList_first(); t != NULL; t = ThreadList_next(t)) {
+                       /* is this a Java thread? */
+
+                       if (!(t->flags & THREAD_FLAG_JAVA))
+                               continue;
+
+                       /* send SIGUSR2 to thread to get the current PC */
+                       /* XXX write a threads-function for that */
+
+                       pthread_kill(t->tid, SIGUSR2);
+
+                       /* the thread object now contains the current thread PC */
+
+                       pc = t->pc;
+
+                       /* Get the PV for the current PC. */
+
+                       pv = methodtree_find_nocheck(pc);
+
+                       /* get methodinfo pointer from data segment */
+
+                       if (pv == NULL) {
+                               misses++;
+                       }
+                       else {
+                               code = *((codeinfo **) (pv + CodeinfoPointer));
+
+                               /* For asm_vm_call_method the codeinfo pointer is NULL
+                                  (which is also in the method tree). */
+
+                               if (code != NULL) {
+                                       m = code->m;
+
+                                       /* native methods are never recompiled */
+
+                                       if (!(m->flags & ACC_NATIVE)) {
+                                               /* increase the method incovation counter */
+
+                                               code->frequency++;
+                                               hits++;
+
+                                               if (code->frequency > 500) {
+                                                       /* clear frequency count before
+                                                          recompilation */
+
+                                                       code->frequency = 0;
+
+                                                       /* add this method to the method list and
+                                                          start recompilation */
+
+                                                       Recompiler_queue_method(m);
+                                               }
+                                       }
+                               }
+                       }
+               }
+#endif
+
+               // Unlock the thread lists.
+               ThreadList::unlock();
+       }
+}
+#endif
+
+
+/* profile_start_thread ********************************************************
+
+   Starts the profile sampling thread.
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS)
+bool profile_start_thread(void)
+{
+       utf *name;
+
+       name = utf_new_char("Profiling Sampler");
+
+       if (!threads_thread_start_internal(name, profile_thread))
+               return false;
+
+       /* everything's ok */
+
+       return true;
+}
+#endif
+
+
+/**
+ * Comparison function used to sort a method list from higher to lower by
+ * comparing the method call frequencies.
+ *
+ * @param m1 First method to be compared.
+ * @param m2 Second method to be compared.
+ * @return Returns true if the first method goes before the second method in
+ * the specific order, and false otherwise.
+ */
+#if !defined(NDEBUG)
+static bool profile_compare_frequency(methodinfo* m1, methodinfo* m2)
+{
+       return (m1->code->frequency > m2->code->frequency);
+}
+#endif
+
+
+/**
+ * Prints profiling statistics gathered during runtime.
+ */
+#if !defined(NDEBUG)
+void profile_printstats(void)
+{
+       classinfo              *c;
+       methodinfo             *m;
+       codeinfo               *code;
+       u4                      slot;
+       classcache_name_entry  *nmen;
+       classcache_class_entry *clsen;
+       s4                      i;
+       s4                      j;
+       u4                      frequency;
+       s8                      cycles;
+
+       frequency = 0;
+       cycles    = 0;
+
+       /* create new method list */
+
+       DumpList<methodinfo*> l;
+
+       /* iterate through all classes and methods */
+
+       for (slot = 0; slot < hashtable_classcache.size; slot++) {
+               nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
+
+               for (; nmen; nmen = nmen->hashlink) {
+                       /* iterate over all class entries */
+
+                       for (clsen = nmen->classes; clsen; clsen = clsen->next) {
+                               c = clsen->classobj;
+
+                               if (c == NULL)
+                                       continue;
+
+                               /* interate over all class methods */
+
+                               for (i = 0; i < c->methodscount; i++) {
+                                       m = &(c->methods[i]);
+
+                                       code = m->code;
+
+                                       /* was this method actually called? */
+
+                                       if ((code != NULL) && (code->frequency > 0)) {
+                                               /* add to overall stats */
+
+                                               frequency += code->frequency;
+                                               cycles    += code->cycles;
+
+                                               /* add new entry into method list */
+
+                                               l.push_back(m);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /* sort the method list */
+
+       l.sort(profile_compare_frequency);
+
+       /* print all methods sorted */
+
+       printf(" frequency     ratio         cycles     ratio   method name\n");
+       printf("----------- --------- -------------- --------- -------------\n");
+
+       /* now iterate through the list and print it */
+
+       for (DumpList<methodinfo*>::iterator it = l.begin(); it != l.end(); ++it) {
+               m = *(it);
+
+               code = m->code;
+
+               printf("%10d   %.5f   %12ld   %.5f   ",
+                          code->frequency,
+                          (double) code->frequency / (double) frequency,
+                          (long) code->cycles,
+                          (double) code->cycles / (double) cycles);
+
+               method_println(m);
+
+               /* print basic block frequencies */
+
+               if (opt_prof_bb) {
+                       for (j = 0; j < code->basicblockcount; j++)
+                               printf("                                                    L%03d: %10d\n",
+                                          j, code->bbfrequency[j]);
+               }
+       }
+
+       printf("-----------           -------------- \n");
+       printf("%10d             %12ld\n", frequency, (long) cycles);
+
+       printf("\nruns  : %10d\n", runs);
+       printf("hits  : %10d\n", hits);
+       printf("misses: %10d\n", misses);
+}
+#endif /* !defined(NDEBUG) */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/src/vm/jit/optimizing/profile.h b/src/vm/jit/optimizing/profile.h
deleted file mode 100644 (file)
index 06a672a..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/* src/vm/jit/optimizing/profile.h - runtime profiling
-
-   Copyright (C) 1996-2005, 2006, 2008
-   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
-   This file is part of CACAO.
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2, or (at
-   your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
-
-*/
-
-
-#ifndef _PROFILE_H
-#define _PROFILE_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-
-/* CPU cycle counting macros **************************************************/
-
-#if defined(ENABLE_PROFILING) && defined(__X86_64__)
-
-#define PROFILE_CYCLE_START \
-    do { \
-        if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { \
-            M_PUSH(RAX); \
-            M_PUSH(RDX); \
-            \
-            M_MOV_IMM(code, REG_ITMP3); \
-            M_RDTSC; \
-            M_ISUB_MEMBASE(RAX, REG_ITMP3, OFFSET(codeinfo, cycles)); \
-            M_ISBB_MEMBASE(RDX, REG_ITMP3, OFFSET(codeinfo, cycles) + 4); \
-            \
-            M_POP(RDX); \
-            M_POP(RAX); \
-        } \
-    } while (0)
-
-#define PROFILE_CYCLE_STOP \
-    do { \
-        if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { \
-            M_PUSH(RAX); \
-            M_PUSH(RDX); \
-            \
-            M_MOV_IMM(code, REG_ITMP3); \
-            M_RDTSC; \
-            M_IADD_MEMBASE(RAX, REG_ITMP3, OFFSET(codeinfo, cycles)); \
-            M_IADC_MEMBASE(RDX, REG_ITMP3, OFFSET(codeinfo, cycles) + 4); \
-            \
-            M_POP(RDX); \
-            M_POP(RAX); \
-        } \
-    } while (0)
-
-#else
-
-#define PROFILE_CYCLE_START
-#define PROFILE_CYCLE_STOP
-
-#endif
-
-
-/* function prototypes ********************************************************/
-
-bool profile_init(void);
-bool profile_start_thread(void);
-
-#if !defined(NDEBUG)
-void profile_printstats(void);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PROFILE_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/src/vm/jit/optimizing/profile.hpp b/src/vm/jit/optimizing/profile.hpp
new file mode 100644 (file)
index 0000000..7afb4c0
--- /dev/null
@@ -0,0 +1,86 @@
+/* src/vm/jit/optimizing/profile.hpp - runtime profiling
+
+   Copyright (C) 1996-2005, 2006, 2008, 2009
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2009 Theobroma Systems Ltd.
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+#ifndef _PROFILE_HPP
+#define _PROFILE_HPP
+
+#include "config.h"
+
+#include "vm/types.h"
+
+#include "vm/global.h"
+
+
+/* CPU cycle counting macros **************************************************/
+
+#if defined(ENABLE_PROFILING)
+
+#define PROFILE_CYCLE_START \
+       do { \
+               if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { \
+                       emit_profile_cycle_start(cd, code); \
+               } \
+       } while (0)
+
+#define PROFILE_CYCLE_STOP \
+       do { \
+               if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { \
+                       emit_profile_cycle_stop(cd, code); \
+               } \
+       } while (0)
+
+#else
+
+#define PROFILE_CYCLE_START  /* nop */
+#define PROFILE_CYCLE_STOP   /* nop */
+
+#endif
+
+
+/* function prototypes ********************************************************/
+
+bool profile_init(void);
+bool profile_start_thread(void);
+
+#if !defined(NDEBUG)
+void profile_printstats(void);
+#endif
+
+#endif /* _PROFILE_HPP */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
index 1e35669c81c4892d9cf0173149dc63ba61887b75..7ff37e917bc4cf237d12ba00e7f832334c602b8c 100644 (file)
@@ -735,6 +735,28 @@ void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr)
 #endif
 
 
+/**
+ * Emit profiling code to start CPU cycle counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_cycle_start(codegendata* cd, codeinfo* code)
+{
+       // XXX Not implemented yet!
+}
+#endif
+
+
+/**
+ * Emit profiling code to stop CPU cycle counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_cycle_stop(codegendata* cd, codeinfo* code)
+{
+       // XXX Not implemented yet!
+}
+#endif
+
+
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
index 77c685e7723ea6f31dde93e2aee80fb24939e100..334dbada29be73b8e25c770490be75e2ae706381 100644 (file)
@@ -330,13 +330,9 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr)
                                constant_classref *cr = iptr->sx.val.c.ref;
                                disp = dseg_add_unique_address(cd, cr);
 
-/*                             PROFILE_CYCLE_STOP; */
-
                                patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
                                                                          cr, disp);
 
-/*                             PROFILE_CYCLE_START; */
-
                                M_ALD_DSEG(d, disp);
                        } else {
                                if (iptr->sx.val.anyptr == 0) {
index fcaeba52793f822dc6d8e6617e0662afaad0d724..2cce3c6356254d9534a9d22ece2b878ff681d419 100644 (file)
@@ -816,10 +816,6 @@ static inline uint8_t N_ILL_GET_TYPE(uint8_t *instrp) {
 
 #define M_ASUB_IMM32(imm, tmpreg, reg) M_ISUB_IMM32(imm, tmpreg, reg)
 
-#define PROFILE_CYCLE_START 
-
-#define PROFILE_CYCLE_STOP 
-
 #endif /* _CODEGEN_H */
 
 /*
index 358d154e627ec95008fa9a86b83b26ef90e612b9..f933634352742f1d78cfc21a0d899ed56ca87376 100644 (file)
@@ -414,6 +414,28 @@ void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr)
 #endif
 
 
+/**
+ * Emit profiling code to start CPU cycle counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_cycle_start(codegendata* cd, codeinfo* code)
+{
+       // XXX Not implemented yet!
+}
+#endif
+
+
+/**
+ * Emit profiling code to stop CPU cycle counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_cycle_stop(codegendata* cd, codeinfo* code)
+{
+       // XXX Not implemented yet!
+}
+#endif
+
+
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
index 649270abe8f7080f871777905a13ff79aebf8e29..830024cc01ce6b00f9fb54f42fdd96ba17389498 100644 (file)
@@ -600,6 +600,46 @@ void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr)
 #endif
 
 
+/**
+ * Emit profiling code to start CPU cycle counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_cycle_start(codegendata* cd, codeinfo* code)
+{
+       M_PUSH(RAX);
+       M_PUSH(RDX);
+
+       M_MOV_IMM(code, REG_ITMP3);
+       M_RDTSC;
+       M_ISUB_MEMBASE(RAX, REG_ITMP3, OFFSET(codeinfo, cycles));
+       M_ISBB_MEMBASE(RDX, REG_ITMP3, OFFSET(codeinfo, cycles) + 4);
+
+       M_POP(RDX);
+       M_POP(RAX);
+}
+#endif
+
+
+/**
+ * Emit profiling code to stop CPU cycle counting.
+ */
+#if defined(ENABLE_PROFILING)
+void emit_profile_cycle_stop(codegendata* cd, codeinfo* code)
+{
+       M_PUSH(RAX);
+       M_PUSH(RDX);
+
+       M_MOV_IMM(code, REG_ITMP3);
+       M_RDTSC;
+       M_IADD_MEMBASE(RAX, REG_ITMP3, OFFSET(codeinfo, cycles));
+       M_IADC_MEMBASE(RDX, REG_ITMP3, OFFSET(codeinfo, cycles) + 4);
+
+       M_POP(RDX);
+       M_POP(RAX);
+}
+#endif
+
+
 /* emit_verbosecall_enter ******************************************************
 
    Generates the code for the call trace.
index 1239da685cfc3c129b10ff7f81576d1a2ee68b83..f83e80e7429d7711e3aefe724c7f6f0cf0347c45 100644 (file)
 #include "vm/jit/jit.hpp"
 #include "vm/jit/methodtree.h"
 
-#if defined(ENABLE_PROFILING)
-# include "vm/jit/optimizing/profile.h"
-#endif
-
+#include "vm/jit/optimizing/profile.hpp"
 #include "vm/jit/optimizing/recompiler.hpp"
 
 #if defined(ENABLE_PYTHON)