[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.
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"
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);
}
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;
}
}
+/**
+ * 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
}
+/**
+ * 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.
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);
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