This fixes a bug where a method may require other classes to load, thereby compiling and executing _their_ <clinit> methods, which may (compile and) call the same method we were trying to execute in the first place.
Signed-off-by: Vegard Nossum <vegard.nos...@gmail.com> --- include/vm/classloader.h | 3 +- jit/trampoline.c | 8 ++++++ vm/class.c | 2 +- vm/classloader.c | 58 ++++++++++++++++++++++++++++++++++------------ vm/jato.c | 4 ++- 5 files changed, 57 insertions(+), 18 deletions(-) diff --git a/include/vm/classloader.h b/include/vm/classloader.h index 0fe25d6..e05feb9 100644 --- a/include/vm/classloader.h +++ b/include/vm/classloader.h @@ -8,6 +8,7 @@ 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); + +int synchronize_clinit(void); #endif diff --git a/jit/trampoline.c b/jit/trampoline.c index af3dae5..b912db2 100644 --- a/jit/trampoline.c +++ b/jit/trampoline.c @@ -120,6 +120,14 @@ void *jit_magic_trampoline(struct compilation_unit *cu) pthread_mutex_unlock(&cu->mutex); + /* XXX: + * + * 09:58 < penberg> but you need to be careful + * 09:58 < penberg> not to allow any threads to run the jit'd code + * before classes are initialized + */ + synchronize_clinit(); + return ret; } diff --git a/vm/class.c b/vm/class.c index cd19840..fcdc324 100644 --- a/vm/class.c +++ b/vm/class.c @@ -256,7 +256,7 @@ struct vm_class *vm_class_resolve_class(struct vm_class *vmc, uint16_t i) return NULL; } - struct vm_class *class = classloader_load_and_init(class_name_str); + struct vm_class *class = classloader_load(class_name_str); if (!class) { NOT_IMPLEMENTED; return NULL; diff --git a/vm/classloader.c b/vm/classloader.c index 1ce3cf9..6aebcff 100644 --- a/vm/classloader.c +++ b/vm/classloader.c @@ -421,6 +421,14 @@ out_filename: return result; } +struct clinit { + struct list_head node; + + struct vm_class *vmc; +}; + +static struct list_head clinits = LIST_HEAD_INIT(clinits); + /* XXX: Should use hash table or tree, not linear search. -Vegard */ struct vm_class *classloader_load(const char *class_name) { @@ -462,31 +470,51 @@ struct vm_class *classloader_load(const char *class_name) class->class = vmc; out: + if (vmc && vmc->state < VM_CLASS_INITIALIZING) { + struct clinit *c = malloc(sizeof *c); + if (!c) { + NOT_IMPLEMENTED; + return NULL; + } + + c->vmc = vmc; + + list_add(&c->node, &clinits); + } + trace_pop(); return vmc; } -struct vm_class *classloader_load_and_init(const char *class_name) +int synchronize_clinit(void) { - struct vm_class *vmc; + while (!list_is_empty(&clinits)) { + struct clinit *c + = list_first_entry(&clinits, struct clinit, node); + struct vm_class *vmc = c->vmc; - vmc = classloader_load(class_name); - if (!vmc) - return NULL; + list_del(&c->node); + free(c); - if (vmc->state < VM_CLASS_INITIALIZING) { - vmc->state = VM_CLASS_INITIALIZING; + /* Don't try to initialize classes without a backing class- + * file. */ + if (!vmc->class) + continue; - if (vm_class_init_object(vmc)) { - NOT_IMPLEMENTED; - return NULL; - } + if (vmc->state < VM_CLASS_INITIALIZING) { + vmc->state = VM_CLASS_INITIALIZING; - if (vm_class_run_clinit(vmc)) { - NOT_IMPLEMENTED; - return NULL; + if (vm_class_init_object(vmc)) { + NOT_IMPLEMENTED; + return -1; + } + + if (vm_class_run_clinit(vmc)) { + NOT_IMPLEMENTED; + return -1; + } } } - return vmc; + return 0; } diff --git a/vm/jato.c b/vm/jato.c index 0819fec..559b65e 100644 --- a/vm/jato.c +++ b/vm/jato.c @@ -306,12 +306,14 @@ 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; } + synchronize_clinit(); + struct vm_method *vmm = vm_class_get_method_recursive(vmc, "main", "([Ljava/lang/String;)V"); if (!vmm) { -- 1.6.0.4 ------------------------------------------------------------------------------ _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel