From f8cb8fc347756f0ade43d11f8dd8f1b3d2637cca Mon Sep 17 00:00:00 2001 From: Michael Starzinger Date: Wed, 10 Dec 2008 11:06:13 +0100 Subject: [PATCH] * src/vm/jit/stacktrace.cpp [ENABLE_JAVASE] (stacktrace_get_StackTraceElement): Added new function. [ENABLE_JAVASE] (stacktrace_get_StackTraceElements): Likewise [ENABLE_THREADS] (stacktrace_get_of_thread): Likewise (still bogus). * src/vm/jit/stacktrace.hpp: Added prototypes for above functions. * src/native/vm/gnuclasspath/java_lang_VMThrowable.cpp: Use new functions. * src/native/vm/openjdk/jvm.cpp (JVM_DumpThreads): Implemented. --- .../vm/gnuclasspath/java_lang_VMThrowable.cpp | 61 +------- src/native/vm/openjdk/jvm.cpp | 106 ++++++------- src/vm/jit/stacktrace.cpp | 147 ++++++++++++++++++ src/vm/jit/stacktrace.hpp | 3 + 4 files changed, 200 insertions(+), 117 deletions(-) diff --git a/src/native/vm/gnuclasspath/java_lang_VMThrowable.cpp b/src/native/vm/gnuclasspath/java_lang_VMThrowable.cpp index d62fe2926..fca7f8d1d 100644 --- a/src/native/vm/gnuclasspath/java_lang_VMThrowable.cpp +++ b/src/native/vm/gnuclasspath/java_lang_VMThrowable.cpp @@ -101,66 +101,7 @@ JNIEXPORT jobjectArray JNICALL Java_java_lang_VMThrowable_getStackTrace(JNIEnv * assert(st != NULL); - stacktrace_entry_t* ste = st->entries; - - /* Create the stacktrace element array. */ - - java_handle_objectarray_t* oa = builtin_anewarray(st->length, class_java_lang_StackTraceElement); - - if (oa == NULL) - return NULL; - - for (int i = 0; i < st->length; i++, ste++) { - /* Get the codeinfo and methodinfo. */ - - codeinfo* code = ste->code; - methodinfo* m = code->m; - - /* Get filename. */ - - java_handle_t* filename; - - if (!(m->flags & ACC_NATIVE)) { - if (m->clazz->sourcefile) - filename = javastring_new(m->clazz->sourcefile); - else - filename = NULL; - } - else - filename = NULL; - - /* get line number */ - - int32_t linenumber; - - if (m->flags & ACC_NATIVE) { - linenumber = -1; - } - else { - /* FIXME linenumbertable->find could change the methodinfo - pointer when hitting an inlined method. */ - - linenumber = code->linenumbertable->find(&m, ste->pc); - linenumber = (linenumber == 0) ? -1 : linenumber; - } - - /* get declaring class name */ - - java_handle_t* declaringclass = class_get_classname(m->clazz); - - /* allocate a new stacktrace element */ - - java_handle_t* h = builtin_new(class_java_lang_StackTraceElement); - - if (h == NULL) - return NULL; - - java_lang_StackTraceElement ste(h, filename, linenumber, declaringclass, javastring_new(m->name), ((m->flags & ACC_NATIVE) ? 1 : 0)); - - array_objectarray_element_set(oa, i, ste.get_handle()); - } - - return (jobjectArray) oa; + return stacktrace_get_StackTraceElements(st); } } // extern "C" diff --git a/src/native/vm/openjdk/jvm.cpp b/src/native/vm/openjdk/jvm.cpp index c13f6ece6..d9079edff 100644 --- a/src/native/vm/openjdk/jvm.cpp +++ b/src/native/vm/openjdk/jvm.cpp @@ -435,64 +435,11 @@ jobject JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index) java_lang_Throwable jlt(throwable); java_handle_bytearray_t* ba = jlt.get_backtrace(); - // We need a critical section here as the stacktrace structure is + // XXX We need a critical section here as the stacktrace structure is // mapped onto a Java byte-array. - LLNI_CRITICAL_START; - stacktrace_t* st = (stacktrace_t *) LLNI_array_data(ba); - if ((index < 0) || (index >= st->length)) { - /* XXX This should be an IndexOutOfBoundsException (check this - again). */ - exceptions_throw_arrayindexoutofboundsexception(); - return NULL; - } - - // Get the stacktrace entry. - stacktrace_entry_t* ste = &(st->entries[index]); - - // Get the codeinfo, methodinfo and classinfo. - codeinfo* code = ste->code; - methodinfo* m = code->m; - classinfo* c = m->clazz; - - // Get filename. - java_handle_t* filename; - - if (!(m->flags & ACC_NATIVE)) { - if (c->sourcefile != NULL) - filename = javastring_new(c->sourcefile); - else - filename = NULL; - } - else - filename = NULL; - - // Get line number. - int32_t linenumber; - - if (m->flags & ACC_NATIVE) { - linenumber = -2; - } - else { - // FIXME linenumbertable->find could change the methodinfo - // pointer when hitting an inlined method. - linenumber = code->linenumbertable->find(&m, ste->pc); - linenumber = (linenumber == 0) ? -1 : linenumber; - } - - LLNI_CRITICAL_END; - - // Get declaring class name. - java_handle_t* declaringclass = class_get_classname(c); - - // Allocate a new StackTraceElement object. - java_lang_StackTraceElement jlste(declaringclass, javastring_new(m->name), filename, linenumber); - - if (jlste.is_null()) - return NULL; - - return (jobject) jlste.get_handle(); + return stacktrace_get_StackTraceElement(st, index); } @@ -3235,9 +3182,54 @@ jobjectArray JVM_GetAllThreads(JNIEnv *env, jclass dummy) jobjectArray JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads) { - log_println("JVM_DumpThreads: IMPLEMENT ME!"); + int32_t i; - return NULL; + TRACEJVMCALLS(("JVM_DumpThreads((env=%p, threadClass=%p, threads=%p)", env, threadClass, threads)); + + if (threads == NULL) { + exceptions_throw_nullpointerexception(); + return NULL; + } + + // Get length of the threads array. + int32_t length = array_length_get((java_handle_t*) threads); + + if (length <= 0) { + exceptions_throw_illegalargumentexception(); + return NULL; + } + + // Allocate array to hold stacktraces. + classinfo* arrayclass = class_array_of(class_java_lang_StackTraceElement, true); + java_handle_objectarray_t* oas = builtin_anewarray(length, arrayclass); + + if (oas == NULL) { + return NULL; + } + + // Iterate over all passed thread objects. + for (i = 0; i < length; i++) { + java_handle_t* thread = array_objectarray_element_get(threads, i); + + // Get thread for the given thread object. + threadobject* t = thread_get_thread(thread); + + if (t == NULL) + continue; + + // Get stacktrace for given thread. + stacktrace_t* st = stacktrace_get_of_thread(t); + + if (st == NULL) + continue; + + // Convert stacktrace into array of StackTraceElements. + java_handle_objectarray_t* oa = stacktrace_get_StackTraceElements(st); + + array_objectarray_element_set(oas, i, (java_handle_t*) oa); + } + + return oas; } diff --git a/src/vm/jit/stacktrace.cpp b/src/vm/jit/stacktrace.cpp index 514c2fd08..6d8d51d0c 100644 --- a/src/vm/jit/stacktrace.cpp +++ b/src/vm/jit/stacktrace.cpp @@ -674,6 +674,123 @@ java_handle_bytearray_t *stacktrace_get_current(void) } +/** + * Creates a java.lang.StackTraceElement for one element of the given + * stacktrace. + * + * @param st Given stacktrace. + * @param index Index of element inside stacktrace. + * @return The filled StackTraceElement object. + */ +#if defined(ENABLE_JAVASE) +java_handle_t* stacktrace_get_StackTraceElement(stacktrace_t* st, int32_t index) +{ + if ((index < 0) || (index >= st->length)) { + /* XXX This should be an IndexOutOfBoundsException (check this + again). */ + exceptions_throw_arrayindexoutofboundsexception(); + return NULL; + } + + // Get the stacktrace entry. + stacktrace_entry_t* ste = &(st->entries[index]); + + // Get the codeinfo, methodinfo and classinfo. + codeinfo* code = ste->code; + methodinfo* m = code->m; + classinfo* c = m->clazz; + + // Get filename. + java_handle_t* filename; + + if (!(m->flags & ACC_NATIVE)) { + if (c->sourcefile != NULL) + filename = javastring_new(c->sourcefile); + else + filename = NULL; + } + else + filename = NULL; + + // Get line number. + int32_t linenumber; + + if (m->flags & ACC_NATIVE) { +#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) + linenumber = -1; +#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) + linenumber = -2; +#else +# error unknown classpath configuration +#endif + } + else { + // FIXME linenumbertable->find could change the methodinfo + // pointer when hitting an inlined method. + linenumber = code->linenumbertable->find(&m, ste->pc); + linenumber = (linenumber == 0) ? -1 : linenumber; + } + + // Get declaring class name. + java_handle_t* declaringclass = class_get_classname(c); + +#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) + // Allocate a new StackTraceElement object. + java_handle_t* h = builtin_new(class_java_lang_StackTraceElement); + + if (h == NULL) + return NULL; + + java_lang_StackTraceElement jlste(h, filename, linenumber, declaringclass, javastring_new(m->name), ((m->flags & ACC_NATIVE) ? 1 : 0)); +#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) + // Allocate a new StackTraceElement object. + java_lang_StackTraceElement jlste(declaringclass, javastring_new(m->name), filename, linenumber); + + if (jlste.is_null()) + return NULL; +#else +# error unknown classpath configuration +#endif + + return jlste.get_handle(); +} +#endif + + +/** + * Creates a complete array of java.lang.StackTraceElement objects + * for the given stacktrace. + * + * @param st Given stacktrace. + * @return Array of filled StackTraceElement objects. + */ +#if defined(ENABLE_JAVASE) +java_handle_objectarray_t* stacktrace_get_StackTraceElements(stacktrace_t* st) +{ + // Create the stacktrace element array. + java_handle_objectarray_t* oa = builtin_anewarray(st->length, class_java_lang_StackTraceElement); + + if (oa == NULL) + return NULL; + + // Iterate over all stacktrace elements. + for (int i = 0; i < st->length; i++) { + + // Get stacktrace element at current index. + java_handle_t* h = stacktrace_get_StackTraceElement(st, i); + + if (h == NULL) + return NULL; + + // Store stacktrace element in array. + array_objectarray_element_set(oa, i, h); + } + + return oa; +} +#endif + + /* stacktrace_get_caller_class ************************************************* Get the class on the stack at the given depth. This function skips @@ -1187,6 +1304,36 @@ void stacktrace_print_current(void) } +/** + * Creates a stacktrace for the given thread. + * + * @param t Given thread. + * @return Current stacktrace of the given thread. + * + * XXX: Creation of the stacktrace starts at the most recent + * stackframeinfo block. If the thread is not inside the native + * world, the created stacktrace is not complete! + */ +#if defined(ENABLE_THREADS) +stacktrace_t* stacktrace_get_of_thread(threadobject* t) +{ + stackframeinfo_t* sfi; + java_handle_bytearray_t* ba; + stacktrace_t* st; + + sfi = t->_stackframeinfo; + ba = stacktrace_get(sfi); + + if (ba == NULL) + return NULL; + + st = (stacktrace_t*) LLNI_array_data(ba); + + return st; +} +#endif + + /* stacktrace_print_of_thread ************************************************** Print the current stacktrace of the given thread. diff --git a/src/vm/jit/stacktrace.hpp b/src/vm/jit/stacktrace.hpp index 6aa0ecf5b..2c2920c82 100644 --- a/src/vm/jit/stacktrace.hpp +++ b/src/vm/jit/stacktrace.hpp @@ -106,6 +106,8 @@ java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi); java_handle_bytearray_t *stacktrace_get_current(void); #if defined(ENABLE_JAVASE) +java_handle_t* stacktrace_get_StackTraceElement(stacktrace_t *st, int32_t index); +java_handle_objectarray_t* stacktrace_get_StackTraceElements(stacktrace_t *st); classinfo *stacktrace_get_caller_class(int depth); classloader_t *stacktrace_first_nonnull_classloader(void); java_handle_objectarray_t *stacktrace_getClassContext(void); @@ -117,6 +119,7 @@ void stacktrace_print(stacktrace_t *st); void stacktrace_print_current(void); #if defined(ENABLE_THREADS) +stacktrace_t* stacktrace_get_of_thread(threadobject *t); void stacktrace_print_of_thread(threadobject *t); #endif -- 2.25.1