[interp] implement cee_unbox and cee_ldobj correctly
authorBernhard Urban <bernhard.urban@xamarin.com>
Tue, 7 Mar 2017 09:46:58 +0000 (10:46 +0100)
committerBernhard Urban <bernhard.urban@xamarin.com>
Wed, 8 Mar 2017 22:02:51 +0000 (23:02 +0100)
unbox is supposed to push a managed pointer on the stack and ldobj does
the actual value copy.  unbox_any is basically unbox+ldobj according to
the spec.

fixes random crashes in test_0_regress_80622:iltests.il

mono/mini/interp/interp.c
mono/mini/interp/transform.c

index 7092c749b08e07ac241dbcf6f10f6c34fe503cd5..d881e23dfaba954d9ac2efbce915c4531a9bc123 100644 (file)
@@ -2767,20 +2767,16 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
                }
 #endif
                MINT_IN_CASE(MINT_LDOBJ) {
-                       int size;
                        void *p;
                        c = rtm->data_items[* (guint16 *)(ip + 1)];
                        ip += 2;
-                       if (c->byval_arg.type != MONO_TYPE_VALUETYPE || c->byval_arg.data.klass->enumtype) {
-                               p = sp [-1].data.p;
-                               stackval_from_data (&c->byval_arg, &sp [-1], p, FALSE);
-                       } else {
-                               size = mono_class_value_size (c, NULL);
-                               p = sp [-1].data.p;
+                       p = sp [-1].data.p;
+                       if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
+                               int size = mono_class_value_size (c, NULL);
                                sp [-1].data.p = vt_sp;
-                               memcpy(vt_sp, p, size);
                                vt_sp += (size + 7) & ~7;
                        }
+                       stackval_from_data (&c->byval_arg, &sp [-1], p, FALSE);
                        MINT_IN_BREAK;
                }
                MINT_IN_CASE(MINT_LDSTR)
@@ -2919,12 +2915,7 @@ array_constructed:
                        if (!(isinst_obj || ((o->vtable->klass->rank == 0) && (o->vtable->klass->element_class == c->element_class))))
                                THROW_EX (mono_get_exception_invalid_cast (), ip);
 
-                       if (c->byval_arg.type == MONO_TYPE_VALUETYPE && !c->enumtype) {
-                               int size = mono_class_native_size (c, NULL);
-                               sp [-1].data.p = vt_sp;
-                               vt_sp += (size + 7) & ~7;
-                       }
-                       stackval_from_data (&c->byval_arg, &sp [-1], mono_object_unbox (o), FALSE);
+                       sp [-1].data.p = mono_object_unbox (o);
                        ip += 2;
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_THROW)
index 7496c18596ce23add761361ecd41464a033d8e58..5e2876cd869f292db1de39cd72f16e4acd1d8105 100644 (file)
@@ -1953,7 +1953,11 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                                int mt = mint_type (&klass->byval_arg);
                                ADD_CODE (&td, MINT_UNBOX);
                                ADD_CODE (&td, get_data_item_index (&td, klass));
+
+                               ADD_CODE (&td, MINT_LDOBJ);
+                               ADD_CODE (&td, get_data_item_index(&td, klass));
                                SET_TYPE (td.sp - 1, stack_type [mt], klass);
+
                                if (mt == MINT_TYPE_VT) {
                                        int size = mono_class_value_size (klass, NULL);
                                        PUSH_VT (&td, size);