* src/vm/jit/optimizing/recompile.h: Likewise.
* src/vm/jit/optimizing/recompiler.cpp: New file.
* src/vm/jit/optimizing/recompiler.hpp: Likewise.
* src/native/vm/openjdk/jvm.cpp,
src/threads/posix/condition-posix.hpp,
src/vm/jit/optimizing/Makefile.am,
src/vm/jit/optimizing/profile.c,
src/vm/vm.cpp,
src/vm/vm.hpp: Related changes.
--HG--
branch : twisti
rename : src/vm/jit/optimizing/recompile.c => src/vm/jit/optimizing/recompiler.cpp
rename : src/vm/jit/optimizing/recompile.h => src/vm/jit/optimizing/recompiler.hpp
extra : transplant_source : %29%17Mc%E6z%0D%DB%10H%D0%9B%E8%C5%870B%5B%DC%BE
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/
void signal();
void timedwait(Mutex* mutex, const struct timespec* abstime);
void wait(Mutex* mutex);
+ void wait(Mutex& mutex);
};
+// Includes.
+#include "vm/vm.hpp"
+
+
// Includes.
#include "vm/os.hpp"
*/
inline Condition::Condition()
{
- int result;
-
- result = pthread_cond_init(&_cond, NULL);
+ int result = pthread_cond_init(&_cond, NULL);
if (result != 0) {
os::abort_errnum(result, "Condition::Condition(): pthread_cond_init failed");
*/
inline Condition::~Condition()
{
- int result;
+ // Restart all threads waiting on this condition.
+ broadcast();
- result = pthread_cond_destroy(&_cond);
+ int result = pthread_cond_destroy(&_cond);
if (result != 0) {
os::abort_errnum(result, "Condition::~Condition(): pthread_cond_destroy failed");
*/
inline void Condition::broadcast()
{
- int result;
-
- result = pthread_cond_broadcast(&_cond);
+ int result = pthread_cond_broadcast(&_cond);
if (result != 0) {
os::abort_errnum(result, "Condition::broadcast(): pthread_cond_broadcast failed");
*/
inline void Condition::signal()
{
- int result;
-
- result = pthread_cond_signal(&_cond);
+ int result = pthread_cond_signal(&_cond);
if (result != 0) {
os::abort_errnum(result, "Condition::signal(): pthread_cond_signal failed");
*/
inline void Condition::wait(Mutex* mutex)
{
- int result;
+ wait(*mutex);
+}
+
- result = pthread_cond_wait(&_cond, &(mutex->_mutex));
+/**
+ * Waits for the condition variable.
+ */
+inline void Condition::wait(Mutex& mutex)
+{
+ int result = pthread_cond_wait(&_cond, &(mutex._mutex));
if (result != 0) {
os::abort_errnum(result, "Condition::wait(): pthread_cond_wait failed");
endif
if ENABLE_THREADS
-RECOMPILE_SOURCES = \
- recompile.c \
- recompile.h
+RECOMPILER_SOURCES = \
+ recompiler.cpp \
+ recompiler.hpp
endif
if ENABLE_SSA
liboptimizing_la_SOURCES = \
$(IFCONV_SOURCES) \
$(PROFILE_SOURCES) \
- $(RECOMPILE_SOURCES) \
+ $(RECOMPILER_SOURCES) \
$(REORDER_SOURCES) \
$(SSA_SOURCES) \
$(ESCAPE_SOURCES)
#include "vm/jit/methodheader.h"
#include "vm/jit/methodtree.h"
-#include "vm/jit/optimizing/recompile.h"
+#include "vm/jit/optimizing/recompiler.hpp"
/* profile_init ****************************************************************
/* add this method to the method list and
start recompilation */
- recompile_queue_method(m);
+ Recompiler_queue_method(m);
}
}
}
+++ /dev/null
-/* src/vm/jit/optimizing/recompile.c - recompilation system
-
- 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.h"
-
-#include "threads/condition.hpp"
-#include "threads/mutex.hpp"
-#include "threads/thread.hpp"
-
-#include "toolbox/list.hpp"
-
-#include "vm/jit/builtin.hpp"
-#include "vm/classcache.h"
-#include "vm/exceptions.hpp"
-#include "vm/options.h"
-#include "vm/string.hpp"
-
-#include "vm/jit/code.hpp"
-#include "vm/jit/jit.hpp"
-
-#include "vm/jit/optimizing/recompile.h"
-
-
-/* global variables ***********************************************************/
-
-static Mutex *recompile_thread_mutex;
-static Condition *recompile_thread_cond;
-static List* list_recompile_methods;
-
-
-/* recompile_init **************************************************************
-
- Initializes the recompilation system.
-
-*******************************************************************************/
-
-bool recompile_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("recompile_init");
-
- /* initialize the recompile thread mutex and condition */
-
- recompile_thread_mutex = Mutex_new();
- recompile_thread_cond = Condition_new();
-
- /* create method list */
-
- list_recompile_methods = List_new();
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* recompile_replace_vftbl *****************************************************
-
- XXX
-
-*******************************************************************************/
-
-static void recompile_replace_vftbl(methodinfo *m)
-{
- codeinfo *code;
- codeinfo *pcode;
- u4 slot;
- classcache_name_entry *nmen;
- classcache_class_entry *clsen;
- classinfo *c;
- vftbl_t *vftbl;
- s4 i;
-
- /* get current and previous codeinfo structure */
-
- code = m->code;
- pcode = code->prev;
-
- assert(pcode);
-
- /* iterate over all classes */
-
- 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;
-
- /* Search for entrypoint of the previous codeinfo in
- the vftbl and replace it with the current one. */
-
- vftbl = c->vftbl;
-
- /* Is the class linked? Means, is the vftbl finished? */
-
- if (!(c->state & CLASS_LINKED))
- continue;
-
- /* Does the class have a vftbl? Some internal classes
- (e.g. $NEW$) are linked, but do not have a
- vftbl. */
-
- if (vftbl == NULL)
- continue;
-
- for (i = 0; i < vftbl->vftbllength; i++) {
- if (vftbl->table[i] == pcode->entrypoint) {
-#if !defined(NDEBUG)
- printf("replacing vftbl in: ");
- class_println(c);
-#endif
- vftbl->table[i] = code->entrypoint;
- }
- }
- }
- }
- }
-}
-
-
-/* recompile_thread ************************************************************
-
- XXX
-
-*******************************************************************************/
-
-static void recompile_thread(void)
-{
- list_method_entry *lme;
-
- while (true) {
- /* get the lock on the recompile mutex, so we can call wait */
-
- Mutex_lock(recompile_thread_mutex);
-
- /* wait forever on that condition till we are signaled */
-
- Condition_wait(recompile_thread_cond, recompile_thread_mutex);
-
- /* leave the lock */
-
- Mutex_unlock(recompile_thread_mutex);
-
- /* get the next method and recompile it */
-
- while ((lme = List_front(list_recompile_methods)) != NULL) {
- /* recompile this method */
-
- if (jit_recompile(lme->m) != NULL) {
- /* replace in vftbl's */
-
- recompile_replace_vftbl(lme->m);
- }
- else {
- /* XXX what is the right-thing(tm) to do here? */
-
- exceptions_print_current_exception();
- }
-
- /* remove the compiled method */
-
- List_remove(list_recompile_methods, lme);
-
- /* free the entry */
-
- FREE(lme, list_method_entry);
- }
- }
-}
-
-
-/* recompile_start_thread ******************************************************
-
- Starts the recompilation thread.
-
-*******************************************************************************/
-
-bool recompile_start_thread(void)
-{
- utf *name;
-
- name = utf_new_char("Recompiler");
-
- if (!threads_thread_start_internal(name, recompile_thread))
- return false;
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* recompile_queue_method ******************************************************
-
- Adds a method to the recompilation list and signal the
- recompilation thread that there is some work to do.
-
-*******************************************************************************/
-
-void recompile_queue_method(methodinfo *m)
-{
- list_method_entry *lme;
-
- /* create a method entry */
-
- lme = NEW(list_method_entry);
- lme->m = m;
-
- /* and add it to the list */
-
- List_push_back(list_recompile_methods, lme);
-
- /* get the lock on the recompile mutex, so we can call notify */
-
- Mutex_lock(recompile_thread_mutex);
-
- /* signal the recompiler thread */
-
- Condition_signal(recompile_thread_cond);
-
- /* leave the lock */
-
- Mutex_unlock(recompile_thread_mutex);
-}
-
-
-/*
- * 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/recompile.h - recompilation system
-
- 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.
-
-*/
-
-
-#ifndef _RECOMPILE_H
-#define _RECOMPILE_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-
-/* list_method_entry **********************************************************/
-
-typedef struct list_method_entry list_method_entry;
-
-struct list_method_entry {
- methodinfo *m;
-/* listnode_t linkage; */
-};
-
-
-/* function prototypes ********************************************************/
-
-bool recompile_init(void);
-bool recompile_start_thread(void);
-
-void recompile_queue_method(methodinfo *m);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _RECOMPILE_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/recompiler.cpp - recompilation system
+
+ 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.h"
+
+#include "threads/condition.hpp"
+#include "threads/mutex.hpp"
+#include "threads/thread.hpp"
+
+#include "toolbox/list.hpp"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/classcache.h"
+#include "vm/exceptions.hpp"
+#include "vm/options.h"
+#include "vm/string.hpp"
+
+#include "vm/jit/code.hpp"
+#include "vm/jit/jit.hpp"
+
+#include "vm/jit/optimizing/recompiler.hpp"
+
+
+/**
+ * Stop the worker thread.
+ */
+Recompiler::~Recompiler()
+{
+ // Set the running flag to false.
+ _run = false;
+
+ // Now signal the worker thread.
+ _cond.signal();
+
+ // TODO We should wait here until the thread exits.
+}
+
+
+/* recompile_replace_vftbl *****************************************************
+
+ XXX
+
+*******************************************************************************/
+
+static void recompile_replace_vftbl(methodinfo *m)
+{
+ codeinfo *code;
+ codeinfo *pcode;
+ u4 slot;
+ classcache_name_entry *nmen;
+ classcache_class_entry *clsen;
+ classinfo *c;
+ vftbl_t *vftbl;
+ s4 i;
+
+ /* get current and previous codeinfo structure */
+
+ code = m->code;
+ pcode = code->prev;
+
+ assert(pcode);
+
+ /* iterate over all classes */
+
+ 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;
+
+ /* Search for entrypoint of the previous codeinfo in
+ the vftbl and replace it with the current one. */
+
+ vftbl = c->vftbl;
+
+ /* Is the class linked? Means, is the vftbl finished? */
+
+ if (!(c->state & CLASS_LINKED))
+ continue;
+
+ /* Does the class have a vftbl? Some internal classes
+ (e.g. $NEW$) are linked, but do not have a
+ vftbl. */
+
+ if (vftbl == NULL)
+ continue;
+
+ for (i = 0; i < vftbl->vftbllength; i++) {
+ if (vftbl->table[i] == pcode->entrypoint) {
+#if !defined(NDEBUG)
+ printf("replacing vftbl in: ");
+ class_println(c);
+#endif
+ vftbl->table[i] = code->entrypoint;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * The actual recompilation thread.
+ */
+void Recompiler::thread()
+{
+ // FIXME This just works for one recompiler.
+ Recompiler& r = VM::get_current()->get_recompiler();
+
+ while (r._run == true) {
+ // Enter the recompile mutex, so we can call wait.
+ r._mutex.lock();
+
+ // Wait forever on that condition until we are signaled.
+ r._cond.wait(r._mutex);
+
+ // Leave the mutex.
+ r._mutex.unlock();
+
+ // FIXME Move this into the for loop.
+ if (r._run == false)
+ break;
+
+ // Sanity check.
+ assert(r._methods.empty() == false);
+
+ // Get the next method form the queue and recompile it.
+ while (r._methods.empty() == false) {
+ methodinfo* m = r._methods.front();
+
+ // Recompile this method.
+ if (jit_recompile(m) != NULL) {
+ // Replace in vftbl's.
+ recompile_replace_vftbl(m);
+ }
+ else {
+ // XXX What is the right-thing(tm) to do here?
+ exceptions_print_current_exception();
+ }
+
+ // Remove the method from the queue.
+ r._methods.pop();
+ }
+ }
+}
+
+
+/**
+ * Start the recompilation thread.
+ *
+ * @return true on success, false otherwise.
+ */
+bool Recompiler::start()
+{
+ utf *name = utf_new_char("Recompiler");
+
+ if (!threads_thread_start_internal(name, (functionptr) &Recompiler::thread))
+ return false;
+
+ return true;
+}
+
+
+/**
+ * Add a method to the recompilation queue and signal the
+ * recompilation thread that there is some work to do.
+ *
+ * @param m Method to recompile.
+ */
+void Recompiler::queue_method(methodinfo *m)
+{
+ // Add the method to the queue.
+ _methods.push(m);
+
+ // Enter the recompile mutex, so we can call notify.
+ _mutex.lock();
+
+ // Signal the recompiler thread.
+ _cond.signal();
+
+ // Leave the mutex.
+ _mutex.unlock();
+}
+
+
+
+// Legacy C interface.
+extern "C" {
+ void Recompiler_queue_method(methodinfo* m) { VM::get_current()->get_recompiler().queue_method(m); }
+}
+
+
+/*
+ * 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:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/jit/optimizing/recompiler.hpp - recompilation system
+
+ 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.
+
+*/
+
+
+#ifndef _RECOMPILER_HPP
+#define _RECOMPILER_HPP
+
+#include "config.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+#include <queue>
+#endif
+
+#include "threads/condition.hpp"
+#include "threads/mutex.hpp"
+
+#include "vm/method.h"
+
+
+#ifdef __cplusplus
+
+/**
+ * Thread for JIT recompilations.
+ */
+class Recompiler {
+private:
+ Mutex _mutex;
+ Condition _cond;
+ std::queue<methodinfo*> _methods;
+ bool _run; ///< Flag to stop worker thread.
+
+ static void thread(); ///< Worker thread.
+
+public:
+ Recompiler() : _run(true) {}
+ ~Recompiler();
+
+ bool start(); ///< Start the worker thread.
+ void queue_method(methodinfo* m); ///< Queue a method for recompilation.
+};
+
+#endif
+
+/* list_method_entry **********************************************************/
+
+typedef struct list_method_entry list_method_entry;
+
+struct list_method_entry {
+ methodinfo *m;
+/* listnode_t linkage; */
+};
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void Recompiler_queue_method(methodinfo *m);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _RECOMPILER_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:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
# include "vm/jit/optimizing/profile.h"
#endif
-#include "vm/jit/optimizing/recompile.h"
+#include "vm/jit/optimizing/recompiler.hpp"
#if defined(ENABLE_PYTHON)
# include "vm/jit/python.h"
#endif
#if defined(ENABLE_THREADS)
- /* initialize recompilation */
-
- if (!recompile_init())
- os::abort("vm_create: recompile_init failed");
-
/* start the signal handler thread */
#if defined(__LINUX__)
os::abort("vm_create: memory_start_thread failed");
# endif
- /* start the recompilation thread (must be done before the
- profiling thread) */
-
- if (!recompile_start_thread())
- os::abort("vm_create: recompile_start_thread failed");
+ // Start the recompilation thread (must be done before the
+ // profiling thread).
+ // FIXME Only works for one recompiler.
+ _recompiler.start();
# if defined(ENABLE_PROFILING)
/* start the profile sampling thread */
#include "vm/properties.hpp"
+#include "vm/jit/optimizing/recompiler.hpp"
+
#ifdef __cplusplus
// Subsystems.
Properties _properties; ///< Commandline properties.
+#if defined(ENABLE_THREADS)
+ Recompiler _recompiler; ///< JIT recompilation framework.
+#endif
public:
// Constructor, Destructor.
int64_t get_starttime() { return _starttime; }
Properties& get_properties() { return _properties; }
+ Recompiler& get_recompiler() { return _recompiler; } // REMOVEME
};
#else