Reported-by: Tomek Grabiec <tgrab...@gmail.com> Signed-off-by: Vegard Nossum <vegard.nos...@gmail.com> --- include/vm/class.h | 1 + include/vm/method.h | 3 ++ vm/class.c | 85 +++++++++++++++++++++++++++++++++++++++++++++----- vm/method.c | 19 +++++++++++ 4 files changed, 99 insertions(+), 9 deletions(-)
diff --git a/include/vm/class.h b/include/vm/class.h index 46b34b2..4451680 100644 --- a/include/vm/class.h +++ b/include/vm/class.h @@ -52,6 +52,7 @@ struct vm_class { unsigned int nr_interfaces; struct vm_class **interfaces; struct vm_field *fields; + unsigned int nr_methods; struct vm_method *methods; unsigned int object_size; diff --git a/include/vm/method.h b/include/vm/method.h index 90a4fef..54c2b94 100644 --- a/include/vm/method.h +++ b/include/vm/method.h @@ -53,6 +53,9 @@ struct vm_method { int vm_method_init(struct vm_method *vmm, struct vm_class *vmc, unsigned int method_index); +int vm_method_init_from_interface(struct vm_method *vmm, struct vm_class *vmc, + unsigned int method_index, struct vm_method *interface_method); + static inline bool vm_method_is_public(struct vm_method *vmm) { return vmm->method->access_flags & CAFEBABE_METHOD_ACC_PUBLIC; diff --git a/vm/class.c b/vm/class.c index 4c77dd3..abd3a5b 100644 --- a/vm/class.c +++ b/vm/class.c @@ -37,6 +37,7 @@ #include "cafebabe/method_info.h" #include "cafebabe/stream.h" +#include "lib/array.h" #include "lib/string.h" #include "vm/class.h" @@ -74,7 +75,7 @@ setup_vtable(struct vm_class *vmc) } vtable_size = 0; - for (uint16_t i = 0; i < vmc->class->methods_count; ++i) { + for (uint16_t i = 0; i < vmc->nr_methods; ++i) { struct vm_method *vmm = &vmc->methods[i]; if (super) { @@ -101,7 +102,7 @@ setup_vtable(struct vm_class *vmc) super_vtable->native_ptr[i]); /* Our methods */ - for (uint16_t i = 0; i < vmc->class->methods_count; ++i) { + for (uint16_t i = 0; i < vmc->nr_methods; ++i) { struct vm_method *vmm = &vmc->methods[i]; vtable_setup_method(&vmc->vtable, @@ -186,6 +187,23 @@ static void buckets_order_fields(struct field_bucket buckets[VM_TYPE_MAX], *size = offset; } +static int insert_interface_method(struct vm_class *vmc, + struct array *extra_methods, struct vm_method *vmm) +{ + /* We need this "manual" recursive lookup because we haven't + * initialized this class' list of methods yet... */ + unsigned int idx = 0; + if (!cafebabe_class_get_method(vmc->class, vmm->name, vmm->type, &idx)) + return 0; + + if (!vmc->super) + return 0; + if (vm_class_get_method_recursive(vmc->super, vmm->name, vmm->type)) + return 0; + + return array_append(extra_methods, vmm); +} + int vm_class_link(struct vm_class *vmc, const struct cafebabe_class *class) { vmc->class = class; @@ -371,7 +389,36 @@ int vm_class_link(struct vm_class *vmc, const struct cafebabe_class *class) } } - vmc->methods = malloc(sizeof(*vmc->methods) * class->methods_count); + struct array extra_methods; + array_init(&extra_methods); + + /* The array is temporary anyway, so there's no harm in allocating a + * bit more just in case. If it's too little, the array will expand. */ + array_resize(&extra_methods, 64); + + /* If in any of the superinterfaces we find a method which is not + * defined in this class file, we need to add a "miranda" method. + * Note that we don't need to do this recursively for all super- + * interfaces because they will have already done this very same + * procedure themselves. */ + for (unsigned int i = 0; i < class->interfaces_count; ++i) { + struct vm_class *vmi = vmc->interfaces[i]; + + for (unsigned int j = 0; j < vmi->nr_methods; ++j) { + struct vm_method *vmm = &vmi->methods[j]; + + int err = insert_interface_method(vmc, + &extra_methods, vmm); + if (err) { + NOT_IMPLEMENTED; + return -1; + } + } + } + + vmc->nr_methods = class->methods_count + extra_methods.size; + + vmc->methods = malloc(sizeof(*vmc->methods) * vmc->nr_methods); if (!vmc->methods) { NOT_IMPLEMENTED; return -1; @@ -380,19 +427,36 @@ int vm_class_link(struct vm_class *vmc, const struct cafebabe_class *class) for (uint16_t i = 0; i < class->methods_count; ++i) { struct vm_method *vmm = &vmc->methods[i]; - if (vm_method_init(&vmc->methods[i], vmc, i)) { + if (vm_method_init(vmm, vmc, i)) { + NOT_IMPLEMENTED; + return -1; + } + } + + for (unsigned int i = 0; i < extra_methods.size; ++i) { + struct vm_method *vmm = &vmc->methods[class->methods_count + i]; + + if (vm_method_init_from_interface(vmm, vmc, + class->methods_count + i, extra_methods.ptr[i])) + { NOT_IMPLEMENTED; return -1; } + } + + for (uint16_t i = 0; i < vmc->nr_methods; ++i) { + struct vm_method *vmm = &vmc->methods[i]; vmm->itable_index = itable_hash(vmm); - if (vm_method_prepare_jit(&vmc->methods[i])) { + if (vm_method_prepare_jit(vmm)) { NOT_IMPLEMENTED; return -1; } } + array_destroy(&extra_methods); + if (!vm_class_is_interface(vmc)) { setup_vtable(vmc); @@ -403,7 +467,7 @@ int vm_class_link(struct vm_class *vmc, const struct cafebabe_class *class) INIT_LIST_HEAD(&vmc->static_fixup_site_list); vmc->state = VM_CLASS_LINKED; - return 0;; + return 0; } int vm_class_link_primitive_class(struct vm_class *vmc, const char *class_name) @@ -829,9 +893,12 @@ struct vm_method *vm_class_get_method(const struct vm_class *vmc, if (vmc->kind != VM_CLASS_KIND_REGULAR) return NULL; - unsigned int index = 0; - if (!cafebabe_class_get_method(vmc->class, name, type, &index)) - return &vmc->methods[index]; + for (unsigned int i = 0; i < vmc->nr_methods; ++i) { + struct vm_method *vmm = &vmc->methods[i]; + + if (!strcmp(vmm->name, name) && !strcmp(vmm->type, type)) + return vmm; + } return NULL; } diff --git a/vm/method.c b/vm/method.c index 095c1de..7a4f0c5 100644 --- a/vm/method.c +++ b/vm/method.c @@ -141,6 +141,25 @@ int vm_method_init(struct vm_method *vmm, return 0; } +int vm_method_init_from_interface(struct vm_method *vmm, struct vm_class *vmc, + unsigned int method_index, struct vm_method *interface_method) +{ + /* NOTE: If we ever keep reference counts on loaded classes, we should + * perhaps _copy_ the interformation from the interface method instead + * of just grabbing a reference to the same information. */ + + vmm->class = vmc; + vmm->method_index = method_index; + vmm->method = interface_method->method; + + vmm->name = interface_method->name; + vmm->type = interface_method->type; + + vmm->args_count = interface_method->args_count; + vmm->is_vm_native = false; + return 0; +} + int vm_method_prepare_jit(struct vm_method *vmm) { struct compilation_unit *cu; -- 1.6.0.4 ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel