[Mono-list] jit patch: delegate support
Dietmar Maurer
dietmar@ximian.com
19 Nov 2001 14:26:52 +0100
Index: mono/jit/ChangeLog
===================================================================
RCS file: /cvs/public/mono/mono/jit/ChangeLog,v
retrieving revision 1.45
diff -u -r1.45 ChangeLog
--- mono/jit/ChangeLog 2001/11/19 06:52:52 1.45
+++ mono/jit/ChangeLog 2001/11/19 09:29:16
@@ -1,3 +1,10 @@
+2001-11-19 Dietmar Maurer <dietmar@ximian.com>
+
+ * jit.c (mono_analyze_stack): impl. LDFTN
+
+ * emit-x86.c (enter_method): more debugging output for Strings
+ (arch_compile_method): added delegate support
+ (arch_compile_method): align EBP to 8 byte boundary
Mon Nov 19 11:36:22 CET 2001 Paolo Molaro <lupus@ximian.com>
Index: mono/jit/TODO
===================================================================
RCS file: /cvs/public/mono/mono/jit/TODO,v
retrieving revision 1.2
diff -u -r1.2 TODO
--- mono/jit/TODO 2001/09/21 12:50:46 1.2
+++ mono/jit/TODO 2001/11/19 09:29:16
@@ -1,5 +1,6 @@
+* correctly align value types on the stack and in arrays
+* enum types can have several base types (not only int32)
* document the functions and variables in the JIT
* compute the frame size
-* implement value types
* implement a register set for FP registers (just count register usage on x86)
Index: mono/jit/emit-x86.c
===================================================================
RCS file: /cvs/public/mono/mono/jit/emit-x86.c,v
retrieving revision 1.18
diff -u -r1.18 emit-x86.c
--- mono/jit/emit-x86.c 2001/11/16 10:56:52 1.18
+++ mono/jit/emit-x86.c 2001/11/19 09:29:16
@@ -49,7 +49,12 @@
} else {
o = *((MonoObject **)ebp);
class = o->klass;
- printf ("this:%p[%s.%s], ", o, class->name_space, class->name);
+ if (!strcmp (class->name_space, "System") &&
+ !strcmp (class->name, "String")) {
+ printf ("this:%p[STRING:%s], ", o, mono_string_to_utf8 ((MonoString *)o));
+
+ } else
+ printf ("this:%p[%s.%s], ", o, class->name_space, class->name);
}
ebp += sizeof (gpointer);
}
@@ -73,6 +78,8 @@
printf ("%d, ", *((int *)(ebp)));
break;
case MONO_TYPE_STRING:
+ printf ("[STRING:%s], ", mono_string_to_utf8 (*(MonoString **)(ebp)));
+ break;
case MONO_TYPE_PTR:
case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
@@ -128,6 +135,8 @@
method->klass->name, method->name, eax);
break;
case MONO_TYPE_STRING:
+ printf ("[STRING:%s], ", mono_string_to_utf8 ((MonoString *)(eax)));
+ break;
case MONO_TYPE_PTR:
case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
@@ -490,9 +499,9 @@
tree->reg1 = mono_regset_alloc_reg (rs, tree->left->reg1, tree->exclude_mask);
tree->reg2 = mono_regset_alloc_reg (rs, tree->right->reg1, tree->exclude_mask);
}
- if (tree->op == MB_TERM_CALL_I4) {
- tree->reg1 = mono_regset_alloc_reg (rs, tree->left->reg1, tree->exclude_mask);
- }
+ //if (tree->op == MB_TERM_CALL_I4) {
+ //tree->reg1 = mono_regset_alloc_reg (rs, tree->left->reg1, tree->exclude_mask);
+ //}
break;
case MB_NTERM_base:
@@ -633,55 +642,143 @@
g_assert (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL));
g_assert (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL));
- if (mono_jit_trace_calls) {
+ if (mono_jit_trace_calls || mono_jit_dump_asm || mono_jit_dump_forest) {
printf ("Start JIT compilation of %s.%s:%s\n", method->klass->name_space,
method->klass->name, method->name);
}
- cfg = mono_cfg_new (method, mp);
+ if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
+ MonoClassField *field;
+ const char *name = method->name;
+ static guint target_offset = 0;
+ static guint method_offset = 0;
+ guint8 *code;
+ gboolean delegate = FALSE;
+
+ if (method->klass->parent &&
+ method->klass->parent->parent == mono_defaults.delegate_class)
+ delegate = TRUE;
+
+ if (!target_offset) {
+ mono_jit_init_class (mono_defaults.delegate_class);
+
+ field = mono_class_get_field_from_name (mono_defaults.delegate_class, "m_target");
+ target_offset = field->offset;
+ field = mono_class_get_field_from_name (mono_defaults.delegate_class, "method_ptr");
+ method_offset = field->offset;
+ }
+
+ if (delegate && *name == '.' && (strcmp (name, ".ctor") == 0)) {
+ method->addr = code = g_malloc (32);
+ x86_push_reg (code, X86_EBP);
+ x86_mov_reg_reg (code, X86_EBP, X86_ESP, 4);
+
+ /* load the this pointer */
+ x86_mov_reg_membase (code, X86_EAX, X86_EBP, 8, 4);
+ /* load m_target arg */
+ x86_mov_reg_membase (code, X86_EDX, X86_EBP, 12, 4);
+ /* store mtarget */
+ x86_mov_membase_reg (code, X86_EAX, target_offset, X86_EDX, 4);
+ /* load method_ptr arg */
+ x86_mov_reg_membase (code, X86_EDX, X86_EBP, 16, 4);
+ /* store method_ptr */
+ x86_mov_membase_reg (code, X86_EAX, method_offset, X86_EDX, 4);
+
+ x86_leave (code);
+ x86_ret (code);
+
+ g_assert ((code - (guint8*)method->addr) < 32);
+ } else if (delegate && *name == 'I' && (strcmp (name, "Invoke") == 0)) {
+ MonoMethodSignature *csig = method->signature;
+ int i, target, this_pos = 4;
+ guint8 *source;
+
+ method->addr = g_malloc (1024);
+
+ if (csig->ret->type == MONO_TYPE_VALUETYPE) {
+ int size, align;
+ if ((size = mono_type_size (csig->ret, &align)) > 4 || size == 3)
+ this_pos = 8;
+ }
+
+ for (i = 0; i < 2; i ++) {
+ code = method->addr;
+ /* load the this pointer */
+ x86_mov_reg_membase (code, X86_EAX, X86_ESP, this_pos, 4);
+ /* load mtarget */
+ x86_mov_reg_membase (code, X86_EDX, X86_EAX, target_offset, 4);
+ /* check if zero (static method call without this pointer) */
+ x86_alu_reg_imm (code, X86_CMP, X86_EDX, 0);
+ x86_branch32 (code, X86_CC_EQ, target, TRUE);
+ source = code;
+
+ /* virtual call - we have to replace the this pointer */
+ x86_mov_membase_reg (code, X86_ESP, this_pos, X86_EDX, 4);
+
+ /* jump to method_ptr() */
+ target = code - source;
+ x86_jump_membase (code, X86_EAX, method_offset);
+ }
- mono_analyze_flow (cfg);
+ } else {
+ g_error ("Don't know how to exec runtime method %s.%s::%s",
+ method->klass->name_space, method->klass->name, method->name);
+ }
+
+ } else {
- mono_analyze_stack (cfg);
+ cfg = mono_cfg_new (method, mp);
- cfg->code = NULL;
- cfg->rs = mono_regset_new (X86_NREG);
- mono_regset_reserve_reg (cfg->rs, X86_ESP);
- mono_regset_reserve_reg (cfg->rs, X86_EBP);
+ mono_analyze_flow (cfg);
- // fixme: remove limitation to 4096 bytes
- method->addr = cfg->start = cfg->code = g_malloc (4096);
+ mono_analyze_stack (cfg);
+
+ cfg->code = NULL;
+ cfg->rs = mono_regset_new (X86_NREG);
+ mono_regset_reserve_reg (cfg->rs, X86_ESP);
+ mono_regset_reserve_reg (cfg->rs, X86_EBP);
- if (mono_jit_dump_forest) {
- int i;
- for (i = 0; i < cfg->block_count; i++) {
- printf ("BLOCK %d:\n", i);
- mono_print_forest (cfg->bblocks [i].forest);
+ // fixme: remove limitation to 8192 bytes
+ method->addr = cfg->start = cfg->code = g_malloc (8192);
+
+ if (mono_jit_dump_forest) {
+ int i;
+ for (i = 0; i < cfg->block_count; i++) {
+ printf ("BLOCK %d:\n", i);
+ mono_print_forest (cfg->bblocks [i].forest);
+ }
}
- }
+
+ mono_label_cfg (cfg);
+
+ arch_allocate_regs (cfg);
- mono_label_cfg (cfg);
+ /* align to 8 byte boundary */
+ cfg->locals_size += 7;
+ cfg->locals_size &= ~7;
- arch_allocate_regs (cfg);
+ arch_emit_prologue (cfg);
- arch_emit_prologue (cfg);
+ mono_emit_cfg (cfg);
- mono_emit_cfg (cfg);
+ g_assert ((cfg->code - cfg->start) < 8100);
- arch_emit_epilogue (cfg);
+ arch_emit_epilogue (cfg);
- mono_compute_branches (cfg);
+ mono_compute_branches (cfg);
- if (mono_jit_dump_asm)
- mono_disassemble_code (cfg->start, cfg->code - cfg->start);
+ if (mono_jit_dump_asm)
+ mono_disassemble_code (cfg->start, cfg->code - cfg->start);
- mono_regset_free (cfg->rs);
+ mono_regset_free (cfg->rs);
- mono_cfg_free (cfg);
+ mono_cfg_free (cfg);
- mono_mempool_destroy (mp);
+ mono_mempool_destroy (mp);
- if (mono_jit_trace_calls) {
+ }
+
+ if (mono_jit_trace_calls || mono_jit_dump_asm || mono_jit_dump_forest) {
printf ("END JIT compilation of %s.%s:%s %p %p\n", method->klass->name_space,
method->klass->name, method->name, method, metho_->addr);
}
Index: mono/jit/jit.c
===================================================================
RCS file: /cvs/public/mono/mono/jit/jit.c,v
retrieving revision 1.46
diff -u -r1.46 jit.c
--- mono/jit/jit.c 2001/11/19 06:52:52 1.46
+++ mono/jit/jit.c 2001/11/19 09:29:16
@@ -164,7 +164,7 @@
* Initialise the class @klass by calling the class
* constructor.
*/
-static void
+void
mono_jit_init_class (MonoClass *klass)
{
MonoCCtor cctor;
@@ -770,6 +770,8 @@
MonoVarInfo vi;
MonoFlowGraph *cfg;
+ g_assert (((MonoMethodNormal *)method)->header);
+
cfg = mono_mempool_alloc0 (mp, sizeof (MonoFlowGraph));
cfg->method = method;
@@ -1063,6 +1065,7 @@
break;
case CEE_LDARG:
case CEE_INITOBJ:
+ case CEE_LDFTN:
ip +=5;
break;
default:
@@ -1864,6 +1867,8 @@
ADD_TREE (t1);
size = mono_type_size (cm->signature->params [i], &align);
args_size += (size + 3) & ~3;
+
+ // fixme: align value type arguments to 8 byte boundary on the stack
}
if (csig->hasthis) {
@@ -2441,6 +2446,25 @@
MAKE_BI_ALU (CEQ)
MAKE_BI_ALU (CLT)
+ case CEE_LDFTN: {
+ MonoMethod *cm;
+ guint32 token;
+ ++ip;
+ token = read32 (ip);
+ ip += 4;
+
+ cm = mono_get_method (image, token, NULL);
+ g_assert (cm);
+
+ if (!cm->addr)
+ cm->addr = arch_create_simple_jit_trampoline (cm);
+
+ t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
+ t1->data.p = (char *)cm + G_STRUCT_OFFSET (MonoMethod, addr);
+ t1 = mono_ctree_new (mp, MB_TERM_LDIND_I4, t1, NULL);
+ PUSH_TREE (t1, VAL_POINTER);
+ break;
+ }
case CEE_INITOBJ: {
MonoClass *class;
guint32 token;
Index: mono/jit/jit.h
===================================================================
RCS file: /cvs/public/mono/mono/jit/jit.h,v
retrieving revision 1.13
diff -u -r1.13 jit.h
--- mono/jit/jit.h 2001/11/16 10:56:52 1.13
+++ mono/jit/jit.h 2001/11/19 09:29:16
@@ -96,6 +96,9 @@
void
mono_disassemble_code (guint8 *code, int size);
+void
+mono_jit_init_class (MonoClass *klass);
+
gpointer
arch_compile_method (MonoMethod *method);
Index: mono/jit/x86.brg
===================================================================
RCS file: /cvs/public/mono/mono/jit/x86.brg,v
retrieving revision 1.37
diff -u -r1.37 x86.brg
--- mono/jit/x86.brg 2001/11/16 10:56:52 1.37
+++ mono/jit/x86.brg 2001/11/19 09:29:16
@@ -398,6 +398,7 @@
break;
}
+
PRINT_REG ("LDIND_I4", tree->reg1);
}