2008-05-22 Mark Probst <mark.probst@gmail.com>
authorMark Probst <mark.probst@gmail.com>
Thu, 22 May 2008 21:00:56 +0000 (21:00 -0000)
committerMark Probst <mark.probst@gmail.com>
Thu, 22 May 2008 21:00:56 +0000 (21:00 -0000)
* 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  Mark Probst  <mark.probst@gmail.com>

* generic-refanyval.2.il: Test case for generic refanyval.

* Makefile.am: Test added.

svn path=/trunk/mono/; revision=103844

mono/mini/ChangeLog
mono/mini/inssel.brg
mono/mini/mini-ops.h
mono/mini/mini.c
mono/tests/ChangeLog
mono/tests/Makefile.am
mono/tests/generic-refanyval.2.il [new file with mode: 0644]

index cb50d01752afe6637985f4917dce1c37037f281a..69c8ea42f2a6db3e9deb90ec308da3a7edb40f09 100644 (file)
@@ -1,3 +1,10 @@
+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
index ae8da9a98a6324a9e9f16f3be0c12fd0e641c995..d881614ee6a856ecb618be417cd5553f5e25b55b 100644 (file)
@@ -1647,6 +1647,14 @@ reg: CEE_REFANYVAL (reg) {
        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));
 }      
@@ -1669,6 +1677,17 @@ stmt: CEE_MKREFANY (OP_GROUP (reg, OP_I8CONST), reg) {
        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);
index 8b5a7d817f471df68d6bb9776d18756aa041c4da..66b6ac1363f1ebcd8f873dea5165d7b32a19a152 100644 (file)
@@ -543,6 +543,9 @@ MINI_OP(OP_CISINST, "cisinst")
 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")
index 9df12cbdadba3d644cdc5de792564c36436a7325..9cb6c4b66fd8a83a53e5f31493716d39be2c9119 100644 (file)
@@ -8059,43 +8059,96 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ++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);
@@ -11178,8 +11231,11 @@ emit_state (MonoCompile *cfg, MBState *state, int goal)
                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]);
+                               }
                        }
                }
        }
index d78b2b43d399b701e6aa7bbd84e8e187d4a43300..4365a6ebf9f989df870698033c018949efc7d150 100644 (file)
@@ -1,3 +1,9 @@
+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.
index 8b5a112cb51c8be7c29f63e0544cb136d2814014..6ba0c1ca93e133fd64a7c97230a1503ac1b7a65f 100644 (file)
@@ -368,6 +368,7 @@ TEST_IL_SRC=                        \
        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      \
@@ -692,7 +693,7 @@ test-generic-sharing : generics-sharing.2.exe shared-generic-methods.2.exe  \
                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        \
@@ -708,6 +709,7 @@ test-generic-sharing : generics-sharing.2.exe shared-generic-methods.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
diff --git a/mono/tests/generic-refanyval.2.il b/mono/tests/generic-refanyval.2.il
new file mode 100644 (file)
index 0000000..fffaeaa
--- /dev/null
@@ -0,0 +1,168 @@
+.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
+