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