* src/threads/threadlist.h: Likewise.
* src/toolbox/list.c: Likewise.
* src/toolbox/list.h: Likewise.
* src/threads/threadlist.cpp: New file.
* src/threads/threadlist.hpp: Likewise.
* src/toolbox/list.cpp: Likewise.
* src/toolbox/list.hpp: Likewise.
* src/mm/dumpmemory.hpp,
src/native/vm/gnuclasspath/java_lang_VMClassLoader.cpp,
src/native/vm/openjdk/jvm.cpp,
src/threads/Makefile.am,
src/threads/lock-common.h,
src/threads/posix/lock.c,
src/threads/posix/lock.h,
src/threads/posix/thread-posix.cpp,
src/threads/posix/thread-posix.hpp,
src/threads/thread.cpp,
src/threads/thread.hpp,
src/toolbox/Makefile.am,
src/toolbox/logging.h,
src/toolbox/util.h,
src/vm/assertion.c,
src/vm/assertion.h,
src/vm/class.h,
src/vm/jit/code.hpp,
src/vm/jit/codegen-common.cpp,
src/vm/jit/codegen-common.hpp,
src/vm/jit/dseg.h,
src/vm/jit/emit-common.cpp,
src/vm/jit/linenumbertable.c,
src/vm/jit/linenumbertable.h,
src/vm/jit/optimizing/profile.c,
src/vm/jit/optimizing/recompile.c,
src/vm/jit/optimizing/recompile.h,
src/vm/jit/patcher-common.cpp,
src/vm/jit/patcher-common.hpp,
src/vm/loader.cpp,
src/vm/signal.c,
src/vm/suck.cpp,
src/vm/suck.hpp,
src/vm/vm.cpp: Related changes.
--HG--
branch : twisti
}
pointer allocate(size_type n, void* = 0) {
- printf("allocate: n=%d * %d\n", n, sizeof(T));
+// printf("allocate: n=%d * %d\n", n, sizeof(T));
return static_cast<pointer>(DumpMemory::allocate(n * sizeof(T)));
}
// Initialize elements of allocated storage p with value value.
void construct(pointer p, const T& value) {
- printf("construct: p=%p, value=%p\n", p, value);
+// printf("construct: p=%p, value=%p\n", (void*) p, (void*) value);
// Initialize memory with placement new.
new ((void*) p) T(value);
}
// Destroy elements of initialized storage p.
void destroy(pointer p) {
- printf("destroy: p=%p\n", p);
+// printf("destroy: p=%p\n", (void*) p);
// Destroy objects by calling their destructor.
p->~T();
}
void deallocate(pointer p, size_type n) {
- printf("deallocate: p=%p, n=%d\n", p, n);
+// printf("deallocate: p=%p, n=%d\n", (void*) p, n);
// We don't need to deallocate on dump memory.
}
};
#endif
#include "toolbox/logging.h"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
#if defined(ENABLE_ASSERTION)
#include "vm/assertion.h"
java_handle_t *o; /* vector being created */
methodinfo *m; /* "add" method of vector */
java_handle_t *path; /* path to be added */
- list_classpath_entry *lce; /* classpath entry */
utf *utfname; /* utf to look for */
char *buffer; /* char buffer */
char *namestart; /* start of name to use */
/* iterate over all classpath entries */
- for (lce = (list_classpath_entry*) list_first(list_classpath_entries); lce != NULL;
- lce = (list_classpath_entry*) list_next(list_classpath_entries, lce)) {
+ for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+ list_classpath_entry* lce = *it;
+
/* clear path pointer */
path = NULL;
#if defined(ENABLE_ASSERTION)
java_handle_t *js;
methodinfo *m;
- assertion_name_t *item;
#endif
/* new HashMap() */
return NULL;
}
- item = (assertion_name_t *)list_first(list_assertion_names);
+ for (List<assertion_name_t*>::iterator it = list_assertion_names->begin(); it != list_assertion_names->end(); it++) {
+ assertion_name_t* item = *it;
- while (item != NULL) {
- if (item->package == false) {
- item = (assertion_name_t *)list_next(list_assertion_names, item);
+ if (item->package == false)
continue;
- }
if (strcmp(item->name, "") == 0) {
/* unnamed package wanted */
else {
vm_call_method(m, hm, js, jfalse);
}
-
- item = (assertion_name_t *)list_next(list_assertion_names, item);
}
#endif
#if defined(ENABLE_ASSERTION)
java_handle_t *js;
methodinfo *m;
- assertion_name_t *item;
#endif
/* new HashMap() */
return NULL;
}
- item = (assertion_name_t *)list_first(list_assertion_names);
+ for (List<assertion_name_t*>::iterator it = list_assertion_names->begin(); it != list_assertion_names->end(); it++) {
+ assertion_name_t* item = *it;
- while (item != NULL) {
- if (item->package == true) {
- item = (assertion_name_t *)list_next(list_assertion_names, item);
+ if (item->package == true)
continue;
- }
js = javastring_new_from_ascii(item->name);
if (js == NULL) {
else {
vm_call_method(m, hm, js, jfalse);
}
-
- item = (assertion_name_t *)list_next(list_assertion_names, item);
}
#endif
#include "threads/thread.hpp"
#include "toolbox/logging.h"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
#include "vm/array.h"
jboolean JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls)
{
#if defined(ENABLE_ASSERTION)
- assertion_name_t *item;
classinfo *c;
jboolean status;
utf *name;
}
if (list_assertion_names != NULL) {
- item = (assertion_name_t *)list_first(list_assertion_names);
- while (item != NULL) {
+ for (List<assertion_name_t*>::iterator it = list_assertion_names->begin();
+ it != list_assertion_names->end(); it++) {
+ assertion_name_t* item = *it;
+
name = utf_new_char(item->name);
if (name == c->packagename) {
status = (jboolean)item->enabled;
else if (name == c->name) {
status = (jboolean)item->enabled;
}
-
- item = (assertion_name_t *)list_next(list_assertion_names, item);
}
}
java_booleanarray_t *classEnabled;
java_booleanarray_t *packageEnabled;
#if defined(ENABLE_ASSERTION)
- assertion_name_t *item;
java_handle_t *js;
s4 i, j;
#endif
i = 0;
j = 0;
- item = (assertion_name_t *)list_first(list_assertion_names);
- while (item != NULL) {
+ for (List<assertion_name_t*>::iterator it = list_assertion_names->begin(); it != list_assertion_names->end(); it++) {
+ assertion_name_t* item = *it;
+
js = javastring_new_from_ascii(item->name);
if (js == NULL) {
return NULL;
packageEnabled->data[j] = (jboolean) item->enabled;
j += 1;
}
-
- item = (assertion_name_t *)list_next(list_assertion_names, item);
}
}
#endif
lock-common.h \
removeme.cpp \
mutex.hpp \
- threadlist.c \
- threadlist.h \
+ threadlist.cpp \
+ threadlist.hpp \
thread.cpp \
thread.hpp
else
#include "config.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include "vm/types.h"
#include "vm/global.h"
/* functions ******************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void lock_init(void);
void lock_init_object_lock(java_object_t *);
void lock_notify_object(java_handle_t *o);
void lock_notify_all_object(java_handle_t *o);
-#endif /* ENABLE_THREADS */
-
#ifdef __cplusplus
}
#endif
+#endif /* ENABLE_THREADS */
+
#endif /* _LOCK_COMMON_H */
#include "threads/lock-common.h"
#include "threads/mutex.hpp"
-#include "threads/threadlist.h"
+#include "threads/threadlist.hpp"
#include "threads/thread.hpp"
#include "threads/posix/lock.h"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
#include "vm/exceptions.hpp"
#include "vm/finalizer.h"
lr->object = NULL;
lr->owner = NULL;
lr->count = 0;
- lr->waiters = list_create(OFFSET(lock_waiter_t, linkage));
+ lr->waiters = List_new();
#if defined(ENABLE_GC_CACAO)
/* register the lock object as weak reference with the GC */
/* Free the waiters list. */
- list_free(lr->waiters);
+ List_delete(lr->waiters);
/* Free the data structure. */
}
-/* TODO Move this function into threadlist.[ch]. */
-
-static threadobject *threads_lookup_thread_id(int index)
-{
- threadobject *t;
-
- threadlist_lock();
-
- for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
- if (t->state == THREAD_STATE_NEW)
- continue;
- if (t->index == index)
- break;
- }
-
- threadlist_unlock();
- return t;
-}
-
static void sable_flc_waiting(ptrint lockword, threadobject *t, java_handle_t *o)
{
int index;
int old_flc;
index = GET_THREAD_INDEX(lockword);
- t_other = threads_lookup_thread_id(index);
+ t_other = ThreadList_get_thread_by_index(index);
if (!t_other)
/* failure, TODO: add statistics */
return;
/* Add the waiter as last entry to waiters list. */
- list_add_last(lr->waiters, w);
+ List_push_back(lr->waiters, w);
}
static void lock_record_remove_waiter(lock_record_t *lr, threadobject *thread)
{
- list_t *l;
+ List* l;
+ void* it;
lock_waiter_t *w;
/* Get the waiters list. */
l = lr->waiters;
- for (w = list_first(l); w != NULL; w = list_next(l, w)) {
+ for (it = List_iterator_begin(l); it != List_iterator_end(l); it = List_iterator_plusplus(it)) {
+ w = (lock_waiter_t*) List_iterator_deref(it);
+
if (w->thread == thread) {
/* Remove the waiter entry from the list. */
- list_remove(l, w);
+ List_remove(l, w);
/* Free the waiter data structure. */
static void lock_record_notify(threadobject *t, lock_record_t *lr, bool one)
{
- list_t *l;
+ List* l;
+ void* it;
lock_waiter_t *w;
threadobject *waitingthread;
l = lr->waiters;
- for (w = list_first(l); w != NULL; w = list_next(l, w)) {
+ for (it = List_iterator_begin(l); it != List_iterator_end(l); it = List_iterator_plusplus(it)) {
+ w = (lock_waiter_t*) List_iterator_deref(it);
+
/* signal the waiting thread */
waitingthread = w->thread;
#include "threads/mutex.hpp"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
#include "vm/global.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/* typedefs *******************************************************************/
typedef struct lock_record_t lock_record_t;
struct lock_waiter_t {
struct threadobject *thread; /* the waiting thread */
- listnode_t linkage;
+/* listnode_t linkage; */
};
struct threadobject *owner; /* current owner of this monitor */
s4 count; /* recursive lock count */
Mutex* mutex; /* mutex for synchronizing */
- list_t *waiters; /* list of threads waiting */
+/* List *waiters; /\* list of threads waiting *\/ */
+ void* waiters;
lock_record_t *hashlink; /* next record in hash chain */
};
/* defines ********************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define LOCK_INIT_OBJECT_LOCK(o) lock_init_object_lock((java_object_t *) (o))
#define LOCK_MONITOR_ENTER(o) lock_monitor_enter((java_handle_t *) LLNI_QUICKWRAP(o))
#include "threads/condition.hpp"
#include "threads/lock-common.h"
#include "threads/mutex.hpp"
-#include "threads/threadlist.h"
+#include "threads/threadlist.hpp"
#include "threads/thread.hpp"
#include "toolbox/logging.h"
compare against 1 because the current (main thread) is also a
non-daemon thread. */
- while (threadlist_get_non_daemons() > 1)
+ while (ThreadList::get_number_of_non_daemon_threads() > 1)
cond_join->wait(mutex_join);
/* leave join mutex */
#if defined(ENABLE_ESCAPE_REASON)
void *escape_reasons;
#endif
-
- listnode_t linkage; /* threads-list */
- listnode_t linkage_free; /* free-list */
};
#include "native/native.h"
#include "threads/lock-common.h"
-#include "threads/threadlist.h"
+#include "threads/threadlist.hpp"
#include "threads/thread.hpp"
#include "vm/jit/builtin.hpp"
/* Get the main-thread (NOTE: The main thread is always the first
thread in the list). */
- t = threadlist_first();
+ t = ThreadList::get_main_thread();
/* The thread name. */
/* Lock the thread lists */
- threadlist_lock();
+ ThreadList::lock();
- index = threadlist_get_free_index();
+ index = ThreadList::get_free_thread_index();
/* Allocate a thread data structure. */
/* First, try to get one from the free-list. */
- t = threadlist_free_first();
+ t = ThreadList::get_free_thread();
if (t != NULL) {
- /* Remove from free list. */
-
- threadlist_free_remove(t);
-
/* Equivalent of MZERO on the else path */
threads_impl_thread_clear(t);
/* Add the thread to the thread list. */
- threadlist_add(t);
+ ThreadList::add_to_active_thread_list(t);
/* Unlock the thread lists. */
- threadlist_unlock();
+ ThreadList::unlock();
return t;
}
void thread_free(threadobject *t)
{
- /* Lock the thread lists. */
-
- threadlist_lock();
-
- /* Remove the thread from the thread-list. */
-
- threadlist_remove(t);
-
- /* Add the thread index to the free list. */
-
- threadlist_index_add(t->index);
-
/* Set the reference to the Java object to NULL. */
thread_set_object(t, NULL);
- /* Add the thread data structure to the free list. */
-
- threadlist_free_add(t);
+ /* Release the thread. */
- /* Unlock the thread lists. */
-
- threadlist_unlock();
+ ThreadList::release_thread(t);
}
#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
/* FIXME: In OpenJDK and CLDC the name is a char[]. */
- java_chararray_t *name;
+ //java_chararray_t *name;
/* FIXME This prints to stdout. */
utf_display_printable_ascii(utf_null);
{
/* Set the state inside a lock. */
- threadlist_lock();
+ ThreadList::lock();
if (t->state != THREAD_STATE_TERMINATED) {
t->state = THREAD_STATE_RUNNABLE;
DEBUGTHREADS("is RUNNABLE", t);
}
- threadlist_unlock();
+ ThreadList::unlock();
}
{
/* Set the state inside a lock. */
- threadlist_lock();
+ ThreadList::lock();
if (t->state != THREAD_STATE_TERMINATED) {
t->state = THREAD_STATE_WAITING;
DEBUGTHREADS("is WAITING", t);
}
- threadlist_unlock();
+ ThreadList::unlock();
}
{
/* Set the state inside a lock. */
- threadlist_lock();
+ ThreadList::lock();
if (t->state != THREAD_STATE_TERMINATED) {
t->state = THREAD_STATE_TIMED_WAITING;
DEBUGTHREADS("is TIMED_WAITING", t);
}
- threadlist_unlock();
+ ThreadList::unlock();
}
{
/* Set the state inside a lock. */
- threadlist_lock();
+ ThreadList::lock();
t->state = THREAD_STATE_TERMINATED;
DEBUGTHREADS("is TERMINATED", t);
- threadlist_unlock();
+ ThreadList::unlock();
}
#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
/* XXX This is just a quick hack. */
- threadobject* t;
- bool equal;
-
- threadlist_lock();
-
- for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
- LLNI_equals(t->object, h, equal);
-
- if (equal == true)
- break;
- }
-
- threadlist_unlock();
+ threadobject* t = ThreadList::get_thread_from_java_object(h);
#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
- log_println("threads_get_thread: IMPLEMENT ME!");
+ log_println("thread_get_thread: IMPLEMENT ME!");
threadobject* t = NULL;
#else
}
-/* threads_dump ****************************************************************
-
- Dumps info for all threads running in the JVM. This function is
- called when SIGQUIT (<ctrl>-\) is sent to CACAO.
-
-*******************************************************************************/
-
-void threads_dump(void)
-{
- threadobject *t;
-
- /* XXX we should stop the world here */
-
- /* Lock the thread lists. */
-
- threadlist_lock();
-
- printf("Full thread dump CACAO "VERSION":\n");
-
- /* iterate over all started threads */
-
- for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
- /* ignore threads which are in state NEW */
- if (t->state == THREAD_STATE_NEW)
- continue;
-
-#if defined(ENABLE_GC_CACAO)
- /* Suspend the thread. */
- /* XXX Is the suspend reason correct? */
-
- if (threads_suspend_thread(t, SUSPEND_REASON_JNI) == false)
- vm_abort("threads_dump: threads_suspend_thread failed");
-#endif
-
- /* Print thread info. */
-
- printf("\n");
- thread_print_info(t);
- printf("\n");
-
- /* Print trace of thread. */
-
- stacktrace_print_of_thread(t);
-
-#if defined(ENABLE_GC_CACAO)
- /* Resume the thread. */
-
- if (threads_resume_thread(t) == false)
- vm_abort("threads_dump: threads_resume_thread failed");
-#endif
- }
-
- /* Unlock the thread lists. */
-
- threadlist_unlock();
-}
-
-
/*
* 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
bool threads_thread_is_alive(threadobject *t);
-void threads_dump(void);
-
/* implementation specific functions */
void threads_yield(void);
-#endif /* ENABLE_THREADS */
-
#ifdef __cplusplus
}
#endif
+#endif /* ENABLE_THREADS */
+
#endif // _THREAD_HPP
+++ /dev/null
-/* src/threads/threadlist.c - different thread-lists
-
- Copyright (C) 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 <stdint.h>
-
-#include "mm/memory.h"
-
-#include "threads/mutex.hpp"
-#include "threads/threadlist.h"
-#include "threads/thread.hpp"
-
-#include "toolbox/list.h"
-
-#include "vm/options.h"
-
-
-/* global variables ***********************************************************/
-
-static Mutex* threadlist_mutex; /* global mutex for the thread list */
-
-static list_t *list_thread; /* global threads list */
-static list_t *list_thread_free; /* global free threads list */
-static list_t *list_thread_index_free;
-
-
-typedef struct thread_index_t {
- int32_t index;
- listnode_t linkage;
-} thread_index_t;
-
-
-/* threadlist_init *************************************************************
-
- Initialize thread-lists.
-
-*******************************************************************************/
-
-void threadlist_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("threadlist_init");
-
- /* Initialize the thread list mutex. */
-
- threadlist_mutex = Mutex_new();
-
- /* Initialize the thread lists. */
-
- list_thread = list_create(OFFSET(threadobject, linkage));
- list_thread_free = list_create(OFFSET(threadobject, linkage_free));
- list_thread_index_free = list_create(OFFSET(thread_index_t, linkage));
-}
-
-
-/* threadlist_lock *************************************************************
-
- Enter the thread list mutex.
-
- NOTE: We need this function as we can't use an internal lock for
- the threads lists because the thread's lock is initialized in
- threads_table_add (when we have the thread index), but we
- already need the lock at the entry of the function.
-
-*******************************************************************************/
-
-void threadlist_lock(void)
-{
- Mutex_lock(threadlist_mutex);
-}
-
-
-/* threadlist_unlock *********************************************************
-
- Leave the thread list mutex.
-
-*******************************************************************************/
-
-void threadlist_unlock(void)
-{
- Mutex_unlock(threadlist_mutex);
-}
-
-
-/* threadlist_add **************************************************************
-
- Add the given threadobject as last entry to the thread list.
-
- IN:
- t ... threadobject to be added
-
-*******************************************************************************/
-
-void threadlist_add(threadobject *t)
-{
- list_add_last(list_thread, t);
-}
-
-
-/* threadlist_remove ***********************************************************
-
- Remove the given threadobject from the thread list.
-
- IN:
- t ... threadobject to be removed
-
-*******************************************************************************/
-
-void threadlist_remove(threadobject *t)
-{
- list_remove(list_thread, t);
-}
-
-
-/* threadlist_first ************************************************************
-
- Return the first entry in the thread list.
-
- RETURN:
- threadobject of the first entry
-
-*******************************************************************************/
-
-threadobject *threadlist_first(void)
-{
- threadobject *t;
-
- t = list_first(list_thread);
-
- return t;
-}
-
-
-/* threadlist_next *************************************************************
-
- Return the next entry in the thread list.
-
- IN:
- t ... threadobject to get next thread of
-
- RETURN:
- threadobject of the next entry
-
-*******************************************************************************/
-
-threadobject *threadlist_next(threadobject *t)
-{
- threadobject *next;
-
- next = list_next(list_thread, t);
-
- return next;
-}
-
-
-/* threadlist_free_add *********************************************************
-
- Add the given threadobject as last entry to the free thread list.
-
- IN:
- t ... threadobject to be added
-
-*******************************************************************************/
-
-void threadlist_free_add(threadobject *t)
-{
- list_add_last(list_thread_free, t);
-}
-
-
-/* threadlist_free_remove ******************************************************
-
- Remove the given entry from the free thread list.
-
- IN:
- t ... threadobject to be removed
-
-*******************************************************************************/
-
-void threadlist_free_remove(threadobject *t)
-{
- list_remove(list_thread_free, t);
-}
-
-
-/* threadlist_free_first *******************************************************
-
- Return the first entry in the free thread list.
-
- RETURN:
- threadobject of the first free entry
-
-*******************************************************************************/
-
-threadobject *threadlist_free_first(void)
-{
- threadobject *t;
-
- t = list_first(list_thread_free);
-
- return t;
-}
-
-
-/* threadlist_get_non_daemons **************************************************
-
- Return the number of non-daemon threads.
-
- NOTE: This function does a linear-search over the threads list,
- because it's only used for joining the threads.
-
-*******************************************************************************/
-
-int threadlist_get_non_daemons(void)
-{
- threadobject *t;
- int nondaemons;
-
- /* Lock the thread lists. */
-
- threadlist_lock();
-
- nondaemons = 0;
-
- for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
- if (!thread_is_daemon(t))
- nondaemons++;
- }
-
- /* Unlock the thread lists. */
-
- threadlist_unlock();
-
- return nondaemons;
-}
-
-
-/* threadlist_index_first ******************************************************
-
- Return the first entry in the thread-index list.
-
- RETURN VALUE:
- thread-index structure
-
-*******************************************************************************/
-
-static inline thread_index_t *threadlist_index_first(void)
-{
- thread_index_t *ti;
-
- ti = list_first(list_thread_index_free);
-
- return ti;
-}
-
-
-/* threadlist_index_add ********************************************************
-
- Add the given thread-index to the thread-index free list.
-
- IN:
- i ... thread index
-
-*******************************************************************************/
-
-void threadlist_index_add(int index)
-{
- thread_index_t *ti;
-
- ti = NEW(thread_index_t);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_thread_index_t += sizeof(thread_index_t);
-#endif
-
- /* Set the index in the structure. */
-
- ti->index = index;
-
- list_add_last(list_thread_index_free, ti);
-}
-
-
-/* threadlist_index_remove *****************************************************
-
- Remove the given thread-index from the thread-index list and free
- the thread-index structure.
-
- IN:
- ti ... thread-index structure
-
-*******************************************************************************/
-
-static inline void threadlist_index_remove(thread_index_t *ti)
-{
- list_remove(list_thread_index_free, ti);
-
- FREE(ti, thread_index_t);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_thread_index_t -= sizeof(thread_index_t);
-#endif
-}
-
-
-/* threadlist_get_free_index ***************************************************
-
- Return a free thread index.
-
- RETURN VALUE:
- free thread index
-
-*******************************************************************************/
-
-int threadlist_get_free_index(void)
-{
- thread_index_t *ti;
- int index;
-
- /* Try to get a thread index from the free-list. */
-
- ti = threadlist_index_first();
-
- /* Is a free thread index available? */
-
- if (ti != NULL) {
- /* Yes, get the index and remove it from the free list. */
-
- index = ti->index;
-
- threadlist_index_remove(ti);
- }
- else {
- /* Get a new the thread index. */
-
- index = list_thread->size + 1;
- }
-
- return index;
-}
-
-
-/*
- * 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/threads/threadlist.cpp - thread list
+
+ Copyright (C) 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 <stdint.h>
+
+#include "threads/mutex.hpp"
+#include "threads/threadlist.hpp"
+#include "threads/thread.hpp"
+
+#include "toolbox/list.hpp"
+#include "toolbox/logging.h"
+
+
+/* class variables */
+
+Mutex ThreadList::_mutex; // a mutex for all thread lists
+
+list<threadobject*> ThreadList::_active_thread_list; // list of active threads
+list<threadobject*> ThreadList::_free_thread_list; // list of free threads
+list<int32_t> ThreadList::_free_index_list; // list of free thread indexes
+
+int32_t ThreadList::_number_of_non_daemon_threads;
+
+
+/**
+ * Dumps info for all threads running in the VM. This function is
+ * called when SIGQUIT (<ctrl>-\) is sent to the VM.
+ */
+void ThreadList::dump_threads()
+{
+ // XXX we should stop the world here
+ // Lock the thread lists.
+ lock();
+
+ printf("Full thread dump CACAO "VERSION":\n");
+
+ // Iterate over all started threads.
+ for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
+ threadobject* t = *it;
+
+ // Ignore threads which are in state NEW.
+ if (t->state == THREAD_STATE_NEW)
+ continue;
+
+#if defined(ENABLE_GC_CACAO)
+ /* Suspend the thread. */
+ /* XXX Is the suspend reason correct? */
+
+ if (threads_suspend_thread(t, SUSPEND_REASON_JNI) == false)
+ vm_abort("threads_dump: threads_suspend_thread failed");
+#endif
+
+ /* Print thread info. */
+
+ printf("\n");
+ thread_print_info(t);
+ printf("\n");
+
+ /* Print trace of thread. */
+
+ stacktrace_print_of_thread(t);
+
+#if defined(ENABLE_GC_CACAO)
+ /* Resume the thread. */
+
+ if (threads_resume_thread(t) == false)
+ vm_abort("threads_dump: threads_resume_thread failed");
+#endif
+ }
+
+ // Unlock the thread lists.
+ unlock();
+}
+
+
+/**
+ * Return a free thread object.
+ *
+ * @return free thread object or NULL if none available
+ */
+threadobject* ThreadList::get_free_thread()
+{
+ threadobject* t = NULL;
+
+ // Do we have free threads in the free-list?
+ if (_free_thread_list.empty() == false) {
+ // Yes, get the index and remove it from the free list.
+ threadobject* t = _free_thread_list.front();
+ _free_thread_list.remove(t);
+ }
+
+ return t;
+}
+
+
+/**
+ * Return a free thread index.
+ *
+ * @return free thread index
+ */
+int32_t ThreadList::get_free_thread_index()
+{
+ int32_t index;
+
+ // Do we have free indexes in the free-list?
+ if (_free_index_list.empty() == false) {
+ // Yes, get the index and remove it from the free list.
+ index = _free_index_list.front();
+ _free_index_list.remove(index);
+ }
+ else {
+ // Get a new the thread index.
+ index = _active_thread_list.size() + 1;
+ }
+
+ return index;
+}
+
+
+/**
+ * Return the number of non-daemon threads.
+ *
+ * NOTE: This function does a linear-search over the threads list,
+ * because it is only used for joining the threads.
+ *
+ * @return number of non daemon threads
+ */
+int32_t ThreadList::get_number_of_non_daemon_threads(void)
+{
+ int nondaemons = 0;
+
+ lock();
+
+ for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
+ threadobject* t = *it;
+
+ if (!thread_is_daemon(t))
+ nondaemons++;
+ }
+
+ unlock();
+
+ return nondaemons;
+}
+
+
+/**
+ * Return the thread object with the given index.
+ *
+ * @return thread object
+ */
+threadobject* ThreadList::get_thread_by_index(int32_t index)
+{
+ threadobject* t = NULL;
+
+ lock();
+
+ for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
+ t = *it;
+
+ if (t->state == THREAD_STATE_NEW)
+ continue;
+
+ if (t->index == index)
+ break;
+ }
+
+ unlock();
+
+ return t;
+}
+
+
+/**
+ * Return the Java thread object from the given thread object.
+ *
+ * @return Java thread object
+ */
+threadobject* ThreadList::get_thread_from_java_object(java_handle_t* h)
+{
+ List<threadobject*>::iterator it;
+ threadobject* t;
+ bool equal;
+
+ lock();
+
+ for (it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
+ t = *it;
+
+ LLNI_equals(t->object, h, equal);
+
+ if (equal == true) {
+ unlock();
+ return t;
+ }
+ }
+
+ unlock();
+
+ return NULL;
+}
+
+
+/**
+ * Release the thread.
+ *
+ * @return free thread index
+ */
+void ThreadList::release_thread(threadobject* t)
+{
+ lock();
+
+ // Move thread from active thread list to free thread list.
+ remove_from_active_thread_list(t);
+ add_to_free_thread_list(t);
+
+ // Add thread index to free index list.
+ add_to_free_index_list(t->index);
+
+ unlock();
+}
+
+
+/* C interface functions ******************************************************/
+
+extern "C" {
+ void ThreadList_lock() { ThreadList::lock(); }
+ void ThreadList_unlock() { ThreadList::unlock(); }
+ void ThreadList_dump_threads() { ThreadList::dump_threads(); }
+ void ThreadList_release_thread(threadobject* t) { ThreadList::release_thread(t); }
+ threadobject* ThreadList_get_free_thread() { return ThreadList::get_free_thread(); }
+ int32_t ThreadList_get_free_thread_index() { return ThreadList::get_free_thread_index(); }
+ void ThreadList_add_to_active_thread_list(threadobject* t) { ThreadList::add_to_active_thread_list(t); }
+ threadobject* ThreadList_get_thread_by_index(int32_t index) { return ThreadList::get_thread_by_index(index); }
+ threadobject* ThreadList_get_main_thread() { return ThreadList::get_main_thread(); }
+ threadobject* ThreadList_get_thread_from_java_object(java_handle_t* h) { return ThreadList::get_thread_from_java_object(h); }
+
+ int32_t ThreadList_get_number_of_non_daemon_threads() { return ThreadList::get_number_of_non_daemon_threads(); }
+}
+
+/*
+ * 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/threads/threadlist.h - different thread-lists
-
- Copyright (C) 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 _THREADLIST_H
-#define _THREADLIST_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "threads/thread.hpp"
-
-
-/* function prototypes ********************************************************/
-
-void threadlist_init(void);
-
-void threadlist_add(threadobject *t);
-void threadlist_remove(threadobject *t);
-threadobject *threadlist_first(void);
-threadobject *threadlist_next(threadobject *t);
-
-void threadlist_free_add(threadobject *t);
-void threadlist_free_remove(threadobject *t);
-threadobject *threadlist_free_first(void);
-
-int threadlist_get_non_daemons(void);
-
-void threadlist_index_add(int index);
-int threadlist_get_free_index(void);
-
-/* implementation specific functions */
-
-void threadlist_impl_init(void);
-
-void threadlist_lock(void);
-void threadlist_unlock(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _THREADLIST_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:
- * vim:noexpandtab:sw=4:ts=4:
- */
--- /dev/null
+/* src/threads/threadlist.hpp - different thread-lists
+
+ Copyright (C) 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 _THREADLIST_HPP
+#define _THREADLIST_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "threads/thread.hpp"
+
+#include "toolbox/list.hpp"
+
+
+/* ThreadList *****************************************************************/
+
+#ifdef __cplusplus
+
+using std::list;
+
+class ThreadList {
+private:
+ static Mutex _mutex; // a mutex for all thread lists
+
+ static list<threadobject*> _active_thread_list; // list of active threads
+ static list<threadobject*> _free_thread_list; // list of free threads
+ static list<int32_t> _free_index_list; // list of free thread indexes
+
+ static int32_t _number_of_non_daemon_threads;
+
+ static inline void remove_from_active_thread_list(threadobject* t);
+ static inline void add_to_free_thread_list(threadobject* t);
+ static inline void add_to_free_index_list(int32_t index);
+
+public:
+ static inline void lock() { _mutex.lock(); }
+ static inline void unlock() { _mutex.unlock(); }
+
+ // TODO make private
+ static inline void add_to_active_thread_list(threadobject* t);
+
+ static void dump_threads();
+ static inline threadobject* get_main_thread();
+ static threadobject* get_free_thread();
+ static int32_t get_free_thread_index();
+ static int32_t get_number_of_non_daemon_threads();
+ static threadobject* get_thread_by_index(int32_t index);
+ static threadobject* get_thread_from_java_object(java_handle_t* h);
+ static void release_thread(threadobject* t);
+};
+
+
+inline void ThreadList::add_to_active_thread_list(threadobject* t)
+{
+ _active_thread_list.push_back(t);
+}
+
+inline void ThreadList::remove_from_active_thread_list(threadobject* t)
+{
+ _active_thread_list.remove(t);
+}
+
+inline void ThreadList::add_to_free_thread_list(threadobject* t)
+{
+ _free_thread_list.push_back(t);
+}
+
+inline void ThreadList::add_to_free_index_list(int32_t index)
+{
+ _free_index_list.push_back(index);
+}
+
+inline threadobject* ThreadList::get_main_thread()
+{
+ return _active_thread_list.front();
+}
+
+#else
+
+typedef struct ThreadList ThreadList;
+
+void ThreadList_lock();
+void ThreadList_unlock();
+void ThreadList_dump_threads();
+void ThreadList_release_thread(threadobject* t);
+threadobject* ThreadList_get_free_thread();
+int32_t ThreadList_get_free_thread_index();
+void ThreadList_add_to_active_thread_list(threadobject* t);
+threadobject* ThreadList_get_thread_by_index(int32_t index);
+threadobject* ThreadList_get_main_thread();
+threadobject* ThreadList_get_thread_from_java_object(java_handle_t* h);
+int32_t ThreadList_get_number_of_non_daemon_threads();
+
+#endif
+
+#endif // _THREADLIST_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:
+ */
bitvector.h \
hashtable.c \
hashtable.h \
- list.c \
- list.h \
+ list.cpp \
+ list.hpp \
logging.c \
logging.h \
set.h \
+++ /dev/null
-/* src/toolbox/list.c - double linked list
-
- 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 <stdint.h>
-#include <stdlib.h>
-
-#include "mm/memory.h"
-
-#include "threads/mutex.hpp"
-
-#include "toolbox/list.h"
-
-
-/* list_create *****************************************************************
-
- Allocates a new list and initializes the lock object.
-
-*******************************************************************************/
-
-list_t *list_create(int nodeoffset)
-{
- list_t *l;
-
- l = NEW(list_t);
-
- l->mutex = Mutex_new();
- l->first = NULL;
- l->last = NULL;
- l->nodeoffset = nodeoffset;
- l->size = 0;
-
- return l;
-}
-
-
-/* list_free *******************************************************************
-
- Free a list.
-
-*******************************************************************************/
-
-void list_free(list_t *l)
-{
- assert(l != NULL);
-
- Mutex_delete(l->mutex);
-
- FREE(l, list_t);
-}
-
-
-/* list_create_dump ************************************************************
-
- Allocates a new list on the dump memory.
-
- ATTENTION: This list does NOT initialize the locking object!!!
-
-*******************************************************************************/
-
-list_t *list_create_dump(int nodeoffset)
-{
- list_t *l;
-
- l = DumpMemory_allocate(sizeof(list_t));
-
- l->mutex = NULL;
- l->first = NULL;
- l->last = NULL;
- l->nodeoffset = nodeoffset;
- l->size = 0;
-
- return l;
-}
-
-
-/* list_lock *******************************************************************
-
- Locks the list.
-
-*******************************************************************************/
-
-void list_lock(list_t *l)
-{
- Mutex_lock(l->mutex);
-}
-
-
-/* list_unlock *****************************************************************
-
- Unlocks the list.
-
-*******************************************************************************/
-
-void list_unlock(list_t *l)
-{
- Mutex_unlock(l->mutex);
-}
-
-
-/* list_add_first **************************************************************
-
- Adds the element as first element.
-
-*******************************************************************************/
-
-void list_add_first(list_t *l, void *element)
-{
- listnode_t *ln;
-
- ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-
- if (l->first) {
- ln->prev = NULL;
- ln->next = l->first;
- l->first->prev = ln;
- l->first = ln;
- }
- else {
- ln->prev = NULL;
- ln->next = NULL;
- l->last = ln;
- l->first = ln;
- }
-
- /* Increase number of elements. */
-
- l->size++;
-}
-
-
-/* list_add_last ***************************************************************
-
- Adds the element as last element.
-
-*******************************************************************************/
-
-void list_add_last(list_t *l, void *element)
-{
- listnode_t *ln;
-
- ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-
- if (l->last) {
- ln->prev = l->last;
- ln->next = NULL;
- l->last->next = ln;
- l->last = ln;
- }
- else {
- ln->prev = NULL;
- ln->next = NULL;
- l->last = ln;
- l->first = ln;
- }
-
- /* Increase number of elements. */
-
- l->size++;
-}
-
-
-/* list_add_before *************************************************************
-
- Adds the element newelement to the list l before element.
-
- [ A ] <-> [ newn ] <-> [ n ] <-> [ B ]
-
-*******************************************************************************/
-
-void list_add_before(list_t *l, void *element, void *newelement)
-{
- listnode_t *ln;
- listnode_t *newln;
-
- ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
- newln = (listnode_t *) (((uint8_t *) newelement) + l->nodeoffset);
-
- /* Set the new links. */
-
- newln->prev = ln->prev;
- newln->next = ln;
-
- if (newln->prev)
- newln->prev->next = newln;
-
- ln->prev = newln;
-
- /* set list's first and last if necessary */
-
- if (l->first == ln)
- l->first = newln;
-
- if (l->last == ln)
- l->last = newln;
-
- /* Increase number of elements. */
-
- l->size++;
-}
-
-
-/* list_remove ***************************************************************
-
- Removes the element.
-
-*******************************************************************************/
-
-void list_remove(list_t *l, void *element)
-{
- listnode_t *ln;
-
- ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-
- if (ln->next)
- ln->next->prev = ln->prev;
- else
- l->last = ln->prev;
-
- if (ln->prev)
- ln->prev->next = ln->next;
- else
- l->first = ln->next;
-
- ln->next = NULL;
- ln->prev = NULL;
-
- /* Decrease number of elements. */
-
- l->size--;
-}
-
-
-/* list_first ******************************************************************
-
- Returns the first element of the list.
-
-*******************************************************************************/
-
-void *list_first(list_t *l)
-{
- void *el;
-
- if (l->first == NULL)
- el = NULL;
- else
- el = ((uint8_t *) l->first) - l->nodeoffset;
-
- return el;
-}
-
-
-/* list_last *******************************************************************
-
- Returns the last element of the list.
-
-*******************************************************************************/
-
-void *list_last(list_t *l)
-{
- void *el;
-
- if (l->last == NULL)
- el = NULL;
- else
- el = ((uint8_t *) l->last) - l->nodeoffset;
-
- return el;
-}
-
-
-/* list_next *******************************************************************
-
- Returns the next element of element from the list.
-
-*******************************************************************************/
-
-void *list_next(list_t *l, void *element)
-{
- listnode_t *ln;
- void *el;
-
- ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-
- if (ln->next == NULL)
- el = NULL;
- else
- el = ((uint8_t *) ln->next) - l->nodeoffset;
-
- return el;
-}
-
-
-/* list_prev *******************************************************************
-
- Returns the previous element of element from the list.
-
-*******************************************************************************/
-
-void *list_prev(list_t *l, void *element)
-{
- listnode_t *ln;
- void *el;
-
- ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-
- if (ln->prev == NULL)
- el = NULL;
- else
- el = ((uint8_t *) ln->prev) - l->nodeoffset;
-
- return el;
-}
-
-
-/*
- * 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/toolbox/list.cpp - linked list
+
+ 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 <stdint.h>
+
+#include "mm/memory.h"
+
+#include "threads/mutex.hpp"
+
+#include "toolbox/list.hpp"
+
+
+/* list_add_before *************************************************************
+
+ Adds the element newelement to the list l before element.
+
+ [ A ] <-> [ newn ] <-> [ n ] <-> [ B ]
+
+*******************************************************************************/
+
+#if 0
+void list_add_before(list_t *l, void *element, void *newelement)
+{
+ listnode_t *ln;
+ listnode_t *newln;
+
+ ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
+ newln = (listnode_t *) (((uint8_t *) newelement) + l->nodeoffset);
+
+ /* Set the new links. */
+
+ newln->prev = ln->prev;
+ newln->next = ln;
+
+ if (newln->prev)
+ newln->prev->next = newln;
+
+ ln->prev = newln;
+
+ /* set list's first and last if necessary */
+
+ if (l->first == ln)
+ l->first = newln;
+
+ if (l->last == ln)
+ l->last = newln;
+
+ /* Increase number of elements. */
+
+ l->size++;
+}
+#endif
+
+
+/* C interface functions ******************************************************/
+
+extern "C" {
+ List<void*>* List_new(void) { return new List<void*>(); }
+ void List_delete(List<void*>* l) { delete(l); }
+
+ void* List_back(List<void*>* l) { return l->back(); }
+ void* List_front(List<void*>* l) { return l->front(); }
+ void List_push_back(List<void*>* l, void* e) { l->push_back(e); }
+ void List_push_front(List<void*>* l, void* e) { l->push_front(e); }
+ void List_remove(List<void*>* l, void* e) { l->remove(e); }
+ int List_size(List<void*>* l) { return l->size(); }
+
+ void List_lock(List<void*>* l) { l->lock(); }
+ void List_unlock(List<void*>* l) { l->unlock(); }
+
+ List<void*>::iterator List_iterator_begin(List<void*>* l) { return l->begin(); }
+ List<void*>::iterator List_iterator_end(List<void*>* l) { return l->end(); }
+ List<void*>::iterator List_iterator_plusplus(List<void*>::iterator it) { return ++it; }
+
+ void* List_iterator_deref(List<void*>::iterator it) { return *it; }
+
+ List<void*>::reverse_iterator List_rbegin(List<void*>* l) { return l->rbegin(); }
+ List<void*>::reverse_iterator List_rend(List<void*>* l) { return l->rend(); }
+ List<void*>::reverse_iterator List_reverse_iterator_plusplus(List<void*>::reverse_iterator it) { return ++it; }
+
+ void* List_reverse_iterator_deref(List<void*>::reverse_iterator it) { return *it; }
+
+ DumpList<void*>* DumpList_new(void) { return new DumpList<void*>(); }
+ void DumpList_push_back(DumpList<void*>* l, void* e) { l->push_back(e); }
+ void DumpList_push_front(DumpList<void*>* l, void* e) { l->push_front(e); }
+ void DumpList_remove(DumpList<void*>* l, void* e) { l->remove(e); }
+
+ DumpList<void*>::iterator DumpList_iterator_begin(DumpList<void*>* l) { return l->begin(); }
+ DumpList<void*>::iterator DumpList_iterator_end(DumpList<void*>* l) { return l->end(); }
+ DumpList<void*>::iterator DumpList_iterator_plusplus(DumpList<void*>::iterator it) { return ++it; }
+
+ void* DumpList_iterator_deref(DumpList<void*>::iterator it) { return *it; }
+}
+
+
+/*
+ * 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/toolbox/list.h - synchronized linked list
-
- 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 _TOOLBOX_LIST_H
-#define _TOOLBOX_LIST_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "vm/global.h"
-
-#include "threads/mutex.hpp"
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* ---------------------- interface description -----------------------------
-
-The list management with this module works like this:
-
- - to be used in a list, a structure must have an element of type
- 'listnode'.
-
- - there needs to be a structure of type 'list'.
-
- - the function list_init(l, nodeoffset) initializes the structure.
- nodeoffset is the offset of the 'listnode' from the start of the
- structure in bytes.
-
- - The remaining functions provide inserting, removing and searching.
-
-This small example aims to demonstrate correct usage:
-
-
-
- void bsp() {
- struct node {
- listnode linkage;
- int value;
- } a,b,c, *el;
-
- list l;
-
- a.value = 7;
- b.value = 9;
- c.value = 11;
-
- list_init (&l, OFFSET(struct node,linkage) );
- list_addlast (&l, a);
- list_addlast (&l, b);
- list_addlast (&l, c);
-
- e = list_first (&l);
- while (e) {
- printf ("Element: %d\n", e->value);
- e = list_next (&l,e);
- }
- }
-
-
- The output from this program should be:
- 7
- 9
- 11
-
-
-
-The reason for the usage of 'nodeoffset' is that this way, the same node can
-part of different lists (there must be one 'listnode' element for every
-distinct list).
-
-*/
-
-/* listnode_t *****************************************************************/
-
-typedef struct listnode_t listnode_t;
-
-struct listnode_t {
- listnode_t *next;
- listnode_t *prev;
-};
-
-
-/* list_t *********************************************************************/
-
-typedef struct list_t list_t;
-
-struct list_t {
- Mutex* mutex; /* threads lock object */
- listnode_t *first;
- listnode_t *last;
- int nodeoffset;
- int size; /* number of elements in the list */
-};
-
-
-/* function prototypes ********************************************************/
-
-list_t *list_create(int nodeoffset);
-list_t *list_create_dump(int nodeoffset);
-
-void list_free(list_t *l);
-
-void list_lock(list_t *l);
-void list_unlock(list_t *l);
-
-void list_add_first(list_t *l, void *element);
-void list_add_last(list_t *l, void *element);
-void list_add_before(list_t *l, void *element, void *newelement);
-
-void list_remove(list_t *l, void *element);
-
-void *list_first(list_t *l);
-void *list_last(list_t *l);
-
-void *list_next(list_t *l, void *element);
-void *list_prev(list_t *l, void *element);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _TOOLBOX_LIST_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/toolbox/list.hpp - linked list
+
+ 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 _LIST_HPP
+#define _LIST_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+#include <list>
+#endif
+
+#include "threads/mutex.hpp"
+
+
+#ifdef __cplusplus
+
+/**
+ * List implementation with a Mutex.
+ */
+template<class T> class List : protected std::list<T> {
+private:
+ Mutex _mutex;
+
+public:
+ virtual ~List() {}
+
+ void lock () { _mutex.lock(); }
+ void unlock() { _mutex.unlock(); }
+
+ // make iterator of std::list visible
+ using std::list<T>::iterator;
+ using std::list<T>::reverse_iterator;
+
+ // make functions of std::list visible
+ using std::list<T>::back;
+ using std::list<T>::begin;
+ using std::list<T>::clear;
+ using std::list<T>::empty;
+ using std::list<T>::end;
+ using std::list<T>::front;
+ using std::list<T>::push_back;
+ using std::list<T>::push_front;
+ using std::list<T>::rbegin;
+ using std::list<T>::remove;
+ using std::list<T>::rend;
+ using std::list<T>::size;
+};
+
+
+// Required by DumpList.
+#include "mm/dumpmemory.hpp"
+
+
+/**
+ * List implementation with dump memory.
+ */
+template<class T> class DumpList : protected std::list<T, DumpMemoryAllocator<T> > {
+public:
+ virtual ~DumpList() {}
+
+ // make iterator of std::list visible
+ using std::list<T, DumpMemoryAllocator<T> >::iterator;
+ using std::list<T, DumpMemoryAllocator<T> >::reverse_iterator;
+
+ // make functions of std::list visible
+ using std::list<T, DumpMemoryAllocator<T> >::back;
+ using std::list<T, DumpMemoryAllocator<T> >::begin;
+ using std::list<T, DumpMemoryAllocator<T> >::clear;
+ using std::list<T, DumpMemoryAllocator<T> >::empty;
+ using std::list<T, DumpMemoryAllocator<T> >::end;
+ using std::list<T, DumpMemoryAllocator<T> >::front;
+ using std::list<T, DumpMemoryAllocator<T> >::push_back;
+ using std::list<T, DumpMemoryAllocator<T> >::push_front;
+ using std::list<T, DumpMemoryAllocator<T> >::rbegin;
+ using std::list<T, DumpMemoryAllocator<T> >::remove;
+ using std::list<T, DumpMemoryAllocator<T> >::rend;
+ using std::list<T, DumpMemoryAllocator<T> >::size;
+
+ void* operator new(size_t size) {
+ return DumpMemory::allocate(size);
+ }
+
+ void operator delete(void* p) {}
+};
+
+#else
+
+typedef struct List List;
+typedef struct DumpList DumpList;
+
+void* List_new(void);
+void List_delete(List* l);
+
+void* List_back(List* l);
+void* List_front(List* l);
+void List_push_back(List* l, void* e);
+void List_push_front(List* l, void* e);
+void List_remove(List* l, void* e);
+int List_size(List* l);
+
+void List_lock(List* l);
+void List_unlock(List* l);
+
+void* List_iterator_begin(List* l);
+void* List_iterator_end(List* l);
+void* List_rbegin(List* l);
+void* List_rend(List* l);
+
+void* List_iterator_plusplus(void* it);
+void* List_iterator_deref(void* it);
+
+void* List_reverse_iterator_plusplus(void* it);
+void* List_reverse_iterator_deref(void* it);
+
+void* DumpList_new(void);
+void DumpList_push_back(DumpList* l, void* e);
+void DumpList_push_front(DumpList* l, void* e);
+void DumpList_remove(DumpList* l, void* e);
+
+void* DumpList_iterator_begin(DumpList* l);
+void* DumpList_iterator_end(DumpList* l);
+
+void* DumpList_iterator_plusplus(void* it);
+void* DumpList_iterator_deref(void* it);
+#endif
+
+#endif // _LIST_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:
+ */
#include "vm/utf8.h"
+/* function prototypes ********************************************************/
+
#ifdef __cplusplus
extern "C" {
#endif
-/* function prototypes ********************************************************/
-
void log_init(const char *fname);
void log_start(void);
#ifndef _UTIL_H
#define _UTIL_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include "config.h"
#include <stdarg.h>
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
char *_Jv_getcwd(void);
int get_variable_message_length(const char *fmt, va_list ap);
#include "mm/memory.h"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
#include "vm/assertion.h"
#include "vm/global.h"
/* -ea/-da options ************************************************************/
-list_t *list_assertion_names = (list_t *)NULL;
+List* list_assertion_names = NULL;
int32_t assertion_class_count = 0;
int32_t assertion_package_count = 0;
bool assertion_user_enabled = false;
item->package = package;
if (list_assertion_names == NULL) {
- list_assertion_names = list_create(OFFSET(assertion_name_t, linkage));
+ list_assertion_names = List_new();
}
- list_add_last(list_assertion_names, item);
+ List_push_back(list_assertion_names, item);
}
#include <stdint.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/global.h"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
typedef struct assertion_name_t assertion_name_t;
char *name;
bool enabled;
bool package;
- listnode_t linkage;
+/* listnode_t linkage; */
};
/* -ea/-esa/-da/-dsa options **************************************************/
-extern list_t *list_assertion_names;
-extern int32_t assertion_class_count;
-extern int32_t assertion_package_count;
-extern bool assertion_user_enabled;
-extern bool assertion_system_enabled;
+#ifdef __cplusplus
+extern List<assertion_name_t*>* list_assertion_names;
+#else
+extern List* list_assertion_names;
+#endif
+
+extern int32_t assertion_class_count;
+extern int32_t assertion_package_count;
+extern bool assertion_user_enabled;
+extern bool assertion_system_enabled;
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void assertion_ea_da(const char *name, bool enabled);
#ifdef __cplusplus
#include "vm/types.h"
-#include "toolbox/list.h"
-
#if defined(ENABLE_JAVASE)
# include "vm/annotation.h"
#endif
#include "vm/types.h"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
#include "vm/global.h"
#include "vm/method.h"
#include "vm/jit/exceptiontable.h"
#include "vm/jit/linenumbertable.h"
#include "vm/jit/methodheader.h"
+#include "vm/jit/patcher-common.hpp"
#include "vm/jit/replace.hpp"
linenumbertable_t *linenumbertable;
/* patcher list */
- list_t *patchers;
+#ifdef __cplusplus
+ List<patchref_t>* patchers;
+#else
+ List* patchers;
+#endif
/* replacement */
s4 stackframesize; /* size of the stackframe in slots */
#include "mm/memory.h"
#include "toolbox/avl.h"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
#include "toolbox/logging.h"
#include "native/llni.h"
cd->datareferences = NULL;
#endif
- cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
- cd->linenumbers = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
+ cd->brancheslabel = new DumpList<branch_label_ref_t*>();
+ cd->linenumbers = new DumpList<linenumbertable_list_entry_t*>();
}
cd->datareferences = NULL;
#endif
- cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
- cd->linenumbers = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
+ cd->brancheslabel = new DumpList<branch_label_ref_t*>();
+ cd->linenumbers = new DumpList<linenumbertable_list_entry_t*>();
/* We need to clear the mpc and the branch references from all
basic blocks as they will definitely change. */
void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
{
- list_t *l;
- branch_label_ref_t *br;
- s4 mpc;
+ // Calculate the current mpc.
+ int32_t mpc = cd->mcodeptr - cd->mcodebase;
- /* Get the label list. */
-
- l = cd->brancheslabel;
-
- /* calculate the current mpc */
-
- mpc = cd->mcodeptr - cd->mcodebase;
-
- br = (branch_label_ref_t*) DumpMemory::allocate(sizeof(branch_label_ref_t));
+ branch_label_ref_t* br = (branch_label_ref_t*) DumpMemory::allocate(sizeof(branch_label_ref_t));
br->mpc = mpc;
br->label = label;
br->reg = reg;
br->options = options;
- /* Add the branch to the list. */
-
- list_add_last(l, br);
+ // Add the branch to the list.
+ cd->brancheslabel->push_back(br);
}
-/* src/vm/jit/codegen-common.h - architecture independent code generator stuff
+/* src/vm/jit/codegen-common.hpp - architecture independent code generator stuff
Copyright (C) 1996-2005, 2006, 2007, 2008
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
#include "config.h"
#include "vm/types.h"
+#include "toolbox/list.hpp"
+
#include "vm/jit/builtin.hpp"
#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/jit.hpp"
#include "vm/jit/reg.h"
#include "vm/jit/code.hpp"
+#include "vm/jit/linenumbertable.h"
#include "vm/jit/replace.hpp"
dataref *datareferences; /* list of data segment references */
#endif
- list_t *brancheslabel;
- list_t *linenumbers; /* list of line numbers */
+#ifdef __cplusplus
+ DumpList<branch_label_ref_t*>* brancheslabel;
+ DumpList<linenumbertable_list_entry_t*>* linenumbers; ///< List of line numbers.
+#else
+ // REMOVEME
+ DumpList* brancheslabel;
+ DumpList* linenumbers;
+#endif
methodinfo *method;
s4 condition; /* conditional branch condition */
s4 reg; /* register number to check */
u4 options; /* branch options */
- listnode_t linkage;
+/* listnode_t linkage; */
};
#include "config.h"
#include "vm/types.h"
-#include "toolbox/list.h"
-
#include "vm/references.h"
#include "vm/jit/jit.hpp"
#include <assert.h>
#include <stdint.h>
+#include <algorithm>
+
#include "vm/types.h"
#include "arch.h"
#include "codegen.h"
+#include "toolbox/list.hpp"
+
#include "vm/options.h"
#include "vm/statistics.h"
{
codegendata *cd;
codeinfo *code;
- patchref_t *pr;
u1 *savedmcodeptr;
u1 *tmpmcodeptr;
uint32_t mcode;
cd = jd->cd;
code = jd->code;
- /* generate patcher traps code */
-
- for (pr = (patchref_t*) list_first(code->patchers); pr != NULL; pr = (patchref_t*) list_next(code->patchers, pr)) {
+ // Generate patcher traps code.
+ for (List<patchref_t>::iterator it = code->patchers->begin(); it != code->patchers->end(); it++) {
+ patchref_t& pr = *it;
/* Calculate the patch position where the original machine
code is located and the trap should be placed. */
- tmpmcodeptr = (u1 *) (cd->mcodebase + pr->mpc);
+ tmpmcodeptr = (u1 *) (cd->mcodebase + pr.mpc);
/* Patch in the trap to call the signal handler (done at
compile time). */
/* Remember the original machine code which is patched
back in later (done at runtime). */
- pr->mcode = mcode;
+ pr.mcode = mcode;
}
}
void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
{
- list_t *list;
- branch_label_ref_t *br;
- s4 mpc;
- s4 disp;
-
- /* get the label list */
-
- list = cd->brancheslabel;
-
- /* search if the label is already in the list */
+ // Search if the label is already in the list.
+ DumpList<branch_label_ref_t*>::iterator it;
+ for (it = cd->brancheslabel->begin(); it != cd->brancheslabel->end(); it++) {
+ branch_label_ref_t* br = *it;
- for (br = (branch_label_ref_t*) list_first(list); br != NULL; br = (branch_label_ref_t*) list_next(list, br)) {
/* is this entry the correct label? */
if (br->label == label)
break;
}
- if (br == NULL) {
+ if (it == cd->brancheslabel->end()) {
/* current mcodeptr is the correct position,
afterwards emit the NOPs */
return;
}
- /* Branch reference was found. */
+ // Branch reference was found.
+ branch_label_ref_t* br = *it;
/* calculate the mpc of the branch instruction */
- mpc = cd->mcodeptr - cd->mcodebase;
- disp = br->mpc - mpc;
+ int32_t mpc = cd->mcodeptr - cd->mcodebase;
+ int32_t disp = br->mpc - mpc;
#if defined(ENABLE_STATISTICS)
count_emit_branch++;
emit_branch(cd, disp, condition, reg, options);
- /* now remove the branch reference */
-
- list_remove(list, br);
+ // Now remove the branch reference.
+ cd->brancheslabel->remove(br);
}
void emit_label(codegendata *cd, s4 label)
{
- list_t *list;
- branch_label_ref_t *br;
- s4 mpc;
- s4 disp;
- u1 *mcodeptr;
-
- /* get the label list */
-
- list = cd->brancheslabel;
+ u1* mcodeptr;
- /* search if the label is already in the list */
+ // Search if the label is already in the list.
+ DumpList<branch_label_ref_t*>::iterator it;
+ for (it = cd->brancheslabel->begin(); it != cd->brancheslabel->end(); it++) {
+ branch_label_ref_t* br = *it;
- for (br = (branch_label_ref_t*) list_first(list); br != NULL; br = (branch_label_ref_t*) list_next(list, br)) {
/* is this entry the correct label? */
if (br->label == label)
break;
}
- if (br == NULL) {
+ if (it == cd->brancheslabel->end()) {
/* No branch reference found, add the label to the list (use
invalid values for condition and register). */
return;
}
- /* Branch reference was found. */
+ // Branch reference was found.
+ branch_label_ref_t* br = *it;
- /* calculate the mpc of the branch instruction */
-
- mpc = cd->mcodeptr - cd->mcodebase;
- disp = mpc - br->mpc;
+ // Calculate the mpc of the branch instruction.
+ int32_t mpc = cd->mcodeptr - cd->mcodebase;
+ int32_t disp = mpc - br->mpc;
/* temporary set the mcodeptr */
cd->mcodeptr = mcodeptr;
- /* now remove the branch reference */
-
- list_remove(list, br);
+ // Now remove the branch reference.
+ cd->brancheslabel->remove(br);
}
#include "mm/memory.h"
+#include "toolbox/list.hpp"
+
#if defined(ENABLE_STATISTICS)
# include "vm/options.h"
# include "vm/statistics.h"
codegendata *cd;
linenumbertable_t *lnt;
linenumbertable_entry_t *lnte;
- list_t *l;
+ List* l;
+ void* it;
linenumbertable_list_entry_t *le;
uint8_t *pv;
void *pc;
l = cd->linenumbers;
- if (l->size == 0)
+ if (List_size(l) == 0)
return;
/* Allocate the linenumber table and the entries array. */
lnt = NEW(linenumbertable_t);
- lnte = MNEW(linenumbertable_entry_t, l->size);
+ lnte = MNEW(linenumbertable_entry_t, List_size(l));
#if defined(ENABLE_STATISTICS)
if (opt_stat) {
size_linenumbertable +=
sizeof(linenumbertable_t) +
- sizeof(linenumbertable_entry_t) * l->size;
+ sizeof(linenumbertable_entry_t) * List_size(l);
}
#endif
/* Fill the linenumber table. */
- lnt->length = l->size;
+ lnt->length = List_size(l);
lnt->entries = lnte;
/* Fill the linenumber table entries in reverse order, so the
pv = ADDR_MASK(uint8_t *, code->entrypoint);
- for (le = list_first(l); le != NULL; le = list_next(l, le), lnte++) {
+ for (it = List_iterator_begin(l); it != List_iterator_end(l); it = List_iterator_plusplus(it), lnte++) {
+ le = (linenumbertable_list_entry_t*) List_iterator_deref(it);
/* If the entry contains an mcode pointer (normal case),
resolve it (see doc/inlining_stacktrace.txt for
details). */
le->linenumber = linenumber;
le->mpc = cd->mcodeptr - cd->mcodebase;
- list_add_first(cd->linenumbers, le);
+ DumpList_push_front(cd->linenumbers, le);
}
le->linenumber = (-2); /* marks start of inlined method */
le->mpc = (mpc = cd->mcodeptr - cd->mcodebase);
- list_add_first(cd->linenumbers, le);
+ DumpList_push_front(cd->linenumbers, le);
insinfo = iptr->sx.s23.s3.inlineinfo;
le->linenumber = (-3) - iptr->line;
le->mpc = (uintptr_t) insinfo->method;
- list_add_first(cd->linenumbers, le);
+ DumpList_push_front(cd->linenumbers, le);
le = DNEW(linenumbertable_list_entry_t);
le->linenumber = (-1);
le->mpc = insinfo->startmpc;
- list_add_first(cd->linenumbers, le);
+ DumpList_push_front(cd->linenumbers, le);
}
* Emacs will automagically detect them.
* ---------------------------------------------------------------------
* Local variables:
- * mode: c
+ * mode: c++
* indent-tabs-mode: t
* c-basic-offset: 4
* tab-width: 4
#include <stdint.h>
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
#include "vm/method.h"
extern "C" {
#endif
+/* LinenumberTable */
+
+#ifdef __cplusplus
+
+class LinenumberTable {
+public:
+ static void create(jitdata* jd);
+};
+
+#endif
+
+
/* linenumbertable_t **********************************************************/
struct linenumbertable_t {
/* instruction for given line */
/* NOTE: for linenumber <= -3 this is a the */
/* (methodinfo *) of the inlined method */
- listnode_t linkage;
+/* listnode_t linkage; */
};
* Emacs will automagically detect them.
* ---------------------------------------------------------------------
* Local variables:
- * mode: c
+ * mode: c++
* indent-tabs-mode: t
* c-basic-offset: 4
* tab-width: 4
#include "mm/memory.h"
-#include "threads/threadlist.h"
+#include "threads/threadlist.hpp"
#include "threads/thread.hpp"
#include "vm/jit/builtin.hpp"
threads_sleep(0, nanos);
runs++;
- /* lock the threads lists */
-
- threadlist_lock();
+ // Lock the thread lists.
+ ThreadList_lock();
/* iterate over all started threads */
- for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
+ for (t = ThreadList_first(); t != NULL; t = ThreadList_next(t)) {
/* is this a Java thread? */
if (!(t->flags & THREAD_FLAG_JAVA))
}
}
- /* unlock the threads lists */
-
- threadlist_unlock();
+ // Unlock the thread lists.
+ ThreadList_unlock();
}
}
#endif
#if !defined(NDEBUG)
void profile_printstats(void)
{
- list_t *l;
- list_method_entry *lme;
- list_method_entry *tlme;
classinfo *c;
methodinfo *m;
codeinfo *code;
cycles = 0;
/* create new method list */
-
- l = list_create(OFFSET(list_method_entry, linkage));
+ // TODO Use a sorted container.
+ List* l = List_new();
/* iterate through all classes and methods */
frequency += code->frequency;
cycles += code->cycles;
- /* create new list entry */
-
- lme = NEW(list_method_entry);
- lme->m = m;
-
/* sort the new entry into the list */
- if ((tlme = list_first(l)) == NULL) {
- list_add_first(l, lme);
+ if (List_empty(l) == NULL) {
+ List_push_back(l, m);
}
else {
for (; tlme != NULL; tlme = list_next(l, tlme)) {
#include "threads/mutex.hpp"
#include "threads/thread.hpp"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
#include "vm/jit/builtin.hpp"
#include "vm/classcache.h"
static Mutex *recompile_thread_mutex;
static Condition *recompile_thread_cond;
-static list_t *list_recompile_methods;
+static List* list_recompile_methods;
/* recompile_init **************************************************************
/* create method list */
- list_recompile_methods = list_create(OFFSET(list_method_entry, linkage));
+ list_recompile_methods = List_new();
/* everything's ok */
/* get the next method and recompile it */
- while ((lme = list_first(list_recompile_methods)) != NULL) {
+ while ((lme = List_front(list_recompile_methods)) != NULL) {
/* recompile this method */
if (jit_recompile(lme->m) != NULL) {
/* remove the compiled method */
- list_remove(list_recompile_methods, lme);
+ List_remove(list_recompile_methods, lme);
/* free the entry */
/* and add it to the list */
- list_add_last(list_recompile_methods, lme);
+ List_push_back(list_recompile_methods, lme);
/* get the lock on the recompile mutex, so we can call notify */
struct list_method_entry {
methodinfo *m;
- listnode_t linkage;
+/* listnode_t linkage; */
};
#include <assert.h>
#include <stdint.h>
+#include <algorithm>
+#include <functional>
+
#include "codegen.h" /* for PATCHER_NOPS */
#include "md.h"
#include "native/native.h"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
#include "toolbox/logging.h" /* XXX remove me! */
#include "vm/exceptions.hpp"
void patcher_list_create(codeinfo *code)
{
- code->patchers = list_create(OFFSET(patchref_t, linkage));
+ code->patchers = new List<patchref_t>();
}
void patcher_list_reset(codeinfo *code)
{
- patchref_t *pr;
-
- /* free all elements of the list */
-
- while((pr = (patchref_t*) list_first(code->patchers)) != NULL) {
- list_remove(code->patchers, pr);
-
- FREE(pr, patchref_t);
-
#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_patchref -= sizeof(patchref_t);
+ if (opt_stat)
+ size_patchref -= sizeof(patchref_t) * code->patchers->size();
#endif
- }
+
+ // Free all elements of the list.
+ code->patchers->clear();
}
/* patcher_list_free ***********************************************************
void patcher_list_free(codeinfo *code)
{
- /* free all elements of the list */
-
+ // Free all elements of the list.
patcher_list_reset(code);
- /* free the list itself */
-
- list_free(code->patchers);
+ // Free the list itself.
+ delete code->patchers;
}
-/* patcher_list_find ***********************************************************
-
- Find an entry inside the patcher list for the given codeinfo
- by specifying the program counter of the patcher position.
-
- NOTE: Caller should hold the patcher list lock or maintain
- exclusive access otherwise.
+/**
+ * Find an entry inside the patcher list for the given codeinfo by
+ * specifying the program counter of the patcher position.
+ *
+ * NOTE: Caller should hold the patcher list lock or maintain
+ * exclusive access otherwise.
+ *
+ * @param pc Program counter to find.
+ *
+ * @return Pointer to patcher.
+ */
-*******************************************************************************/
+struct foo : public std::binary_function<patchref_t, void*, bool> {
+ bool operator() (const patchref_t& pr, const void* pc) const
+ {
+ return (pr.mpc == (uintptr_t) pc);
+ }
+};
-static patchref_t *patcher_list_find(codeinfo *code, void *pc)
+static patchref_t* patcher_list_find(codeinfo* code, void* pc)
{
- patchref_t *pr;
-
- /* walk through all patcher references for the given codeinfo */
-
- pr = (patchref_t*) list_first(code->patchers);
-
- while (pr) {
-
-/*#define TRACE_PATCHER_FIND*/
-#ifdef TRACE_PATCHER_FIND
- log_println("patcher_list_find: %p == %p", pr->mpc, pc);
-#endif
-
- if (pr->mpc == (ptrint) pc)
- return pr;
+ // Search for a patcher with the given PC.
+ List<patchref_t>::iterator it = std::find_if(code->patchers->begin(), code->patchers->end(), std::bind2nd(foo(), pc));
- pr = (patchref_t*) list_next(code->patchers, pr);
- }
+ if (it == code->patchers->end())
+ return NULL;
- return NULL;
+ return &(*it);
}
{
codegendata *cd;
codeinfo *code;
- patchref_t *pr;
s4 patchmpc;
cd = jd->cd;
vm_abort("patcher_add_patch_ref: different patchers at same position.");
#endif
- /* allocate patchref on heap (at least freed together with codeinfo) */
+ // Set patcher information (mpc is resolved later).
+ patchref_t pr;
+
+ pr.mpc = patchmpc;
+ pr.disp = disp;
+ pr.patcher = patcher;
+ pr.ref = ref;
+ pr.mcode = 0;
+ pr.done = false;
- pr = NEW(patchref_t);
- list_add_first(code->patchers, pr);
+ // Store patcher in the list (NOTE: structure is copied).
+ code->patchers->push_back(pr);
#if defined(ENABLE_STATISTICS)
if (opt_stat)
size_patchref += sizeof(patchref_t);
#endif
- /* set patcher information (mpc is resolved later) */
-
- pr->mpc = patchmpc;
- pr->disp = disp;
- pr->patcher = patcher;
- pr->ref = ref;
- pr->mcode = 0;
- pr->done = false;
-
#if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__SPARC_64__) || defined(__X86_64__))
/* XXX We can remove that when we don't use UD2 anymore on i386
*/
void patcher_resolve(jitdata* jd)
{
- codeinfo* code;
- patchref_t* pr;
+ // Get required compiler data.
+ codeinfo* code = jd->code;
- /* Get required compiler data. */
+ for (List<patchref_t>::iterator it = code->patchers->begin(); it != code->patchers->end(); it++) {
+ patchref_t& pr = *it;
- code = jd->code;
-
- for (pr = (patchref_t*) list_first(code->patchers); pr != NULL; pr = (patchref_t*) list_next(code->patchers, pr)) {
- pr->mpc += (intptr_t) code->entrypoint;
- pr->datap = (intptr_t) (pr->disp + code->entrypoint);
+ pr.mpc += (intptr_t) code->entrypoint;
+ pr.datap = (intptr_t) (pr.disp + code->entrypoint);
}
}
code = code_find_codeinfo_for_pc(pc);
assert(code);
- /* enter a monitor on the patcher list */
-
- list_lock(code->patchers);
+ // Enter a mutex on the patcher list.
+ code->patchers->lock();
/* search the patcher information for the given PC */
log_println("patcher_handler: double-patching detected!");
}
#endif
- list_unlock(code->patchers);
+ code->patchers->unlock();
return NULL;
}
if (result == false) {
e = exceptions_get_and_clear_exception();
- list_unlock(code->patchers);
+ code->patchers->unlock();
return e;
}
pr->done = true; /* XXX this is only preliminary to prevent double-patching */
- list_unlock(code->patchers);
+ code->patchers->unlock();
return NULL;
}
/* forward typedefs ***********************************************************/
+typedef struct patchref_t patchref_t;
+
#include "config.h"
#include "vm/types.h"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
#include "vm/global.h"
*******************************************************************************/
-typedef struct patchref_t {
+struct patchref_t {
ptrint mpc; /* absolute position in code segment */
ptrint datap; /* absolute position in data segment */
s4 disp; /* displacement of ref in the data segment */
void* ref; /* reference passed */
uint32_t mcode; /* machine code to be patched back in */
bool done; /* XXX preliminary: patch already applied? */
- listnode_t linkage;
-} patchref_t;
+};
/* macros *********************************************************************/
void loader_preinit(void)
{
-#if defined(ENABLE_THREADS)
- list_classpath_entry *lce;
-#endif
-
TRACESUBSYSTEMINITIALIZATION("loader_preinit");
#if defined(ENABLE_THREADS)
/* Initialize the monitor pointer for zip/jar file locking. */
- for (lce = (list_classpath_entry*) list_first(list_classpath_entries); lce != NULL;
- lce = (list_classpath_entry*) list_next(list_classpath_entries, lce)) {
+ for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+ list_classpath_entry* lce = *it;
+
if (lce->type == CLASSPATH_ARCHIVE)
lce->mutex = new Mutex();
}
void loader_load_all_classes(void)
{
- list_classpath_entry *lce;
#if defined(ENABLE_ZLIB)
hashtable *ht;
hashtable_zipfile_entry *htzfe;
utf *u;
#endif
- for (lce = (list_classpath_entry*) list_first(list_classpath_entries); lce != NULL;
- lce = (list_classpath_entry*) list_next(list_classpath_entries, lce)) {
+ for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+ list_classpath_entry* lce = *it;
+
#if defined(ENABLE_ZLIB)
if (lce->type == CLASSPATH_ARCHIVE) {
/* get the classes hashtable */
#endif
#include "threads/thread.hpp"
+#include "threads/threadlist.hpp"
#include "vm/exceptions.hpp"
#include "vm/globals.hpp"
case SIGQUIT:
/* print a thread dump */
#if defined(ENABLE_THREADS)
- threads_dump();
+ ThreadList_dump_threads();
#endif
#if defined(ENABLE_STATISTICS)
#include "threads/mutex.hpp"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
#include "toolbox/logging.h"
#include "toolbox/util.h"
/* global variables ***********************************************************/
-list_t *list_classpath_entries;
+List<list_classpath_entry*>* list_classpath_entries;
/* suck_init *******************************************************************
{
TRACESUBSYSTEMINITIALIZATION("suck_init");
- list_classpath_entries = list_create(OFFSET(list_classpath_entry, linkage));
+#warning Move this list into VM.
+ list_classpath_entries = new List<list_classpath_entry*>();
/* everything's ok */
/* add current classpath entry, if no error */
if (lce != NULL)
- list_add_last(list_classpath_entries, lce);
+ list_classpath_entries->push_back(lce);
}
/* goto next classpath entry, skip ':' delimiter */
/* walk through all classpath entries */
- for (lce = (list_classpath_entry*) list_first(list_classpath_entries); lce != NULL && cb == NULL;
- lce = (list_classpath_entry*) list_next(list_classpath_entries, lce)) {
+ for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end() && cb == NULL; it++) {
+ lce = *it;
+
#if defined(ENABLE_ZLIB)
if (lce->type == CLASSPATH_ARCHIVE) {
#include "threads/mutex.hpp"
#include "toolbox/hashtable.h"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
#include "vm/class.h"
#include "vm/global.h"
#if defined(ENABLE_ZLIB)
hashtable *htclasses;
#endif
- listnode_t linkage;
};
/* export variables ***********************************************************/
-extern list_t *list_classpath_entries;
-
+#ifdef __cplusplus
+extern List<list_classpath_entry*>* list_classpath_entries;
+#else
+extern List* list_classpath_entries;
+#endif
/* function prototypes ********************************************************/
#include "native/vm/nativevm.h"
#include "threads/lock-common.h"
-#include "threads/threadlist.h"
#include "threads/thread.hpp"
#include "toolbox/logging.h"
gc_init(opt_heapmaxsize, opt_heapstartsize);
#if defined(ENABLE_THREADS)
- /* BEFORE: threads_preinit */
-
- threadlist_init();
-
/* AFTER: gc_init */
threads_preinit();