virtual method table is introduced to improve the performance for invoking 
virtual methods.

Signed-off-by: Saeed Siam <[EMAIL PROTECTED]>
---
 Makefile                                           |    3 +-
 arch/x86/insn-selector.brg                         |   21 +++++----
 include/jit/vtable.h                               |   12 +++++
 include/vm/vm.h                                    |    3 +
 jamvm/class.c                                      |   10 ++++
 jit/vtable.c                                       |   44 ++++++++++++++++++++
 .../jamvm/MethodInvocationAndReturnTest.java       |   40 ++++++++++++++++++
 test/arch-x86/insn-selector-test.c                 |   20 +--------
 8 files changed, 125 insertions(+), 28 deletions(-)

diff --git a/Makefile b/Makefile
index 2c180c6..c9e2cb7 100644
--- a/Makefile
+++ b/Makefile
@@ -64,7 +64,8 @@ JIT_OBJS = \
        jit/trace-jit.o         \
        jit/trampoline.o        \
        jit/tree-printer.o      \
-       jit/typeconv-bc.o
+       jit/typeconv-bc.o       \
+       jit/vtable.o
 
 VM_OBJS = \
        vm/bitset.o             \
diff --git a/arch/x86/insn-selector.brg b/arch/x86/insn-selector.brg
index 9df7b8d..87fed15 100644
--- a/arch/x86/insn-selector.brg
+++ b/arch/x86/insn-selector.brg
@@ -372,7 +372,6 @@ reg:        EXPR_INVOKE(arg) 1
 
 reg:   EXPR_INVOKEVIRTUAL(arg) 1
 {
-       unsigned long method_table_offset;
        struct var_info *return_value;
        struct var_info *call_target;
        unsigned long method_offset;
@@ -381,7 +380,6 @@ reg:        EXPR_INVOKEVIRTUAL(arg) 1
        struct expression *expr;
 
        expr = to_expr(tree);
-       method_table_offset = offsetof(struct classblock, method_table);
        method_offset = expr_method_index(expr) * sizeof(void *);
 
        return_value = get_fixed_var(s->b_parent, REG_EAX);
@@ -390,16 +388,19 @@ reg:      EXPR_INVOKEVIRTUAL(arg) 1
        call_target = get_var(s->b_parent);
        stack_ptr = get_fixed_var(s->b_parent, REG_ESP);
 
-       /*
-        *      FIXME: This is horrible due to lack of per-method vtables.
-        */
+       /* object reference */
        bb_add_insn(s, membase_reg_insn(INSN_MOV_MEMBASE_REG, stack_ptr, 0, 
call_target));
+
+       /* object class */
        bb_add_insn(s, membase_reg_insn(INSN_MOV_MEMBASE_REG, call_target, 
offsetof(struct object, class), call_target));
-       bb_add_insn(s, imm_reg_insn(INSN_ADD_IMM_REG, sizeof(struct object), 
call_target));
-       bb_add_insn(s, membase_reg_insn(INSN_MOV_MEMBASE_REG, call_target, 
method_table_offset, call_target));
-       bb_add_insn(s, membase_reg_insn(INSN_MOV_MEMBASE_REG, call_target, 
method_offset, call_target));
-       bb_add_insn(s, membase_reg_insn(INSN_MOV_MEMBASE_REG, call_target, 
offsetof(struct methodblock, trampoline), call_target));
-       bb_add_insn(s, membase_reg_insn(INSN_MOV_MEMBASE_REG, call_target, 
offsetof(struct buffer, buf), call_target));
+
+       /* vtable */
+       bb_add_insn(s, membase_reg_insn(INSN_MOV_MEMBASE_REG, call_target, 
sizeof(struct object), call_target));
+
+       /* native ptr */
+       bb_add_insn(s, imm_reg_insn(INSN_ADD_IMM_REG, method_offset, 
call_target));
+
+       /* invoke method */
        bb_add_insn(s, reg_insn(INSN_CALL_REG, call_target));
 
        args_count = nr_args(to_expr(expr->args_list));
diff --git a/include/jit/vtable.h b/include/jit/vtable.h
new file mode 100644
index 0000000..3d56fa0
--- /dev/null
+++ b/include/jit/vtable.h
@@ -0,0 +1,12 @@
+#ifndef __JIT_VTABLE_H
+#define __JIT_VTABLE_H
+
+struct vtable {
+       void **native_ptr;
+};
+
+void vtable_init(struct vtable *vtable, unsigned int nr_methods);
+void vtable_release(struct vtable *vtable);
+void vtable_setup_method(struct vtable *vtable, unsigned long idx, void 
*native_ptr);
+
+#endif /* __JIT_VTABLE_H */
diff --git a/include/vm/vm.h b/include/vm/vm.h
index 0884a2a..be9a0c7 100644
--- a/include/vm/vm.h
+++ b/include/vm/vm.h
@@ -33,6 +33,8 @@
 /* Configure options */
 #include <vm/config.h>
 
+#include <jit/vtable.h>
+
 #ifndef TRUE
 #define         TRUE    1
 #define         FALSE   0
@@ -491,6 +493,7 @@ typedef struct refs_offsets_entry {
 #define CLASS_PAD_SIZE 4
 
 typedef struct classblock {
+   struct vtable vtable;
    uintptr_t pad[CLASS_PAD_SIZE];
    char *name;
    char *signature;
diff --git a/jamvm/class.c b/jamvm/class.c
index db3a6ab..1e09908 100644
--- a/jamvm/class.c
+++ b/jamvm/class.c
@@ -980,6 +980,14 @@ void linkClass(Class *class) {
    cb->method_table = method_table;
    cb->method_table_size = method_table_size;
 
+   if (!(cb->access_flags & ACC_INTERFACE)) {
+       vtable_init(&cb->vtable, method_table_size);
+       for (i = 0; i < method_table_size; i++) {
+           mb = method_table[i];
+           vtable_setup_method(&cb->vtable, mb->method_table_index, 
trampoline_ptr(mb));
+       }
+   }
+
    /* Handle finalizer */
 
    /* If this is Object find the finalize method.  All subclasses will
@@ -1515,6 +1523,8 @@ void freeClassData(Class *class) {
     free(cb->methods);
     free(cb->inner_classes);
 
+    vtable_release(&cb->vtable);
+
     if(cb->annotations != NULL) {
         free(cb->annotations->data);
         free(cb->annotations);
diff --git a/jit/vtable.c b/jit/vtable.c
new file mode 100644
index 0000000..32b452a
--- /dev/null
+++ b/jit/vtable.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2008  Pekka Enberg
+ *
+ * This file is released under the GPL version 2 with the following
+ * clarification and special exception:
+ *
+ *     Linking this library statically or dynamically with other modules is
+ *     making a combined work based on this library. Thus, the terms and
+ *     conditions of the GNU General Public License cover the whole
+ *     combination.
+ *
+ *     As a special exception, the copyright holders of this library give you
+ *     permission to link this library with independent modules to produce an
+ *     executable, regardless of the license terms of these independent
+ *     modules, and to copy and distribute the resulting executable under terms
+ *     of your choice, provided that you also meet, for each linked independent
+ *     module, the terms and conditions of the license of that module. An
+ *     independent module is a module which is not derived from or based on
+ *     this library. If you modify this library, you may extend this exception
+ *     to your version of the library, but you are not obligated to do so. If
+ *     you do not wish to do so, delete this exception statement from your
+ *     version.
+ *
+ * Please refer to the file LICENSE for details.
+ */
+
+#include <jit/vtable.h>
+#include <stdlib.h>
+
+void vtable_init(struct vtable *vtable, unsigned int nr_methods)
+{
+       if (nr_methods != 0)
+               vtable->native_ptr = calloc(nr_methods, sizeof(void *));
+}
+
+void vtable_release(struct vtable *vtable)
+{
+       free(vtable->native_ptr);
+}
+
+void vtable_setup_method(struct vtable *vtable, unsigned long idx, void 
*native_ptr)
+{
+       vtable->native_ptr[idx] = native_ptr;
+}
diff --git a/regression/jamvm/MethodInvocationAndReturnTest.java 
b/regression/jamvm/MethodInvocationAndReturnTest.java
index 8fd5dcb..4131514 100644
--- a/regression/jamvm/MethodInvocationAndReturnTest.java
+++ b/regression/jamvm/MethodInvocationAndReturnTest.java
@@ -25,6 +25,19 @@ public class MethodInvocationAndReturnTest extends TestCase {
 
     public static void main(String[] args) {
         testReturnFromInvokeVirtualReinstatesTheFrameOfTheInvoker();
+
+        Super superClass = new Super();
+        Inherited inherited = new Inherited();
+        AbstractInherited abstractInherited = new AbstractInherited();
+
+        assertEquals(0, superClass.retInt());
+        assertEquals(1, inherited.retInt());
+
+        superClass = inherited;
+        assertEquals(1, superClass.retInt());
+
+        assertEquals(1, abstractInherited.retInt());
+
         Runtime.getRuntime().halt(retval);
     }
 
@@ -51,3 +64,30 @@ public class MethodInvocationAndReturnTest extends TestCase {
         }
     }
 }
+
+class Super {
+
+    int retInt() {
+        return 0;
+    }
+}
+
+class Inherited extends Super{
+
+    //@Override
+    int retInt() {
+        return 1;
+    }
+}
+
+abstract class AbstractSuper {
+    abstract int retInt();
+}
+
+class AbstractInherited extends AbstractSuper {
+
+    //@Override
+    int retInt() {
+        return 1;
+    }
+}
diff --git a/test/arch-x86/insn-selector-test.c 
b/test/arch-x86/insn-selector-test.c
index efbe837..e800c5f 100644
--- a/test/arch-x86/insn-selector-test.c
+++ b/test/arch-x86/insn-selector-test.c
@@ -693,28 +693,14 @@ void test_select_invokevirtual_with_arguments(void)
        assert_membase_reg_insn(INSN_MOV_MEMBASE_REG, dreg, offsetof(struct 
object, class), dreg2, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       assert_imm_reg_insn(INSN_ADD_IMM_REG, sizeof(struct object), dreg2, 
insn);
-
-       insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       dreg = mach_reg(&insn->dest.reg);
-       assert_membase_reg_insn(INSN_MOV_MEMBASE_REG, dreg2,
-                               offsetof(struct classblock, method_table),
-                               dreg, insn);
-
-       insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       dreg2 = mach_reg(&insn->dest.reg);
-       assert_membase_reg_insn(INSN_MOV_MEMBASE_REG, dreg, method_index * 
sizeof(void *), dreg2, insn);
-
-       insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
        dreg = mach_reg(&insn->dest.reg);
-       assert_membase_reg_insn(INSN_MOV_MEMBASE_REG, dreg2, offsetof(struct 
methodblock, trampoline), dreg, insn);
+       assert_membase_reg_insn(INSN_MOV_MEMBASE_REG, dreg2, sizeof(struct 
object), dreg, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       dreg2 = mach_reg(&insn->dest.reg);
-       assert_membase_reg_insn(INSN_MOV_MEMBASE_REG, dreg, offsetof(struct 
buffer, buf), dreg2, insn);
+       assert_imm_reg_insn(INSN_ADD_IMM_REG, method_index * sizeof(void *), 
dreg, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
-       assert_reg_insn(INSN_CALL_REG, dreg2, insn);
+       assert_reg_insn(INSN_CALL_REG, dreg, insn);
 
        insn = list_next_entry(&insn->insn_list_node, struct insn, 
insn_list_node);
        assert_imm_reg_insn(INSN_ADD_IMM_REG, 4, REG_ESP, insn);

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Jatovm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to