[Mono-list] jit patch
Dietmar Maurer
dietmar@ximian.com
07 Nov 2001 11:43:51 +0100
Index: mono/arch/x86/x86-codegen.h
===================================================================
RCS file: /cvs/public/mono/mono/arch/x86/x86-codegen.h,v
retrieving revision 1.13
diff -u -r1.13 x86-codegen.h
--- mono/arch/x86/x86-codegen.h 2001/10/10 10:11:17 1.13
+++ mono/arch/x86/x86-codegen.h 2001/11/07 06:30:28
@@ -1114,7 +1114,7 @@
*/
#define x86_jump_code(inst,target) \
do { \
- int t = (target) - (inst) - 2; \
+ int t = (unsigned char*)(target) - (inst) - 2; \
if (x86_is_imm8(t)) { \
x86_jump8 ((inst), t); \
} else { \
Index: mono/jit/ChangeLog
===================================================================
RCS file: /cvs/public/mono/mono/jit/ChangeLog,v
retrieving revision 1.35
diff -u -r1.35 ChangeLog
--- mono/jit/ChangeLog 2001/11/06 09:46:18 1.35
+++ mono/jit/ChangeLog 2001/11/07 06:30:29
@@ -1,3 +1,11 @@
+2001-11-07 Dietmar Maurer <dietmar@ximian.com>
+
+ * emit-x86.c (enter_method): print out all method arguments
+ (x86_magic_trampoline): impl.
+ (arch_create_simple_jit_trampoline): we use different trampolines
+ for static methods (no need to write the address back into to
+ vtable).
+
2001-11-06 Dietmar Maurer <dietmar@ximian.com>
* emit-x86.c (arch_create_jit_trampoline): optimised trampoline to
Index: mono/jit/emit-x86.c
===================================================================
RCS file: /cvs/public/mono/mono/jit/emit-x86.c,v
retrieving revision 1.13
diff -u -r1.13 emit-x86.c
--- mono/jit/emit-x86.c 2001/11/06 09:46:18 1.13
+++ mono/jit/emit-x86.c 2001/11/07 06:30:29
@@ -23,15 +23,77 @@
#include "codegen.h"
static void
-enter_method (MonoMethod *method)
+enter_method (MonoMethod *method, gpointer ebp)
{
- printf ("ENTER: %s.%s::%s\n", method->klass->name_space,
+ int i;
+ MonoClass *class;
+ MonoObject *o;
+
+ printf ("ENTER: %s.%s::%s (", method->klass->name_space,
method->klass->name, method->name);
+
+ ebp += 8;
+
+ if (method->signature->hasthis) {
+ o = *((MonoObject **)ebp);
+ class = o->klass;
+ printf ("%p[%s.%s], ", o, class->name_space, class->name);
+ ebp += sizeof (gpointer);
+ }
+
+ for (i = 0; i < method->signature->param_count; ++i) {
+ MonoType *type = method->signature->params [i];
+ int size, align;
+
+ switch (type->type) {
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ printf ("%d, ", *((int *)(ebp)));
+ break;
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_FNPTR:
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_SZARRAY:
+ printf ("%p, ", *((gpointer *)(ebp)));
+ break;
+ case MONO_TYPE_I8:
+ printf ("%lld, ", *((gint64 *)(ebp)));
+ break;
+ case MONO_TYPE_R8:
+ printf ("%f, ", *((double *)(ebp)));
+ break;
+
+ default:
+ printf ("XX, ");
+ }
+
+ size = mono_type_size (type, &align);
+ if (size < 4)
+ size = 4;
+
+ ebp += size;
+
+ }
+
+ printf (")\n");
}
static void
leave_method (MonoMethod *method, int edx, int eax, double test)
{
+ gint64 l;
+
switch (method->signature->ret->type) {
case MONO_TYPE_VOID:
printf ("LEAVE: %s.%s::%s\n", method->klass->name_space,
@@ -61,8 +123,10 @@
method->klass->name, method->name, (gpointer)eax);
break;
case MONO_TYPE_I8:
- printf ("LEAVE: %s.%s::%s EAX=%d EDX=%d\n", method->klass->name_space,
- method->klass->name, method->name, eax, edx);
+ *((gint32 *)&l) = eax;
+ *((gint32 *)&l + 1) = edx;
+ printf ("LEAVE: %s.%s::%s EAX/EDX=%lld\n", method->klass->name_space,
+ method->klass->name, method->name, l);
break;
case MONO_TYPE_R8:
printf ("LEAVE: %s.%s::%s FP=%f\n", method->klass->name_space,
@@ -76,7 +140,7 @@
/**
* arch_emit_prologue:
- * @s: pointer to status information
+ * @cfg: pointer to status information
*
* Emits the function prolog.
*/
@@ -99,15 +163,16 @@
x86_push_reg (cfg->code, X86_ESI);
if (mono_jit_trace_calls) {
+ x86_push_reg (cfg->code, X86_EBP);
x86_push_imm (cfg->code, cfg->method);
x86_call_code (cfg->code, enter_method);
- x86_alu_reg_imm (cfg->code, X86_ADD, X86_ESP, 4);
+ x86_alu_reg_imm (cfg->code, X86_ADD, X86_ESP, 8);
}
}
/**
- * arch_emit_prologue:
- * @s: pointer to status information
+ * arch_emit_epilogue:
+ * @cfg: pointer to status information
*
* Emits the function epilog.
*/
@@ -142,19 +207,141 @@
}
/**
+ * x86_magic_trampoline:
+ * @eax: saved x86 register
+ * @ecx: saved x86 register
+ * @edx: saved x86 register
+ * @esi: saved x86 register
+ * @edi: saved x86 register
+ * @ebx: saved x86 register
+ * @code: pointer into caller code
+ * @method: the method to translate
+ *
+ * This method is called by the trampoline functions for virtual
+ * methods. It inspects the caller code to find the address of the
+ * vtable slot, then calls the JIT compiler and writes the address
+ * of the compiled method back to the vtable. All virtual methods
+ * are called with: x86_call_membase (inst, basereg, disp). We always
+ * use 32 bit displacement to ensure that the length of the call
+ * instruction is 6 bytes. We need to get the value of the basereg
+ * and the constant displacement.
+ */
+static gpointer
+x86_magic_trampoline (int eax, int ecx, int edx, int esi, int edi,
+ int ebx, guint8 *code, MonoMethod *m)
+{
+ guint8 ab, reg;
+ gint32 disp;
+ gpointer o;
+
+ /* go to the start of the call instruction */
+ code -= 6;
+ g_assert (*code == 0xff);
+
+ code++;
+ ab = *code;
+ g_assert ((ab >> 6) == 2);
+
+ /* extract the register number containing the address */
+ reg = ab & 0x07;
+ code++;
+
+ /* extract the displacement */
+ disp = *((gint32*)code);
+
+ switch (reg) {
+ case X86_EAX:
+ o = (gpointer)eax;
+ break;
+ case X86_EDX:
+ o = (gpointer)edx;
+ break;
+ case X86_ECX:
+ o = (gpointer)ecx;
+ break;
+ case X86_ESI:
+ o = (gpointer)esi;
+ break;
+ case X86_EDI:
+ o = (gpointer)edi;
+ break;
+ case X86_EBX:
+ o = (gpointer)ebx;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ o += disp;
+
+ return *((gpointer *)o) = arch_compile_method (m);
+}
+
+/**
* arch_create_jit_trampoline:
* @method: pointer to the method info
*
+ * Creates a trampoline function for virtual methods. If the created
+ * code is called it first starts JIT compilation of method,
+ * and then calls the newly created method. I also replaces the
+ * corresponding vtable entry (see x86_magic_trampoline).
+ *
+ * Returns: a pointer to the newly created code
+ */
+gpointer
+arch_create_jit_trampoline (MonoMethod *method)
+{
+ guint8 *code, *buf;
+ static guint8 *vc = NULL;
+
+ if (method->addr)
+ return method->addr;
+
+ if (!vc) {
+ vc = buf = g_malloc (24);
+
+ /* push the return address onto the stack */
+ x86_push_membase (buf, X86_ESP, 4);
+
+ /* save all register values */
+ x86_push_reg (buf, X86_EBX);
+ x86_push_reg (buf, X86_EDI);
+ x86_push_reg (buf, X86_ESI);
+ x86_push_reg (buf, X86_EDX);
+ x86_push_reg (buf, X86_ECX);
+ x86_push_reg (buf, X86_EAX);
+
+ x86_call_code (buf, x86_magic_trampoline);
+ x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 8*4);
+
+ /* call the compiled method */
+ x86_jump_reg (buf, X86_EAX);
+
+ g_assert ((buf - vc) <= 24);
+ }
+
+ code = buf = g_malloc (16);
+ x86_push_imm (buf, method);
+ x86_jump_code (buf, vc);
+ g_assert ((buf - code) <= 16);
+
+ return code;
+}
+
+/**
+ * arch_create_simple_jit_trampoline:
+ * @method: pointer to the method info
+ *
* Creates a trampoline function for method. If the created
* code is called it first starts JIT compilation of method,
* and then calls the newly created method. I also replaces the
* address in method->addr with the result of the JIT
- * compilation step.
+ * compilation step (in arch_compile_method).
*
* Returns: a pointer to the newly created code
*/
gpointer
-arch_create_jit_trampoline (MonoMethod *method)
+arch_create_simple_jit_trampoline (MonoMethod *method)
{
guint8 *code, *buf;
Index: mono/jit/jit.h
=================================================================_=
RCS file: /cvs/public/mono/mono/jit/jit.h,v
retrieving revision 1.10
diff -u -r1.10 jit.h
--- mono/jit/jit.h 2001/11/06 09:46:18 1.10
+++ mono/jit/jit.h 2001/11/07 06:30:29
@@ -93,6 +93,9 @@
gpointer
arch_create_jit_trampoline (MonoMethod *method);
+gpointer
+arch_create_simple_jit_trampoline (MonoMethod *method);
+
/* some handy debugging functions */
void
Index: mono/jit/testjit.c
===================================================================
RCS file: /cvs/public/mono/mono/jit/testjit.c,v
retrieving revision 1.37
diff -u -r1.37 testjit.c
--- mono/jit/testjit.c 2001/11/06 09:46:18 1.37
+++ mono/jit/testjit.c 2001/11/07 06:30:29
@@ -1136,11 +1136,11 @@
superblock_end = TRUE;
sp = stack;
- printf ("START\n");
+ //printf ("START\n");
for (i = 0; i < cfg->block_count; i++) {
bb = &cfg->bblocks [i];
- printf ("BBS %d %d %d %d\n", i, bb->reached, bb->finished, superblock_end);
+ //printf ("BBS %d %d %d %d\n", i, bb->reached, bb->finished, superblock_end);
if (!bb->reached && !superblock_end) {
@@ -1181,8 +1181,8 @@
while (ip < end) {
guint32 cli_addr = ip - header->code;
- printf ("%d IL%04x OPCODE %s %d %d %d\n", i, cli_addr, opcode_names [*ip],
- forest->len, superblock_end, sp - stack);
+ //printf ("%d IL%04x OPCODE %s %d %d %d\n", i, cli_addr, opcode_names [*ip],
+ //forest->len, superblock_end, sp - stack);
switch (*ip) {
case CEE_THROW: {
@@ -1554,8 +1554,8 @@
sp = sp - nargs;
}
- printf ("MINFO %s.%s::%s %d %d\n", cm->klass->name_space,
- cm->klass->name, cm->name, cm->flags & METHOD_ATTRIBUTE_VIRTUAL, virtual);
+ //printf ("MINFO %s.%s::%s %d %d\n", cm->klass->name_space,
+ //cm->klass->name, cm->name, cm->flags & METHOD_ATTRIBUTE_VIRTUAL, virtual);
if (virtual) {
t2 = ctree_create_dup (mp, this);
@@ -1571,7 +1571,7 @@
t2->data.m = cm;
} else {
if (!cm->addr)
- cm->addr = arch_create_jit_trampoline (cm);
+ cm->addr = arch_create_simple_jit_trampoline (cm);
t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
t2->data.p = (char *)cm + G_STRUCT_OFFSET (MonoMethod, addr);
@@ -2082,16 +2082,16 @@
repeat = TRUE;
g_assert (repeat_count < 10);
}
- printf ("BBE %d %d %d %d\n", i, bb->reached, bb->finished, superblock_end);
+ //printf ("BBE %d %d %d %d\n", i, bb->reached, bb->finished, superblock_end);
}
repeat_count++;
- printf ("REPEAT %d\n", repeat);
+ //printf ("REPEAT %d\n", repeat);
} while (repeat);
- printf ("FINISHED\n");
+ //printf ("FINISHED\n");
}
/**
Index: mono/jit/x86.brg
===================================================================
RCS file: /cvs/public/mono/mono/jit/x86.brg,v
retrieving revision 1.30
diff -u -r1.30 x86.brg
--- mono/jit/x86.brg 2001/11/06 09:46:18 1.30
+++ mono/jit/x86.brg 2001/11/07 06:30:29
@@ -92,6 +92,16 @@
#define MB_USE_OPT2(c) c
#endif
+/* The call instruction for virtual functions must have a known
+ * size (used by x86_magic_trampoline)
+ */
+#define x86_call_virtual(inst,basereg,disp) \
+ do { \
+ *(inst)++ = (unsigned char)0xff; \
+ x86_address_byte ((inst), 2, 2, (basereg)); \
+ x86_imm_emit32 ((inst), (disp)); \
+ } while (0)
+
%%
#
@@ -837,7 +847,7 @@
x86_mov_reg_membase (s->code, reg1, reg1,
G_STRUCT_OFFSET (MonoClass, interface_offsets), 4);
x86_mov_reg_membase (s->code, reg1, reg1, tree->left->data.m->klass->interface_id << 2, 4);
- x86_call_membase (s->code, reg1, tree->left->data.m->slot << 2);
+ x86_call_virtual (s->code, reg1, tree->left->data.m->slot << 2);
if (tree->data.i)
x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
@@ -849,7 +859,7 @@
int reg1 = tree->left->left->reg1;
x86_mov_reg_membase (s->code, reg1, reg1, 0, 4);
- x86_call_membase (s->code, reg1,
+ x86_call_virtual (s->code, reg1,
G_STRUCT_OFFSET (MonoClass, vtable) + (tree->left->data.m->slot << 2));
if (tree->data.i)
@@ -872,7 +882,7 @@
x86_mov_reg_membase (s->code, reg1, reg1,
G_STRUCT_OFFSET (MonoClass, interface_offsets), 4);
x86_mov_reg_membase (s->code, reg1, reg1, tree->left->data.m->klass->interface_id << 2, 4);
- x86_call_membase (s->code, reg1, tree->left->data.m->slot << 2);
+ x86_call_virtual (s->code, reg1, tree->left->data.m->slot << 2);
if (tree->data.i)
x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
@@ -882,7 +892,7 @@
int reg1 = tree->left->left->reg1;
x86_mov_reg_membase (s->code, reg1, reg1, 0, 4);
- x86_call_membase (s->code, reg1,
+ x86_call_virtual (s->code, reg1,
G_STRUCT_OFFSET (MonoClass, vtable) + (tree->left->data.m->slot << 2));
if (tree->data.i)
@@ -1556,7 +1566,7 @@
x86_mov_reg_membase (s->code, reg1, reg1,
G_STRUCT_OFFSET (MonoClass, interface_offsets), 4);
x86_mov_reg_membase (s->code, reg1, reg1, tree->left->data.m->klass->interface_id << 2, 4);
- x86_call_membase (s->code, reg1, tree->left->data.m->slot << 2);
+ x86_call_virtual (s->code, reg1, tree->left->data.m->slot << 2);
if (tree->data.i)
x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
@@ -1566,7 +1576,7 @@
int reg1 = tree->left->left->reg1;
x86_mov_reg_membase (s->code, reg1, reg1, 0, 4);
- x86_call_membase (s->code, reg1,
+ x86_call_virtual (s->code, reg1,
G_STRUCT_OFFSET (MonoClass, vtable) + (tree->left->data.m->slot << 2));
if (tree->data.i)
Index: mono/tests/jit-long.cs
===================================================================
RCS file: /cvs/public/mono/mono/tests/jit-long.cs,v
retrieving revision 1.2
diff -u -r1.2 jit-long.cs
--- mono/tests/jit-long.cs 2001/09/24 12:56:27 1.2
+++ mono/tests/jit-long.cs 2001/11/07 06:30:29
@@ -67,8 +67,6 @@
public static int Main() {
int num = 1;
- return test_alu();
-
if (test_call (3, 5) != 8)
return num;
num++;