[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);
 }