The procedure is described in JVM spec: http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html#24237
Signed-off-by: Tomek Grabiec <tgrab...@gmail.com> --- arch/x86/emit-code.c | 13 ++++++++----- include/jit/exception.h | 3 +++ include/vm/class.h | 1 + include/vm/preload.h | 1 + include/vm/signal.h | 1 + include/vm/static.h | 4 ++-- jit/exception.c | 21 +++++++++++++++++++++ test/arch-x86/Makefile | 1 + test/jit/Makefile | 1 + test/vm/preload-stub.c | 2 ++ test/vm/signal-stub.c | 6 ++++++ vm/class.c | 27 ++++++++++++++++++++++++++- vm/jato.c | 3 +++ vm/object.c | 16 ++++------------ vm/preload.c | 8 ++++++++ vm/signal.c | 3 +-- vm/static.c | 4 +++- 17 files changed, 92 insertions(+), 23 deletions(-) create mode 100644 test/vm/signal-stub.c create mode 100644 vm/tmp diff --git a/arch/x86/emit-code.c b/arch/x86/emit-code.c index 20fc9a8..fe4e231 100644 --- a/arch/x86/emit-code.c +++ b/arch/x86/emit-code.c @@ -1273,12 +1273,12 @@ struct emitter emitters[] = { DECL_EMITTER(INSN_XOR_XMM_REG_REG, emit_xor_xmm_reg_reg, TWO_OPERANDS), }; -void fixup_static(struct vm_class *vmc) +int fixup_static(struct vm_class *vmc) { struct static_fixup_site *this, *next; if (vm_class_ensure_init(vmc)) - die("class wouldn't initialize.. oops"); + return -1; list_for_each_entry_safe(this, next, &vmc->static_fixup_site_list, vmc_node) @@ -1294,9 +1294,11 @@ void fixup_static(struct vm_class *vmc) list_del(&this->cu_node); free(this); } + + return 0; } -void fixup_static_at(unsigned long addr) +int fixup_static_at(unsigned long addr) { struct compilation_unit *cu; struct static_fixup_site *this; @@ -1310,10 +1312,11 @@ void fixup_static_at(unsigned long addr) + this->insn->mach_offset; if ((unsigned long) site_addr == addr) { - fixup_static(this->vmf->class); - return; + return fixup_static(this->vmf->class); } } + + return 0; } void emit_trampoline(struct compilation_unit *cu, diff --git a/include/jit/exception.h b/include/jit/exception.h index 83bf8bc..d5f5dc0 100644 --- a/include/jit/exception.h +++ b/include/jit/exception.h @@ -56,6 +56,9 @@ void throw_exception_from_trampoline(void *ctx, struct vm_object *exception); void unwind(void); void signal_exception(struct vm_object *obj); void signal_new_exception(struct vm_class *vmc, const char *msg); +void signal_new_exception_with_cause(struct vm_class *vmc, + struct vm_object *cause, + const char *msg); void clear_exception(void); void init_exceptions(void); void thread_init_exceptions(void); diff --git a/include/vm/class.h b/include/vm/class.h index a54321e..c8b9020 100644 --- a/include/vm/class.h +++ b/include/vm/class.h @@ -15,6 +15,7 @@ enum vm_class_state { VM_CLASS_LOADED, VM_CLASS_LINKED, VM_CLASS_INITIALIZING, + VM_CLASS_ERRONEOUS, VM_CLASS_INITIALIZED, }; diff --git a/include/vm/preload.h b/include/vm/preload.h index 55ba334..1f3a2e9 100644 --- a/include/vm/preload.h +++ b/include/vm/preload.h @@ -37,6 +37,7 @@ extern struct vm_field *vm_java_lang_Throwable_detailMessage; extern struct vm_field *vm_java_lang_VMThrowable_vmdata; extern struct vm_method *vm_java_util_Properties_setProperty; +extern struct vm_method *vm_java_lang_Throwable_initCause; int preload_vm_classes(void); diff --git a/include/vm/signal.h b/include/vm/signal.h index a188daf..55795e1 100644 --- a/include/vm/signal.h +++ b/include/vm/signal.h @@ -10,5 +10,6 @@ typedef unsigned long (*signal_bh_fn)(unsigned long); void setup_signal_handlers(void); int install_signal_bh(void *ctx, signal_bh_fn bh); +unsigned long throw_from_signal_bh(unsigned long jit_addr); #endif /* VM_SIGNAL_H */ diff --git a/include/vm/static.h b/include/vm/static.h index d41711d..e7e6104 100644 --- a/include/vm/static.h +++ b/include/vm/static.h @@ -28,8 +28,8 @@ int add_getstatic_fixup_site(struct insn *insn, int add_putstatic_fixup_site(struct insn *insn, struct vm_field *vmf, struct compilation_unit *cu); -void fixup_static(struct vm_class *vmc); -void fixup_static_at(unsigned long addr); +int fixup_static(struct vm_class *vmc); +int fixup_static_at(unsigned long addr); extern unsigned long static_field_signal_bh(unsigned long ret); diff --git a/jit/exception.c b/jit/exception.c index 20e2e1b..a0a26cb 100644 --- a/jit/exception.c +++ b/jit/exception.c @@ -39,6 +39,7 @@ #include <vm/guard-page.h> #include <vm/method.h> #include <vm/object.h> +#include <vm/preload.h> #include <vm/thread.h> #include <arch/stack-frame.h> @@ -102,6 +103,26 @@ void signal_new_exception(struct vm_class *vmc, const char *msg) signal_exception(e); } +typedef struct vm_object * (*vm_throwable_init_cause_fn)(struct vm_object *, + struct vm_object *); + +void signal_new_exception_with_cause(struct vm_class *vmc, + struct vm_object *cause, + const char *msg) +{ + struct vm_object *e; + vm_throwable_init_cause_fn init_cause; + + init_cause = vm_method_trampoline_ptr(vm_java_lang_Throwable_initCause); + + e = new_exception(vmc, msg); + if (!e || exception_occurred()) + return; + + init_cause(e, cause); + signal_exception(e); +} + void clear_exception(void) { trampoline_exception_guard = &trampoline_exception_guard; diff --git a/test/arch-x86/Makefile b/test/arch-x86/Makefile index 2470e2d..8e2526a 100644 --- a/test/arch-x86/Makefile +++ b/test/arch-x86/Makefile @@ -80,6 +80,7 @@ OBJS = \ ../libharness/libharness.o \ ../vm/classloader-stub.o \ ../vm/preload-stub.o \ + ../vm/signal-stub.o \ $(TESTS) TESTS = \ diff --git a/test/jit/Makefile b/test/jit/Makefile index cc0a1d6..d0ba788 100644 --- a/test/jit/Makefile +++ b/test/jit/Makefile @@ -63,6 +63,7 @@ OBJS = \ ../vm/class-stub.o \ ../vm/classloader-stub.o \ ../vm/object-stub.o \ + ../vm/preload-stub.o \ ../jit/trace-stub.o \ args-test-utils.o \ arithmetic-bc-test.o \ diff --git a/test/vm/preload-stub.c b/test/vm/preload-stub.c index b068714..8426412 100644 --- a/test/vm/preload-stub.c +++ b/test/vm/preload-stub.c @@ -21,3 +21,5 @@ struct vm_class *vm_java_lang_RuntimeException; struct vm_class *vm_java_lang_ExceptionInInitializerError; struct vm_class *vm_java_lang_NegativeArraySizeException; struct vm_class *vm_java_lang_ClassCastException; + +struct vm_method *vm_java_lang_Throwable_initCause; diff --git a/test/vm/signal-stub.c b/test/vm/signal-stub.c new file mode 100644 index 0000000..917b0fb --- /dev/null +++ b/test/vm/signal-stub.c @@ -0,0 +1,6 @@ +#include "vm/signal.h" + +unsigned long throw_from_signal_bh(unsigned long jit_addr) +{ + return 0; +} diff --git a/vm/class.c b/vm/class.c index 35bdc95..961449d 100644 --- a/vm/class.c +++ b/vm/class.c @@ -286,6 +286,14 @@ int vm_class_link_bogus_class(struct vm_class *vmc, const char *class_name) int vm_class_init(struct vm_class *vmc) { + struct vm_object *exception; + + if (vmc->state == VM_CLASS_ERRONEOUS) { + signal_new_exception(vm_java_lang_NoClassDefFoundError, + vmc->name); + goto error; + } + assert(vmc->state == VM_CLASS_LINKED); /* XXX: Not entirely true, but we need it to break the recursion. */ @@ -298,7 +306,7 @@ int vm_class_init(struct vm_class *vmc) if (vmc->super) { int ret = vm_class_ensure_init(vmc->super); if (ret) - return ret; + goto error; } /* @@ -324,10 +332,27 @@ int vm_class_init(struct vm_class *vmc) = vm_method_trampoline_ptr(&vmc->methods[i]); clinit_trampoline(); + if (exception_occurred()) + goto error; } } return 0; + + error: + exception = exception_occurred(); + + if (!vm_object_is_instance_of(exception, vm_java_lang_Error)) { + clear_exception(); + signal_new_exception_with_cause( + vm_java_lang_ExceptionInInitializerError, + exception, + NULL); + } + + vmc->state = VM_CLASS_ERRONEOUS; + + return -1; } struct vm_class *vm_class_resolve_class(const struct vm_class *vmc, uint16_t i) diff --git a/vm/jato.c b/vm/jato.c index ccd60b5..418a2be 100644 --- a/vm/jato.c +++ b/vm/jato.c @@ -192,6 +192,9 @@ native_vmclassloader_getprimitiveclass(int type) return NULL; vm_class_ensure_init(class); + if (exception_occurred()) + throw_from_native(sizeof(int)); + return class->object; } diff --git a/vm/object.c b/vm/object.c index c52ffd5..48a3419 100644 --- a/vm/object.c +++ b/vm/object.c @@ -21,10 +21,8 @@ struct vm_object *vm_object_alloc(struct vm_class *class) { struct vm_object *res; - if (vm_class_ensure_init(class)) { - NOT_IMPLEMENTED; + if (vm_class_ensure_init(class)) return NULL; - } res = zalloc(sizeof(*res) + class->object_size); if (!res) { @@ -88,10 +86,8 @@ struct vm_object *vm_object_alloc_native_array(int type, int count) return NULL; } - if (vm_class_ensure_init(res->class)) { - NOT_IMPLEMENTED; + if (vm_class_ensure_init(res->class)) return NULL; - } res->array_length = count; @@ -106,10 +102,8 @@ struct vm_object *vm_object_alloc_multi_array(struct vm_class *class, { assert(nr_dimensions > 0); - if (vm_class_ensure_init(class)) { - NOT_IMPLEMENTED; + if (vm_class_ensure_init(class)) return NULL; - } struct vm_object *res; @@ -149,10 +143,8 @@ struct vm_object *vm_object_alloc_array(struct vm_class *class, int count) { struct vm_object *res; - if (vm_class_ensure_init(class)) { - NOT_IMPLEMENTED; + if (vm_class_ensure_init(class)) return NULL; - } res = zalloc(sizeof(*res) + sizeof(struct vm_object *) * count); if (!res) { diff --git a/vm/preload.c b/vm/preload.c index 49aaeee..264d7ab 100644 --- a/vm/preload.c +++ b/vm/preload.c @@ -127,6 +127,7 @@ struct method_preload_entry { }; struct vm_method *vm_java_util_Properties_setProperty; +struct vm_method *vm_java_lang_Throwable_initCause; static const struct method_preload_entry method_preload_entries[] = { { @@ -135,6 +136,13 @@ static const struct method_preload_entry method_preload_entries[] = { "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;", &vm_java_util_Properties_setProperty, }, + { + &vm_java_lang_Throwable, + "initCause", + "(Ljava/lang/Throwable;)Ljava/lang/Throwable;", + &vm_java_lang_Throwable_initCause, + }, + }; int preload_vm_classes(void) diff --git a/vm/signal.c b/vm/signal.c index bcf1e8f..264d112 100644 --- a/vm/signal.c +++ b/vm/signal.c @@ -39,8 +39,7 @@ #include <unistd.h> #include <stdio.h> -static unsigned long -throw_from_signal_bh(unsigned long jit_addr) +unsigned long throw_from_signal_bh(unsigned long jit_addr) { struct jit_stack_frame *frame; struct compilation_unit *cu; diff --git a/vm/static.c b/vm/static.c index b49c2f8..4b53c03 100644 --- a/vm/static.c +++ b/vm/static.c @@ -57,7 +57,9 @@ int add_putstatic_fixup_site(struct insn *insn, unsigned long static_field_signal_bh(unsigned long ret) { - fixup_static_at(ret); + if (fixup_static_at(ret)) + return throw_from_signal_bh(ret); + return ret; } diff --git a/vm/tmp b/vm/tmp new file mode 100644 index 0000000..e69de29 -- 1.6.0.6 ------------------------------------------------------------------------------ _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel