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

Reply via email to