Reported-by: Tomek Grabiec <[email protected]>
Signed-off-by: Vegard Nossum <[email protected]>
---
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel