* 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.
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
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)
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 */
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
};
#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"
// 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
// 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
#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);
#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.
/* 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: ");
_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: ");
if ENABLE_PROFILING
PROFILE_SOURCES = \
- profile.c \
- profile.h
+ profile.cpp \
+ profile.hpp
REORDER_SOURCES = \
reorder.c \
+++ /dev/null
-/* 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:
- */
--- /dev/null
+/* 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:
+ */
+++ /dev/null
-/* 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:
- */
--- /dev/null
+/* 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:
+ */
#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.
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) {
#define M_ASUB_IMM32(imm, tmpreg, reg) M_ISUB_IMM32(imm, tmpreg, reg)
-#define PROFILE_CYCLE_START
-
-#define PROFILE_CYCLE_STOP
-
#endif /* _CODEGEN_H */
/*
#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.
#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.
#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)