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

Reply via email to