This is closer to the JVM spec. In particular, classes are immediately
loaded and linked by the class loader, but initialized only on demand,
i.e. when we need to call a method.

Signed-off-by: Vegard Nossum <vegard.nos...@gmail.com>
---
 include/vm/class.h       |   10 +++++++-
 include/vm/classloader.h |    1 -
 jit/trampoline.c         |    5 ++++
 vm/class.c               |   49 +++++++++++++++++++++++++++------------------
 vm/classloader.c         |   23 ---------------------
 vm/jato.c                |   22 ++++++++++----------
 vm/object.c              |   28 +++++++++++++++++++++++--
 7 files changed, 78 insertions(+), 60 deletions(-)

diff --git a/include/vm/class.h b/include/vm/class.h
index cb4060d..a03db0e 100644
--- a/include/vm/class.h
+++ b/include/vm/class.h
@@ -37,9 +37,15 @@ struct vm_class {
 };
 
 int vm_class_link(struct vm_class *vmc, const struct cafebabe_class *class);
+int vm_class_init(struct vm_class *vmc);
 
-int vm_class_init_object(struct vm_class *vmc);
-int vm_class_run_clinit(struct vm_class *vmc);
+static inline int vm_class_ensure_init(struct vm_class *vmc)
+{
+       if (vmc->state == VM_CLASS_INITIALIZED)
+               return 0;
+
+       return vm_class_init(vmc);
+}
 
 static inline bool vm_class_is_interface(const struct vm_class *vmc)
 {
diff --git a/include/vm/classloader.h b/include/vm/classloader.h
index 0fe25d6..885e588 100644
--- a/include/vm/classloader.h
+++ b/include/vm/classloader.h
@@ -8,6 +8,5 @@ struct vm_class;
 int classloader_add_to_classpath(const char *classpath);
 
 struct vm_class *classloader_load(const char *class_name);
-struct vm_class *classloader_load_and_init(const char *class_name);
 
 #endif
diff --git a/jit/trampoline.c b/jit/trampoline.c
index af3dae5..cc27ed3 100644
--- a/jit/trampoline.c
+++ b/jit/trampoline.c
@@ -99,6 +99,11 @@ void *jit_magic_trampoline(struct compilation_unit *cu)
        if (opt_trace_magic_trampoline)
                trace_magic_trampoline(cu);
 
+       if (vm_class_ensure_init(method->class)) {
+               NOT_IMPLEMENTED;
+               return NULL;
+       }
+
        pthread_mutex_lock(&cu->mutex);
 
        if (vm_method_is_native(cu->method))
diff --git a/vm/class.c b/vm/class.c
index b0dc205..8e9a71e 100644
--- a/vm/class.c
+++ b/vm/class.c
@@ -195,37 +195,46 @@ int vm_class_link(struct vm_class *vmc, const struct 
cafebabe_class *class)
        return 0;
 }
 
-/*
- * This function sets the .object member of struct vm_class to point to
- * the object (of type java.lang.Class) for this class.
- */
-int vm_class_init_object(struct vm_class *vmc)
+int vm_class_init(struct vm_class *vmc)
 {
+       assert(vmc->state == VM_CLASS_LINKED);
+
+       /* XXX: Not entirely true, but we need it to break the recursion. */
+       vmc->state = VM_CLASS_INITIALIZED;
+
+       /* JVM spec, 2nd. ed., 2.17.1: "But before Terminator can be
+        * initialized, its direct superclass must be initialized, as well
+        * as the direct superclass of its direct superclass, and so on,
+        * recursively." */
+       if (vmc->super) {
+               int ret = vm_class_ensure_init(vmc->super);
+               if (ret)
+                       return ret;
+       }
+
+       /*
+        * Set the .object member of struct vm_class to point to
+        * the object (of type java.lang.Class) for this class.
+        */
        vmc->object = vm_object_alloc(vm_java_lang_Class);
        if (!vmc->object) {
                NOT_IMPLEMENTED;
                return -1;
        }
 
-       return 0;
-}
+       if (vmc->class) {
+               /* XXX: Make sure there's at most one of these. */
+               for (uint16_t i = 0; i < vmc->class->methods_count; ++i) {
+                       if (strcmp(vmc->methods[i].name, "<clinit>"))
+                               continue;
 
-int vm_class_run_clinit(struct vm_class *vmc)
-{
-       assert(vmc->state == VM_CLASS_LINKED);
+                       void (*clinit_trampoline)(void)
+                               = vm_method_trampoline_ptr(&vmc->methods[i]);
 
-       /* XXX: Make sure there's at most one of these. */
-       for (uint16_t i = 0; i < vmc->class->methods_count; ++i) {
-               if (strcmp(vmc->methods[i].name, "<clinit>"))
-                       continue;
-
-               void (*clinit_trampoline)(void)
-                       = vm_method_trampoline_ptr(&vmc->methods[i]);
-
-               clinit_trampoline();
+                       clinit_trampoline();
+               }
        }
 
-       vmc->state = VM_CLASS_INITIALIZED;
        return 0;
 }
 
diff --git a/vm/classloader.c b/vm/classloader.c
index 05ffc16..917d7c2 100644
--- a/vm/classloader.c
+++ b/vm/classloader.c
@@ -465,26 +465,3 @@ out:
        trace_pop();
        return vmc;
 }
-
-struct vm_class *classloader_load_and_init(const char *class_name)
-{
-       struct vm_class *vmc;
-
-       vmc = classloader_load(class_name);
-       if (!vmc)
-               return NULL;
-
-       if (vmc->state != VM_CLASS_INITIALIZED) {
-               if (vm_class_init_object(vmc)) {
-                       NOT_IMPLEMENTED;
-                       return NULL;
-               }
-
-               if (vm_class_run_clinit(vmc)) {
-                       NOT_IMPLEMENTED;
-                       return NULL;
-               }
-       }
-
-       return vmc;
-}
diff --git a/vm/jato.c b/vm/jato.c
index 163968b..3a42b62 100644
--- a/vm/jato.c
+++ b/vm/jato.c
@@ -182,15 +182,6 @@ static int preload_vm_classes(void)
                *pe->class = class;
        }
 
-       for (unsigned int i = 0; i < ARRAY_SIZE(preload_entries); ++i) {
-               const struct preload_entry *pe = &preload_entries[i];
-
-               if (vm_class_init_object(*pe->class)) {
-                       NOT_IMPLEMENTED;
-                       return 1;
-               }
-       }
-
        for (unsigned int i = 0; i < ARRAY_SIZE(field_preload_entries); ++i) {
                const struct field_preload_entry *pe
                        = &field_preload_entries[i];
@@ -205,6 +196,15 @@ static int preload_vm_classes(void)
                *pe->field = field;
        }
 
+       for (unsigned int i = 0; i < ARRAY_SIZE(preload_entries); ++i) {
+               const struct preload_entry *pe = &preload_entries[i];
+
+               if (vm_class_ensure_init(*pe->class)) {
+                       NOT_IMPLEMENTED;
+                       return 1;
+               }
+       }
+
        return 0;
 }
 
@@ -308,7 +308,7 @@ main(int argc, char *argv[])
 
        init_stack_trace_printing();
 
-       struct vm_class *vmc = classloader_load_and_init(classname);
+       struct vm_class *vmc = classloader_load(classname);
        if (!vmc) {
                fprintf(stderr, "error: %s: could not load\n", classname);
                goto out;
@@ -322,7 +322,7 @@ main(int argc, char *argv[])
        }
 
        if (!vm_method_is_static(vmm)) {
-               fprintf(stderr, "errror: %s: main method not static\n",
+               fprintf(stderr, "error: %s: main method not static\n",
                        classname);
                goto out;
        }
diff --git a/vm/object.c b/vm/object.c
index 9f0b58a..2776ab2 100644
--- a/vm/object.c
+++ b/vm/object.c
@@ -19,11 +19,19 @@ struct vm_object *vm_object_alloc(struct vm_class *class)
 {
        struct vm_object *res;
 
+       if (vm_class_ensure_init(class)) {
+               NOT_IMPLEMENTED;
+               return NULL;
+       }
+
        res = zalloc(sizeof(*res) + class->object_size);
-       if (res) {
-               res->class = class;
+       if (!res) {
+               NOT_IMPLEMENTED;
+               return NULL;
        }
 
+       res->class = class;
+
        if (pthread_mutex_init(&res->mutex, NULL))
                NOT_IMPLEMENTED;
 
@@ -75,6 +83,11 @@ struct vm_object *vm_object_alloc_native_array(int type, int 
count)
                return NULL;
        }
 
+       if (vm_class_ensure_init(res->class)) {
+               NOT_IMPLEMENTED;
+               return NULL;
+       }
+
        res->array_length = count;
 
        if (pthread_mutex_init(&res->mutex, NULL))
@@ -88,6 +101,11 @@ struct vm_object *vm_object_alloc_multi_array(struct 
vm_class *class,
 {
        assert(nr_dimensions > 0);
 
+       if (vm_class_ensure_init(class)) {
+               NOT_IMPLEMENTED;
+               return NULL;
+       }
+
        struct vm_object *res;
 
        res = zalloc(sizeof(*res) + sizeof(struct vm_object *) * counts[0]);
@@ -122,6 +140,11 @@ 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;
+               return NULL;
+       }
+
        res = zalloc(sizeof(*res) + sizeof(struct vm_object *) * count);
        if (!res) {
                NOT_IMPLEMENTED;
@@ -186,7 +209,6 @@ struct vm_object *new_exception(const char *class_name, 
const char *message)
        struct vm_object *obj;
        struct vm_class *e_class;
 
-       /* XXX: load_and_init? We'd better preload exception classes. */
        e_class = classloader_load(class_name);
        if (!e_class)
                return NULL;
-- 
1.6.0.4


------------------------------------------------------------------------------
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to