+2008-05-22 Mark Probst <mark.probst@gmail.com>
+
+ * inssel.brg, mini-ops.h: Added opcodes for mkrefany and refanyval
+ with computed types (for generic sharing).
+
+ * mini.c: Generic sharing for mkrefany and refanyval.
+
2008-05-22 Zoltan Varga <vargaz@gmail.com>
* inssel.brg (mini_emit_virtual_call): Avoid constructing a generic vtable if
MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, value));
}
+reg: OP_REFANYVAL_REG (reg, reg) {
+ int klass_reg = mono_regstate_next_int (s->rs);
+ g_assert (!s->compile_aot);
+ MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, state->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, klass));
+ MONO_EMIT_NEW_COMPARE_EXC (s, NE_UN, klass_reg, state->right->reg1, "InvalidCastException");
+ MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, value));
+}
+
reg: OP_REFANYTYPE (reg) {
MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, type));
}
MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREP_MEMBASE_REG, state->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, value), state->left->left->reg1);
}
+stmt: OP_MKREFANY_REGS (OP_GROUP (reg, reg), OP_GROUP (reg, reg)) {
+ int class_reg = state->left->right->reg1;
+ g_assert (!s->compile_aot);
+ MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREP_MEMBASE_REG,
+ state->right->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, type), state->left->left->reg1);
+ MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREP_MEMBASE_REG,
+ state->right->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, klass), state->left->right->reg1);
+ MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREP_MEMBASE_REG,
+ state->right->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, value), state->right->left->reg1);
+}
+
reg: OP_MIN (reg, reg) "2" {
/* min (x,y) = y + (((x-y)>>31)&(x-y)); */
int diff = mono_regstate_next_int (s->rs);
MINI_OP(OP_CCASTCLASS, "ccastclass")
MINI_OP(OP_SAVE_LMF, "save_lmf")
MINI_OP(OP_RESTORE_LMF, "restore_lmf")
+/* mkrefany/refanyval for generic sharing */
+MINI_OP(OP_MKREFANY_REGS, "mkrefany_regs")
+MINI_OP(OP_REFANYVAL_REG, "refanyval_reg")
/* arch-dep tls access */
MINI_OP(OP_TLS_GET, "tls_get")
++ip;
break;
}
- case CEE_REFANYVAL:
+ case CEE_REFANYVAL: {
+ int context_used = 0;
+
CHECK_STACK (1);
- MONO_INST_NEW (cfg, ins, *ip);
--sp;
CHECK_OPSIZE (5);
- klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
+ token = read32 (ip + 1);
+ klass = mono_class_get_full (image, token, generic_context);
CHECK_TYPELOAD (klass);
mono_class_init (klass);
- ins->type = STACK_MP;
- ins->inst_left = *sp;
- ins->klass = klass;
- ins->inst_newa_class = klass;
+
+ if (cfg->generic_sharing_context) {
+ context_used = mono_class_check_context_used (klass);
+ if (context_used && cfg->compile_aot)
+ GENERIC_SHARING_FAILURE (*ip);
+ }
+
+ if (context_used) {
+ MonoInst *rgctx;
+
+ MONO_INST_NEW (cfg, ins, OP_REFANYVAL_REG);
+ ins->type = STACK_MP;
+ ins->inst_left = *sp;
+ ins->klass = klass;
+
+ GET_RGCTX (rgctx);
+ ins->inst_right = get_runtime_generic_context_ptr (cfg, method,
+ bblock, klass,
+ token, MINI_TOKEN_SOURCE_CLASS, generic_context,
+ rgctx, MONO_RGCTX_INFO_KLASS, ip);
+ } else {
+ MONO_INST_NEW (cfg, ins, *ip);
+ ins->type = STACK_MP;
+ ins->inst_left = *sp;
+ ins->klass = klass;
+ ins->inst_newa_class = klass;
+ }
ins->cil_code = ip;
ip += 5;
*sp++ = ins;
break;
+ }
case CEE_MKREFANY: {
- MonoInst *loc, *klassconst;
+ MonoInst *loc;
+ int context_used = 0;
CHECK_STACK (1);
- MONO_INST_NEW (cfg, ins, *ip);
--sp;
CHECK_OPSIZE (5);
- klass = mono_class_get_full (image, read32 (ip + 1), generic_context);
+ token = read32 (ip + 1);
+ klass = mono_class_get_full (image, token, generic_context);
CHECK_TYPELOAD (klass);
mono_class_init (klass);
- ins->cil_code = ip;
- if (cfg->generic_sharing_context && mono_class_check_context_used (klass))
- GENERIC_SHARING_FAILURE (CEE_MKREFANY);
+ if (cfg->generic_sharing_context) {
+ context_used = mono_class_check_context_used (klass);
+ if (context_used && cfg->compile_aot)
+ GENERIC_SHARING_FAILURE (CEE_MKREFANY);
+ }
loc = mono_compile_create_var (cfg, &mono_defaults.typed_reference_class->byval_arg, OP_LOCAL);
- NEW_TEMPLOADA (cfg, ins->inst_right, loc->inst_c0);
+ if (context_used) {
+ MonoInst *rgctx, *klass_type, *klass_klass, *loc_load;
+
+ GET_RGCTX (rgctx);
+ klass_klass = get_runtime_generic_context_ptr (cfg, method, bblock, klass,
+ token, MINI_TOKEN_SOURCE_CLASS, generic_context,
+ rgctx, MONO_RGCTX_INFO_KLASS, ip);
+ GET_RGCTX (rgctx);
+ klass_type = get_runtime_generic_context_ptr (cfg, method, bblock, klass,
+ token, MINI_TOKEN_SOURCE_CLASS, generic_context,
+ rgctx, MONO_RGCTX_INFO_TYPE, ip);
+
+ NEW_TEMPLOADA (cfg, loc_load, loc->inst_c0);
+
+ MONO_INST_NEW (cfg, ins, OP_MKREFANY_REGS);
+ NEW_GROUP (cfg, ins->inst_left, klass_type, klass_klass);
+ NEW_GROUP (cfg, ins->inst_right, *sp, loc_load);
+ } else {
+ MonoInst *klassconst;
+
+ NEW_PCONST (cfg, klassconst, klass);
+
+ MONO_INST_NEW (cfg, ins, *ip);
+ NEW_TEMPLOADA (cfg, ins->inst_right, loc->inst_c0);
+ NEW_GROUP (cfg, ins->inst_left, *sp, klassconst);
+ }
+
+ ins->cil_code = ip;
- NEW_PCONST (cfg, klassconst, klass);
- NEW_GROUP (cfg, ins->inst_left, *sp, klassconst);
-
MONO_ADD_INS (bblock, ins);
NEW_TEMPLOAD (cfg, *sp, loc->inst_c0);
if (nts [1]) {
emit_state (cfg, kids [1], nts [1]);
if (nts [2]) {
- g_assert (!nts [3]);
emit_state (cfg, kids [2], nts [2]);
+ if (nts [3]) {
+ g_assert (!nts [4]);
+ emit_state (cfg, kids [3], nts [3]);
+ }
}
}
}
+2008-05-22 Mark Probst <mark.probst@gmail.com>
+
+ * generic-refanyval.2.il: Test case for generic refanyval.
+
+ * Makefile.am: Test added.
+
2008-05-21 Rodrigo Kumpera <rkumpera@novell.com>
* bug-325283.2.cs: Regression test for bug #325283.
generics-sharing-other-exc.2.il \
generic-ldobj.2.il \
generic-mkrefany.2.il \
+ generic-refanyval.2.il \
generic-ldtoken.2.il \
generic-ldtoken-method.2.il \
generic-ldtoken-field.2.il \
generics-sharing-other-exc.2.exe generic-box.2.exe \
generic-unbox.2.exe generic-delegate.2.exe generic-sizeof.2.exe \
generic-ldobj.2.exe generic-mkrefany.2.exe \
- generic-ldtoken.2.exe \
+ generic-refanyval.2.exe generic-ldtoken.2.exe \
generic-ldtoken-method.2.exe generic-ldtoken-field.2.exe \
generic-virtual.2.exe generic-tailcall.2.exe \
generic-interface-methods.2.exe generic-array-type.2.exe \
$(RUNTIME) -O=gshared,-inline generic-sizeof.2.exe
$(RUNTIME) -O=gshared,-inline generic-ldobj.2.exe
$(RUNTIME) -O=gshared,-inline generic-mkrefany.2.exe
+ $(RUNTIME) -O=gshared,-inline generic-refanyval.2.exe
$(RUNTIME) -O=gshared,-inline generic-ldtoken.2.exe
$(RUNTIME) -O=gshared,-inline generic-ldtoken-method.2.exe
$(RUNTIME) -O=gshared,-inline generic-ldtoken-field.2.exe
--- /dev/null
+.assembly extern mscorlib
+{
+ .ver 2:0:0:0
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+}
+.assembly 'generic-mkrefany.2'
+{
+ .custom instance void class [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::'.ctor'() = (
+ 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
+ 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
+
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module 'generic-mkrefany.2.exe' // GUID = {51FFBB77-6AFB-435E-B206-16DB5C8A3730}
+
+
+ .class public auto ansi beforefieldinit ClassA
+ extends [mscorlib]System.Object
+ {
+
+ // method line 1
+ .method public hidebysig specialname rtspecialname
+ instance default void '.ctor' () cil managed
+ {
+ // Method begins at RVA 0x20ec
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void object::'.ctor'()
+ IL_0006: ret
+ } // end of method ClassA::.ctor
+
+ } // end of class ClassA
+
+ .class public sequential ansi sealed beforefieldinit GenStruct`1<T>
+ extends [mscorlib]System.ValueType
+ {
+ .field public int32 field1
+ .field public !0 field2
+
+ } // end of class GenStruct`1
+
+ .class public auto ansi beforefieldinit Gen`1<T>
+ extends [mscorlib]System.Object
+ {
+
+ // method line 2
+ .method public hidebysig specialname rtspecialname
+ instance default void '.ctor' () cil managed
+ {
+ // Method begins at RVA 0x20f4
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void object::'.ctor'()
+ IL_0006: ret
+ } // end of method Gen`1::.ctor
+
+ // method line 3
+ .method public hidebysig
+ instance default !T ident (!T t) cil managed
+ {
+ // Method begins at RVA 0x20fc
+ // Code size 4 (0x4)
+ .maxstack 1
+ .locals init (
+ !T V_0)
+ IL_0000: ldarg.1
+ IL_0001: stloc.0
+ ldloca 0
+ mkrefany ClassA
+ refanyval !0
+ ldobj ClassA
+ IL_0003: ret
+ } // end of method Gen`1::ident
+
+ // method line 4
+ .method public hidebysig
+ instance default valuetype GenStruct`1<!T> structIdent (valuetype GenStruct`1<!T> gst) cil managed
+ {
+ // Method begins at RVA 0x210c
+ // Code size 4 (0x4)
+ .maxstack 1
+ .locals init (
+ valuetype GenStruct`1<!T> V_0)
+ IL_0000: ldarg.1
+ IL_0001: stloc.0
+ ldloca 0
+ mkrefany valuetype GenStruct`1<ClassA>
+ refanyval valuetype GenStruct`1<!0>
+ ldobj valuetype GenStruct`1<ClassA>
+ IL_0003: ret
+ } // end of method Gen`1::structIdent
+
+ } // end of class Gen`1
+
+ .class public auto ansi beforefieldinit main
+ extends [mscorlib]System.Object
+ {
+
+ // method line 5
+ .method public hidebysig specialname rtspecialname
+ instance default void '.ctor' () cil managed
+ {
+ // Method begins at RVA 0x211c
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void object::'.ctor'()
+ IL_0006: ret
+ } // end of method main::.ctor
+
+ // method line 6
+ .method public static hidebysig
+ default int32 Main () cil managed
+ {
+ // Method begins at RVA 0x2124
+ .entrypoint
+ // Code size 94 (0x5e)
+ .maxstack 8
+ .locals init (
+ class ClassA V_0,
+ valuetype GenStruct`1<class ClassA> V_1,
+ class Gen`1<class ClassA> V_2,
+ valuetype GenStruct`1<class ClassA> V_3)
+ IL_0000: newobj instance void class ClassA::'.ctor'()
+ IL_0005: stloc.0
+ IL_0006: ldloca.s 1
+ IL_0008: ldc.i4.s 0x7b
+ IL_000a: stfld int32 valuetype GenStruct`1<class ClassA>::field1
+ IL_000f: ldloca.s 1
+ IL_0011: ldloc.0
+ IL_0012: stfld !0 valuetype GenStruct`1<class ClassA>::field2
+ IL_0017: newobj instance void class Gen`1<class ClassA>::'.ctor'()
+ IL_001c: stloc.2
+ IL_001d: ldloc.2
+ IL_001e: ldloc.0
+ IL_001f: callvirt instance !0 class Gen`1<class ClassA>::ident(!0)
+ IL_0024: ldloc.0
+ IL_0025: beq IL_002c
+
+ IL_002a: ldc.i4.1
+ IL_002b: ret
+ IL_002c: ldloc.2
+ IL_002d: ldloc.1
+ IL_002e: callvirt instance valuetype GenStruct`1<!0> class Gen`1<class ClassA>::structIdent(valuetype GenStruct`1<!0>)
+ IL_0033: stloc.3
+ IL_0034: ldloca.s 3
+ IL_0036: ldfld int32 valuetype GenStruct`1<class ClassA>::field1
+ IL_003b: ldloca.s 1
+ IL_003d: ldfld int32 valuetype GenStruct`1<class ClassA>::field1
+ IL_0042: bne.un IL_005a
+
+ IL_0047: ldloca.s 3
+ IL_0049: ldfld !0 valuetype GenStruct`1<class ClassA>::field2
+ IL_004e: ldloca.s 1
+ IL_0050: ldfld !0 valuetype GenStruct`1<class ClassA>::field2
+ IL_0055: beq IL_005c
+
+ IL_005a: ldc.i4.1
+ IL_005b: ret
+ IL_005c: ldc.i4.0
+ IL_005d: ret
+ } // end of method main::Main
+
+ } // end of class main
+