Interp fixes (#4864)
authorZoltan Varga <vargaz@gmail.com>
Mon, 15 May 2017 22:53:10 +0000 (18:53 -0400)
committerGitHub <noreply@github.com>
Mon, 15 May 2017 22:53:10 +0000 (18:53 -0400)
* [interp] Add support for mkrefany,refanytype and refanyval.

* [interp] Avoid inlining empty methods marked with NoInlining.

* [interp] Fix the popping of arguments when inlining empty methods.

mono/mini/interp/interp.c
mono/mini/interp/mintops.def
mono/mini/interp/transform.c
mono/mini/objects.cs

index 790d57fb0d231ade15eefa369ee23c8556df37ad..64c101a30abf76c83ba629403c8a022818f180d8 100644 (file)
@@ -4291,17 +4291,50 @@ array_constructed:
                MINT_IN_CASE(MINT_LDELEM) 
                MINT_IN_CASE(MINT_STELEM) 
                MINT_IN_CASE(MINT_UNBOX_ANY) 
-
-               MINT_IN_CASE(MINT_REFANYVAL) ves_abort(); MINT_IN_BREAK;
 #endif
                MINT_IN_CASE(MINT_CKFINITE)
                        if (!isfinite(sp [-1].data.f))
                                THROW_EX (mono_get_exception_arithmetic (), ip);
                        ++ip;
                        MINT_IN_BREAK;
-#if 0
-               MINT_IN_CASE(MINT_MKREFANY) ves_abort(); MINT_IN_BREAK;
-#endif
+               MINT_IN_CASE(MINT_MKREFANY) {
+                       c = rtm->data_items [*(guint16 *)(ip + 1)];
+
+                       /* The value address is on the stack */
+                       gpointer addr = sp [-1].data.p;
+                       /* Push the typedref value on the stack */
+                       sp [-1].data.p = vt_sp;
+                       vt_sp += sizeof (MonoTypedRef);
+
+                       MonoTypedRef *tref = sp [-1].data.p;
+                       tref->klass = c;
+                       tref->type = &c->byval_arg;
+                       tref->value = addr;
+
+                       ip += 2;
+                       MINT_IN_BREAK;
+               }
+               MINT_IN_CASE(MINT_REFANYTYPE) {
+                       MonoTypedRef *tref = sp [-1].data.p;
+                       MonoType *type = tref->type;
+
+                       vt_sp -= sizeof (MonoTypedRef);
+                       sp [-1].data.p = vt_sp;
+                       vt_sp += 8;
+                       *(gpointer*)sp [-1].data.p = type;
+                       ip ++;
+                       MINT_IN_BREAK;
+               }
+               MINT_IN_CASE(MINT_REFANYVAL) {
+                       MonoTypedRef *tref = sp [-1].data.p;
+                       gpointer addr = tref->value;
+
+                       vt_sp -= sizeof (MonoTypedRef);
+
+                       sp [-1].data.p = addr;
+                       ip ++;
+                       MINT_IN_BREAK;
+               }
                MINT_IN_CASE(MINT_LDTOKEN)
                        sp->data.p = vt_sp;
                        vt_sp += 8;
index 68a559f6db5c0c969d75dfdc5728760236af5d0b..190c6647d08adef26aee2599bfc0bbe2c2be21e1 100644 (file)
@@ -490,6 +490,9 @@ OPDEF(MINT_CLT_UN_I8, "clt.un.i8", 1, MintOpNoArgs)
 OPDEF(MINT_CLT_UN_R8, "clt.un.r8", 1, MintOpNoArgs)
 
 OPDEF(MINT_CKFINITE, "ckfinite", 1, MintOpNoArgs)
+OPDEF(MINT_MKREFANY, "mkrefany", 2, MintOpClassToken)
+OPDEF(MINT_REFANYTYPE, "refanytype", 1, MintOpNoArgs)
+OPDEF(MINT_REFANYVAL, "refanyval", 1, MintOpNoArgs)
 
 OPDEF(MINT_CKNULL, "cknull", 1, MintOpNoArgs)
 
index e5c8f3f00abe61148ad8fed3081c6bebb878f55a..4ffb0d614559b0a0bc0d9c27d9b84804cad613d5 100644 (file)
@@ -321,6 +321,8 @@ enum_type:
                        goto enum_type;
                } else
                        return MINT_TYPE_VT;
+       case MONO_TYPE_TYPEDBYREF:
+               return MINT_TYPE_VT;
        case MONO_TYPE_GENERICINST:
                type = &type->data.generic_class->container_class->byval_arg;
                goto enum_type;
@@ -793,7 +795,8 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
        CHECK_STACK (td, csignature->param_count + csignature->hasthis);
        if (!calli && (!virtual || (target_method->flags & METHOD_ATTRIBUTE_VIRTUAL) == 0) &&
                (target_method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 && 
-               (target_method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) == 0) {
+               (target_method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) == 0 &&
+               !(target_method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING)) {
                int called_inited = mono_class_vtable (domain, target_method->klass)->initialized;
                MonoMethodHeader *mheader = mono_method_get_header (target_method);
 
@@ -817,9 +820,10 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
                        if (mheader && *mheader->code == CEE_RET && called_inited) {
                                if (mono_interp_traceopt)
                                        g_print ("Inline (empty) call of %s.%s\n", target_method->klass->name, target_method->name);
-                               for (i = 0; i < csignature->param_count; i++)
+                               for (i = 0; i < csignature->param_count; i++) {
                                        ADD_CODE (td, MINT_POP); /*FIX: vt */
                                        ADD_CODE (td, 0);
+                               }
                                if (csignature->hasthis) {
                                        if (virtual)
                                                ADD_CODE(td, MINT_CKNULL);
@@ -2632,12 +2636,37 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
 #if SIZEOF_VOID_P == 8
                case CEE_CONV_OVF_U:
 #endif
-               case CEE_REFANYVAL: ves_abort(); break;
 #endif
                case CEE_CKFINITE:
                        CHECK_STACK (&td, 1);
                        SIMPLE_OP (td, MINT_CKFINITE);
                        break;
+               case CEE_MKREFANY:
+                       CHECK_STACK (&td, 1);
+                       ENSURE_I4 (&td, 2);
+                       token = read32 (td.ip + 1);
+                       klass = mini_get_class (method, token, generic_context);
+
+                       ADD_CODE (&td, MINT_MKREFANY);
+                       ADD_CODE (&td, get_data_item_index (&td, klass));
+
+                       td.ip += 5;
+                       PUSH_VT (&td, sizeof (MonoTypedRef));
+                       SET_TYPE(td.sp - 1, STACK_TYPE_VT, mono_defaults.typed_reference_class);
+                       break;
+               case CEE_REFANYVAL: {
+                       CHECK_STACK (&td, 1);
+                       ENSURE_I4 (&td, 2);
+                       token = read32 (td.ip + 1);
+
+                       ADD_CODE (&td, MINT_REFANYVAL);
+
+                       POP_VT (&td, sizeof (MonoTypedRef));
+                       SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_MP);
+
+                       td.ip += 5;
+                       break;
+               }
                case CEE_CONV_OVF_I1:
                case CEE_CONV_OVF_I1_UN:
                        CHECK_STACK (&td, 1);
@@ -3287,9 +3316,13 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                                PUSH_SIMPLE_TYPE(&td, STACK_TYPE_I4);
                                break;
                        }
-#if 0
-                       case CEE_REFANYTYPE: ves_abort(); break;
-#endif
+                       case CEE_REFANYTYPE:
+                               ADD_CODE (&td, MINT_REFANYTYPE);
+                               td.ip += 1;
+                               POP_VT (&td, sizeof (MonoTypedRef));
+                               PUSH_VT (&td, sizeof (gpointer));
+                               SET_TYPE(td.sp - 1, STACK_TYPE_VT, NULL);
+                               break;
                        default:
                                g_error ("transform.c: Unimplemented opcode: 0xFE %02x (%s) at 0x%x\n", *td.ip, mono_opcode_name (256 + *td.ip), td.ip-header->code);
                        }
index 8d0cf336b8c96281d5670973cad0a1133cccb9fe..ef796986cd5419e570167885a1b9220f2b6eace6 100644 (file)
@@ -1809,6 +1809,25 @@ ncells ) {
 
         return 0;
     }
+
+       public static int test_0_typedref () {
+               int i = 5;
+               System.TypedReference r = __makeref(i);
+               System.Type t = __reftype(r);
+
+               if (t != typeof (int))
+                       return 1;
+               int j = __refvalue(r, int);
+               if (j != 5)
+                       return 2;
+
+               try {
+                       object o = __refvalue (r, object);
+               } catch (InvalidCastException) {
+               }
+
+               return 0;
+       }
 }
 
 #if __MOBILE__