diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 54d4c7ea093d3..ed38874fbf5f3 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -6088,6 +6088,11 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; ip += 4; MINT_IN_BREAK; } + MINT_IN_CASE(MINT_STOBJ_VT_NOREF) { + memcpy (LOCAL_VAR (ip [1], gpointer), locals + ip [2], ip [3]); + ip += 4; + MINT_IN_BREAK; + } MINT_IN_CASE(MINT_CONV_OVF_U8_I4) { gint32 val = LOCAL_VAR (ip [2], gint32); if (val < 0) diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index 75097c79bfefa..f8b65c48c404d 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -382,6 +382,7 @@ OPDEF(MINT_CPOBJ, "cpobj", 4, 0, 2, MintOpClassToken) OPDEF(MINT_CPOBJ_VT, "cpobj.vt", 4, 0, 2, MintOpClassToken) OPDEF(MINT_LDOBJ_VT, "ldobj.vt", 4, 1, 1, MintOpShortInt) OPDEF(MINT_STOBJ_VT, "stobj.vt", 4, 0, 2, MintOpClassToken) +OPDEF(MINT_STOBJ_VT_NOREF, "stobj.vt.noref", 4, 0, 2, MintOpShortInt) OPDEF(MINT_CPBLK, "cpblk", 4, 0, 3, MintOpNoArgs) OPDEF(MINT_INITBLK, "initblk", 4, 0, 3, MintOpNoArgs) OPDEF(MINT_LOCALLOC, "localloc", 3, 1, 1, MintOpNoArgs) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 94f0ee6aae77d..b45cd93023c98 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -1856,19 +1856,27 @@ interp_emit_ldobj (TransformData *td, MonoClass *klass) } static void -interp_emit_stobj (TransformData *td, MonoClass *klass) +interp_emit_stobj (TransformData *td, MonoClass *klass, gboolean reverse_order) { int mt = mint_type (m_class_get_byval_arg (klass)); if (mt == MINT_TYPE_VT) { - interp_add_ins (td, MINT_STOBJ_VT); - td->last_ins->data [0] = get_data_item_index (td, klass); + if (m_class_has_references (klass)) { + interp_add_ins (td, MINT_STOBJ_VT); + td->last_ins->data [0] = get_data_item_index (td, klass); + } else { + interp_add_ins (td, MINT_STOBJ_VT_NOREF); + td->last_ins->data [0] = GINT32_TO_UINT16 (mono_class_value_size (klass, NULL)); + } } else { int opcode = interp_get_stind_for_mt (mt); interp_add_ins (td, opcode); } td->sp -= 2; - interp_ins_set_sregs2 (td->last_ins, td->sp [0].local, td->sp [1].local); + if (reverse_order) + interp_ins_set_sregs2 (td->last_ins, td->sp [1].local, td->sp [0].local); + else + interp_ins_set_sregs2 (td->last_ins, td->sp [0].local, td->sp [1].local); } static void @@ -1993,7 +2001,7 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas store_local (td, local); interp_emit_ldelema (td, target_method->klass, value_class); load_local (td, local); - interp_emit_stobj (td, element_class); + interp_emit_stobj (td, element_class, FALSE); td->ip += 5; return TRUE; } else if (!strcmp (tm, "UnsafeStore")) { @@ -2210,7 +2218,7 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas MonoClass *klass = mono_class_from_mono_type_internal (type); interp_emit_ldobj (td, klass); - interp_emit_stobj (td, klass); + interp_emit_stobj (td, klass, FALSE); td->ip += 5; return TRUE; @@ -4175,12 +4183,7 @@ interp_emit_sfld_access (TransformData *td, MonoClassField *field, MonoClass *fi interp_ins_set_dreg (td->last_ins, td->sp [-1].local); } } else { - int opcode = (mt == MINT_TYPE_VT) ? MINT_STOBJ_VT : interp_get_stind_for_mt (mt); - interp_add_ins (td, opcode); - td->sp -= 2; - interp_ins_set_sregs2 (td->last_ins, td->sp [1].local, td->sp [0].local); - if (mt == MINT_TYPE_VT) - td->last_ins->data [0] = get_data_item_index (td, field_class); + interp_emit_stobj (td, field_class, TRUE); } } else { gpointer field_addr = mono_static_field_get_addr (vtable, field); @@ -6201,7 +6204,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, interp_emit_metadata_update_ldflda (td, field, error); goto_if_nok (error, exit); load_local (td, local); - interp_emit_stobj (td, field_class); + interp_emit_stobj (td, field_class, FALSE); td->ip += 5; break; } @@ -6297,7 +6300,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, BARRIER_IF_VOLATILE (td, MONO_MEMORY_BARRIER_REL); - interp_emit_stobj (td, klass); + interp_emit_stobj (td, klass, FALSE); td->ip += 5; break;