[Mono-list] patch: more jit work + bug fixes

Dietmar Maurer dietmar@ximian.com
09 Nov 2001 18:38:42 +0100


Index: mono/arch/x86/x86-codegen.h
===================================================================
RCS file: /cvs/public/mono/mono/arch/x86/x86-codegen.h,v
retrieving revision 1.14
diff -u -r1.14 x86-codegen.h
--- mono/arch/x86/x86-codegen.h	2001/11/07 06:33:48	1.14
+++ mono/arch/x86/x86-codegen.h	2001/11/09 13:38:15
@@ -259,6 +259,10 @@
 		*(inst)++ = 0xcc;	\
 	} while (0)
 
+#define x86_cld(inst) do { *(inst)++ =(unsigned char)0xfc; } while (0)
+#define x86_stosb(inst) do { *(inst)++ =(unsigned char)0xaa; } while
(0)
+#define x86_stosl(inst) do { *(inst)++ =(unsigned char)0xab; } while
(0)
+
 #define x86_prefix(inst,p) do { *(inst)++ =(unsigned char) (p); } while
(0)
 
 #define x86_rdtsc(inst) \
Index: mono/jit/ChangeLog
===================================================================
RCS file: /cvs/public/mono/mono/jit/ChangeLog,v
retrieving revision 1.38
diff -u -r1.38 ChangeLog
--- mono/jit/ChangeLog	2001/11/09 06:28:40	1.38
+++ mono/jit/ChangeLog	2001/11/09 13:38:15
@@ -1,6 +1,11 @@
 2001-11-09  Dietmar Maurer  <dietmar@ximian.com>
 
+	* testjit.c (mono_analyze_stack): new BOX impl.
+
+	* x86.brg: implemented INITOBJ
+
 	* testjit.c (mono_analyze_stack): finished array support
+	(mono_analyze_stack): reimplemented DUP instruction
 
 2001-11-08  Dietmar Maurer  <dietmar@ximian.com>
 
Index: mono/jit/testjit.c
===================================================================
RCS file: /cvs/public/mono/mono/jit/testjit.c,v
retrieving revision 1.40
diff -u -r1.40 testjit.c
--- mono/jit/testjit.c	2001/11/09 06:28:40	1.40
+++ mono/jit/testjit.c	2001/11/09 13:38:15
@@ -166,6 +166,47 @@
 	return g_malloc0 (size);
 } 
 
+
+typedef void (*MonoCCtor) (void);
+
+/**
+ * mono_jit_init_class:
+ * @klass: the class to initialise
+ *
+ * Initialise the class @klass by calling the class
+ * constructor.
+ */
+static void
+mono_jit_init_class (MonoClass *klass)
+{
+	MonoCCtor cctor;
+	MonoMethod *method;
+	int i;
+
+	if (!klass->metadata_inited)
+		mono_class_metadata_init (klass);
+
+	if (klass->inited)
+		return;
+
+	if (klass->parent && !klass->parent->inited)
+		mono_jit_init_class (klass->parent);
+	
+	klass->inited = 1;
+
+	for (i = 0; i < klass->method.count; ++i) {
+		method = klass->methods [i];
+		if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
+		    (strcmp (".cctor", method->name) == 0)) {
+	
+			cctor = arch_compile_method (method);
+			cctor ();
+			return;
+		}
+	}
+	/* No class constructor found */
+}
+
 static int
 map_store_svt_type (int svt)
 {
@@ -184,6 +225,29 @@
 	return 0;
 }
 
+static int
+map_stvalue_type (MonoClass *class)
+{
+	int size;
+
+	g_assert (class->valuetype);
+
+	if (!class->inited)
+		mono_jit_init_class (class);
+
+	size =  class->instance_size - sizeof (MonoObject);
+
+	switch (size) {
+	case 4:
+		return MB_TERM_STIND_I4;
+	case 2:
+		return MB_TERM_STIND_I2;
+	case 1:
+		return MB_TERM_STIND_I1;
+	}
+	return MB_TERM_STIND_OBJ;
+}
+
 /**
  * map_stind_type:
  * @type: the type to map
@@ -223,19 +287,8 @@
 		return MB_TERM_STIND_R4;
 	case MONO_TYPE_R8:
 		return MB_TERM_STIND_R8;
-	case MONO_TYPE_VALUETYPE: {
-		int size =  type->data.klass->instance_size - sizeof (MonoObject);
-
-		switch (size) {
-		case 4:
-			return MB_TERM_STIND_I4;
-		case 2:
-			return MB_TERM_STIND_I2;
-		case 1:
-			return MB_TERM_STIND_I1;
-		}
-		return MB_TERM_STIND_OBJ;
-	}
+	case MONO_TYPE_VALUETYPE: 
+		return map_stvalue_type (type->data.klass);
 	default:
 		g_warning ("unknown type %02x", type->type);
 		g_assert_not_reached ();
@@ -576,13 +629,20 @@
 	return NULL;
 }
 
+/**
+ * Create a duplicate of the value of a tree. This is
+ * easy for trees starting with LDIND/STIND, since the
+ * duplicate is simple a LDIND tree with the same address.
+ * For other trees we have to split the tree into one tree
+ * storing the value to a new temporary variable, and 
+ * another tree which loads that value back. We can then
+ * duplicate the second tree.
+ */
 static MBTree *
-mono_store_tree (MonoFlowGraph *cfg, int slot, MBTree *s, MBTree **dup)
+ctree_create_dup (MonoMemPool *mp, MBTree *s)
 {
-	MonoMemPool *mp = cfg->mp;
 	MBTree *t;
-	int vnum;
-
+	
 	switch (s->op) {
 	case MB_TERM_STIND_I1:
 	case MB_TERM_LDIND_I1:
@@ -602,6 +662,11 @@
 		t = mono_ctree_new (mp, MB_TERM_LDIND_I4, t, NULL);
 		t->svt = VAL_I32;
 		break;
+	case MB_TERM_LDIND_U4:
+		t = ctree_dup_address (mp, s->left);
+		t = mono_ctree_new (mp, MB_TERM_LDIND_U4, t, NULL);
+		t->svt = VAL_I32;
+		break;
 	case MB_TERM_STIND_I8:
 	case MB_TERM_LDIND_I8:
 		t = ctree_dup_address (mp, s->left);
@@ -620,127 +685,61 @@
 		t = mono_ctree_new (mp, MB_TERM_LDIND_R8, t, NULL);
 		t->svt = VAL_DOUBLE;
 		break;
-	default: {
-			g_assert (s->svt != VAL_UNKNOWN);
-
-			if (slot >= 0) 
-				vnum = mono_allocate_intvar (cfg, slot, s->svt);
-			else {
-				int size, align;
-				mono_get_val_sizes (s->svt, &size, &align);
-				vnum = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, s->svt);
-			}
-
-			t = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
-			t->data.i = vnum;
-		       
-			t = mono_ctree_new (mp, map_store_svt_type (s->svt), t, s);
-			t->svt = s->svt;
-		}
+	default:
+		g_warning ("unknown op \"%s\"", mono_burg_term_string [s->op]);
+		g_assert_not_reached ();
 	}
 
-	if (dup) 
-		*dup = mono_store_tree (cfg, -1, t, NULL);
-
 	return t;
 }
 
-/**
- * Create a duplicate of the value of a tree. This is
- * easy for trees starting with LDIND/STIND, since the
- * duplicate is simple a LDIND tree with the same address.
- * For other trees we have to split the tree into one tree
- * storing the value to a new temporary variable, and 
- * another tree which loads that value back. We can then
- * duplicate the second tree.
- */
 static MBTree *
-ctree_create_dup (MonoMemPool *mp, MBTree *s)
+mono_store_tree (MonoFlowGraph *cfg, int slot, MBTree *s, MBTree **dup)
 {
+	MonoMemPool *mp = cfg->mp;
 	MBTree *t;
-	
+	int vnum;
+
 	switch (s->op) {
 	case MB_TERM_STIND_I1:
 	case MB_TERM_LDIND_I1:
-		t = ctree_dup_address (mp, s->left);
-		t->svt = VAL_I32;
-		return mono_ctree_new (mp, MB_TERM_LDIND_I1, t, NULL);
 	case MB_TERM_STIND_I2:
 	case MB_TERM_LDIND_I2:
-		t = ctree_dup_address (mp, s->left);
-		t->svt = VAL_I32;
-		return mono_ctree_new (mp, MB_TERM_LDIND_I2, t, NULL);
 	case MB_TERM_STIND_I4:
 	case MB_TERM_LDIND_I4:
-		t = ctree_dup_address (mp, s->left);
-		t->svt = VAL_I32;
-		return mono_ctree_new (mp, MB_TERM_LDIND_I4, t, NULL);
-	case MB_TERM_LDIND_U4:
-		t = ctree_dup_address (mp, s->left);
-		t->svt = VAL_I32;
-		return mono_ctree_new (mp, MB_TERM_LDIND_U4, t, NULL);
 	case MB_TERM_STIND_I8:
 	case MB_TERM_LDIND_I8:
-		t = ctree_dup_address (mp, s->left);
-		t->svt = VAL_I64;
-		return mono_ctree_new (mp, MB_TERM_LDIND_I8, t, NULL);
 	case MB_TERM_STIND_R4:
 	case MB_TERM_LDIND_R4:
-		t = ctree_dup_address (mp, s->left);
-		t->svt = VAL_DOUBLE;
-		return mono_ctree_new (mp, MB_TERM_LDIND_R4, t, NULL);
 	case MB_TERM_STIND_R8:
-	case MB_TERM_LDIND_R8:
-		t = ctree_dup_address (mp, s->left);
-		t->svt = VAL_DOUBLE;
-		return mono_ctree_new (mp, MB_TERM_LDIND_R8, t, NULL);
-	default:
-		g_warning ("unknown op \"%s\"", mono_burg_term_string [s->op]);
-		g_assert_not_reached ();
-	}
-
-	g_assert_not_reached ();
-	return NULL;
-}
-
-typedef void (*MonoCCtor) (void);
-
-/**
- * mono_jit_init_class:
- * @klass: the class to initialise
- *
- * Initialise the class @klass by calling the class
- * constructor.
- */
-static void
-mono_jit_init_class (MonoClass *klass)
-{
-	MonoCCtor cctor;
-	MonoMethod *method;
-	int i;
-
-	if (!klass->metadata_inited)
-		mono_class_metadata_init (klass);
-
-	if (klass->inited)
-		return;
+	case MB_TERM_LDIND_R8: {
+		if (dup)
+			*dup = ctree_create_dup (mp, s);
+		return NULL;
+	}			
+	default: {
+			g_assert (s->svt != VAL_UNKNOWN);
 
-	if (klass->parent && !klass->parent->inited)
-		mono_jit_init_class (klass->parent);
-	
-	klass->inited = 1;
+			if (slot >= 0) 
+				vnum = mono_allocate_intvar (cfg, slot, s->svt);
+			else {
+				int size, align;
+				mono_get_val_sizes (s->svt, &size, &align);
+				vnum = arch_all_cate_var (cfg, size, align, MONO_TEMPVAR, s->svt);
+			}
 
-	for (i = 0; i < klass->method.count; ++i) {
-		method = klass->methods [i];
-		if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
-		    (strcmp (".cctor", method->name) == 0)) {
-	
-			cctor = arch_compile_method (method);
-			cctor ();
-			return;
+			t = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
+			t->data.i = vnum;
+		       
+			t = mono_ctree_new (mp, map_store_svt_type (s->svt), t, s);
+			t->svt = s->svt;
 		}
 	}
-	/* No class constructor found */
+
+	if (dup) 
+		mono_store_tree (cfg, -1, t, dup);
+
+	return t;
 }
 
 MonoFlowGraph *
@@ -939,6 +938,7 @@
 			ip += 5;
 			break;
 		case CEE_BR:
+		case CEE_LEAVE:
 		case CEE_BRTRUE:
 		case CEE_BRFALSE:
 		case CEE_BGT:
@@ -971,6 +971,7 @@
 			ip += 2;
 			break;
 		case CEE_BR_S:
+		case CEE_LEAVE_S:
 		case CEE_BRTRUE_S:
 		case CEE_BRFALSE_S:
 		case CEE_BGT_S:
@@ -1014,6 +1015,7 @@
 				ip++;
 				break;
 			case CEE_LDARG:
+			case CEE_INITOBJ:
 				ip +=5;
 				break;
 			default:
@@ -1305,9 +1307,26 @@
 			
 			c = mono_class_get (image, token);
 			
-			t1 = mono_ctree_new (mp, MB_TERM_BOX, *sp, NULL);
+			t1 = mono_ctree_new_leaf (mp, MB_TERM_NEWOBJ);
 			t1->data.p = c;
-			PUSH_TREE (t1, VAL_POINTER);
+			t1->svt = VAL_POINTER;
+
+			t1 = mono_store_tree (cfg, -1, t1, &t2);
+			g_assert (t1);
+
+			ADD_TREE (t1);
+			PUSH_TREE (t2, VAL_POINTER);
+
+			t1 = ctree_create_dup (mp, t2);
+			t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+			t2->data.i = sizeof (MonoObject);
+			t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);
+
+			t1 = mono_ctree_new (mp, map_stvalue_type (c), t1, *sp);
+			ADD_TREE (t1);
+
+			// I need to test this first
+			g_assert_not_reached ();
 			break;
 		}
 		case CEE_UNBOX: {
@@ -1630,6 +1649,7 @@
 				this->svt = VAL_POINTER;
 
 				t1 = mono_store_tree (cfg, -1, this, &this);
+				g_assert (t1);
 				ADD_TREE (t1);
 
 			}
@@ -1671,6 +1691,7 @@
 			if (newarr) {
 				
 				t1 = mono_store_tree (cfg, -1, t1, &t2);
+				g_assert (t1);
 				ADD_TREE (t1);
 				PUSH_TREE (t2, t2->svt);
 
@@ -1803,6 +1824,7 @@
 				if (csig->ret->type != MONO_TYPE_VOID) {
 
 					t1 = mono_store_tree (cfg, -1, t1, &t2);
+					g_assert (t1);
 					ADD_TREE (t1);
 					PUSH_TREE (t2, t2->svt);
 					
@@ -2169,11 +2191,15 @@
 		}
 		case CEE_DUP: {
 			++ip; 
-			
+			sp--;
 			/* fixme: IMO we can use the temp. variable associated
 			 * with the current slot instead of -1 
 			 */
-			sp [-1] = mono_store_tree (cfg, -1, sp [-1], &t1);
+			if (t2 = mono_store_tree (cfg, -1, *sp, &t1))
+				ADD_TREE (t2);
+
+			PUSH_TREE (t1, t1->svt);
+			t1 = ctree_create_dup (mp, t1);		
 			PUSH_TREE (t1, t1->svt);
 
 			break;
@@ -2233,6 +2259,22 @@
 				
 			MAKE_BI_ALU (CEQ)
 
+			case CEE_INITOBJ: {
+				MonoClass *class;
+				guint32 token;
+				
+				++ip;
+				token = read32 (ip);
+				class = mono_class_get (image, token);
+				ip += 4;
+				sp--;
+				
+				t1 = mono_ctree_new (mp, MB_TERM_INITOBJ, *sp, NULL);
+				t1->data.i = mono_class_value_size (class, NULL);
+				ADD_TREE (t1);
+
+				break;
+			}
 			case CEE_LDARG: {
 				guint32 n;
 				++ip;
Index: mono/jit/x86.brg
===================================================================
RCS file: /cvs/public/mono/mono/jit/x86.brg,v
retrieving revision 1.33
diff -u -r1.33 x86.brg
--- mono/jit/x86.brg	2001/11/09 06:28:40	1.33
+++ mono/jit/x86.brg	2001/11/09 13:38:15
@@ -118,7 +118,7 @@
 %term BLT BLT_UN BEQ BNE_UN BRTRUE BRFALSE BGE BGE_UN BLE BLE_UN BGT
BGT_UN 
 %term CEQ
 %term CONV_I4 CONV_I1 CONV_I2 CONV_I8 CONV_R8
-%term INTF_ADDR VFUNC_ADDR NOP BOX NEWARR NEWOBJ POP 
+%term INTF_ADDR VFUNC_ADDR NOP NEWARR NEWOBJ POP INITOBJ
 %term LDLEN
 
 #
@@ -243,6 +243,30 @@
 	}
 }
 
+stmt: STIND_I1 (addr, reg) {
+	switch (tree->left->data.ainfo.amode) {
+
+	case AMImmediate:
+		x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset,
tree->right->reg1, 1);
+		break;
+		
+	case AMBase:
+		x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg, 
+				     tree->left->data.ainfo.offset, tree->right->reg1, 1);
+		break;		
+	case AMIndex:
+		x86_mov_memindex_reg (s->code, X86_NOBASEREG,
tree->left->data.ainfo.offset,
+				      tree->left->data.ainfo.indexreg,
tree->left->data.ainfo.shift,
+				      tree->right->reg1, 1);
+		break;		
+	case AMBaseIndex:
+		x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg,
tree->left->data.ainfo.offset,
+				      tree->left->data.ainfo.indexreg,
tree->left->data.ainfo.shift,
+				      tree->right->reg1, 1);
+		break;		
+	}
+}
+
 reg: LDIND_I4 (addr) {
 	switch (tree->left->data.ainfo.amode) {
 
@@ -266,6 +290,29 @@
 	}
 }
 
+reg: LDIND_U1 (addr) {
+	switch (tree->left->data.ainfo.amode) {
+
+	case AMImmediate:
+		x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset,
1);
+		break;
+
+	case AMBase:
+		x86_mov_reg_membase (s->code, tree->reg1,
tree->left->data.ainfo.basereg, 
+				     tree->left->data.ainfo.offset, 1);
+		break;		
+	case AMIndex:
+		x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG,
tree->left->data.ainfo.offset,
+				      tree->left->data.ainfo.indexreg,
tree->left->data.ainfo.shift, 1);
+		break;		
+	case AMBaseIndex:
+		x86_mov_reg_memindex (s->code, tree->reg1,
tree->left->data.ainfo.basereg, 
+				      tree->left->data.ainfo.offset,
tree->left->data.ainfo.indexreg, 
+				      tree->left->data.ainfo.shift, 1);
+		break;		
+	}
+}
+
 reg: LDIND_U4 (addr) {
 	switch (tree->left->data.ainfo.amode) {
 
@@ -513,26 +560,6 @@
 		  tree->left->reg1 != X86_ECX);
 }
 
-reg: BOX (reg) {
-	if (tree->reg1 != X86_EAX)
-		x86_push_reg (s->code, X86_EAX);
-	x86_push_reg (s->code, X86_ECX);
-	x86_push_reg (s->code, X86_EDX);
-
-	x86_push_reg (s->code, tree->left->reg1); //save it to memory
-	x86_push_reg (s->code, X86_ESP); // push address to saved value
-	x86_push_imm (s->code, tree->data.p);
-	x86_call_code (s->code, mono_value_box);
-	x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
-
-	x86_pop_reg (s->code, X86_EDX);
-	x86_pop_reg (s->code, X86_ECX);
-	if (tree->reg1 != X86_EAX) {
-		x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
-		x86_pop_reg (s->code, X86_EAX);
-	}
-}
-
 # array support
 reg: LDLEN (reg) {
 	x86_mov_reg_membase (s->code, tree->reg1, tree->left->reg1,  
@@ -582,6 +609,69 @@
 		x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
 		x86_pop_reg (s->code, X86_EAX);
 	}
+}
+
+stmt: INITOBJ (reg) {
+	int i, j;
+
+	if (i == 1 || i == 2 || i == 4) {
+		int t = X86_ECX;
+
+		if (tree->left->reg1 != X86_EAX) 
+			t = X86_EAX;
+
+		x86_push_reg (s->code, t);
+		x86_alu_reg_reg (s->code, X86_XOR, t, t);
+
+		switch (tree->data.i) {
+		case 4:
+			x86_mov_regp_reg (s->code, tree->left->reg1, t, 4);
+			break;
+		case 2:
+			x86_mov_regp_reg (s->code, tree->left->reg1, t, 4);
+			break;
+		case 1:
+			x86_mov_regp_reg (s->code, tree->left->reg1, t, 4);
+			break;
+		}
+		x86_pop_reg (s->code, t);
+
+		return;
+	}
+
+	i = tree->data.i / 4;
+	j = tree->data.i % 4;
+
+	x86_push_reg (s->code, X86_EAX);
+	
+	if (tree->left->reg1 != X86_EDI) {
+		x86_push_reg (s->code, X86_EDI);
+		x86_mov_reg_reg (s->code, X86_EDI, tree->left->reg1, 4);
+	}
+
+	if (i) {
+		x86_push_reg (s->code, X86_ECX);
+		x86_alu_reg_reg (s->code, X86_XOR, X86_EAX, X86_EAX);
+		x86_mov_reg_imm (s->code, X86_ECX, i);
+		x86_cld (s->code);
+		x86_prefix (s->code, X86_REP_PREFIX);
+		x86_stosl (s->code);
+		x86_pop_reg (s->code, X86_ECX);
+	}
+
+
+	if (j == 2) {
+		x86_prefix (s->code, X86_OPERAND_PREFIX);
+		x86_stosl (s->code);
+	} else {
+		for (i = 0; i < j; i++)
+			x86_stosb (s->code);
+	}
+
+	if (tree->left->reg1 != X86_EDI)
+		x86_pop_reg (s->code, X86_EDI);
+	
+	x86_pop_reg (s->code, X86_EAX);
 }
 
 stmt: NOP
Index: mono/metadata/ChangeLog
===================================================================
RCS file: /cvs/public/mono/mono/metadata/ChangeLog,v
retrieving revision 1.83
diff -u -r1.83 ChangeLog
--- mono/metadata/ChangeLog	2001/11/08 21:38:32	1.83
+++ mono/metadata/ChangeLog	2001/11/09 13:38:15
@@ -1,3 +1,7 @@
+2001-11-09  Dietmar Maurer  <dietmar@ximian.com>
+
+	* class.c (mono_class_metadata_init): bug fix: compute the right slot
+
 2001-11-07  Miguel de _caza  <miguel@ximian.com>
 
 	* reflection.c (build_compressed_metadata): Eliminates warnings
Index: mono/metadata/class.c
===================================================================
RCS file: /cvs/public/mono/mono/metadata/class.c,v
retrieving revision 1.50
diff -u -r1.50 class.c
--- mono/metadata/class.c	2001/11/08 21:38:32	1.50
+++ mono/metadata/class.c	2001/11/09 13:38:15
@@ -240,9 +240,14 @@
 	for (k = class->parent; k ; k = k->parent) {
 		for (i = 0; i < k->interface_count; i++) {
 			ic = k->interfaces [i]; 
-			if (class->interface_offsets [ic->interface_id] == NULL)
-				class->interface_offsets [ic->interface_id] = 
-					&class->vtable [(k->interface_offsets [ic->interface_id] -
(gpointer)k->vtable)>>2];
+			if (class->interface_offsets [ic->interface_id] == NULL) {
+				int io = (k->interface_offsets [ic->interface_id] -
(gpointer)k->vtable)>>2;
+
+				g_assert (io >= 0);
+				g_assert (io <= class->vtable_size);
+
+				class->interface_offsets [ic->interface_id] = &class->vtable [io];
+			}
 		}
 	}
 
@@ -257,7 +262,10 @@
 			int j, l, io;
 			ic = k->interfaces [i];
 
-			io = (class->interface_offsets [ic->interface_id] -
(gpointer)k->vtable)>>2;
+			io = (k->interface_offsets [ic->interface_id] -
(gpointer)k->vtable)>>2;
+			
+			g_assert (io >= 0);
+			g_assert (io <= class->vtable_size);
 
 			if (k == class) {
 				for (l = 0; l < ic->method.count; l++) {