diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index b1472278a9dd73..ea7dbc2ddb949a 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -5202,8 +5202,8 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs gpointer *byreference_this = (gpointer*)vt_sp; *byreference_this = arg0; - /* Followed by a VTRESULT opcode which will push the result on the stack */ - /* FIXME kill MINT_VTRESULT */ + sp [-1].data.p = vt_sp; + vt_sp += MINT_VT_ALIGNMENT; ip++; MINT_IN_BREAK; } @@ -5514,6 +5514,21 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs MINT_IN_CASE(MINT_STFLD_I8_UNALIGNED) STFLD_UNALIGNED(l, gint64, TRUE); MINT_IN_BREAK; MINT_IN_CASE(MINT_STFLD_R8_UNALIGNED) STFLD_UNALIGNED(f, double, TRUE); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STFLD_VT_NOREF) { + MonoObject* const o = sp [-2].data.o; + NULL_CHECK (o); + sp -= 2; + + guint16 offset = ip [1]; + guint16 vtsize = ip [2]; + + memcpy ((char *) o + offset, sp [1].data.p, vtsize); + + vt_sp -= ALIGN_TO (vtsize, MINT_VT_ALIGNMENT); + ip += 3; + MINT_IN_BREAK; + } + MINT_IN_CASE(MINT_STFLD_VT) { MonoObject* const o = sp [-2].data.o; NULL_CHECK (o); diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index edef35ef971a21..3ba07ec600c808 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -138,6 +138,7 @@ OPDEF(MINT_STFLD_R4, "stfld.r4", 2, Pop2, Push0, MintOpUShortInt) OPDEF(MINT_STFLD_R8, "stfld.r8", 2, Pop2, Push0, MintOpUShortInt) OPDEF(MINT_STFLD_O, "stfld.o", 2, Pop2, Push0, MintOpUShortInt) OPDEF(MINT_STFLD_VT, "stfld.vt", 3, Pop2, Push0, MintOpTwoShorts) +OPDEF(MINT_STFLD_VT_NOREF, "stfld.vt.noref", 3, Pop2, Push0, MintOpTwoShorts) OPDEF(MINT_STFLD_I8_UNALIGNED, "stfld.i8.unaligned", 2, Pop2, Push0, MintOpUShortInt) OPDEF(MINT_STFLD_R8_UNALIGNED, "stfld.r8.unaligned", 2, Pop2, Push0, MintOpUShortInt) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index e6f7eb52a6c3a2..af28de5ddd1ff7 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -4731,7 +4731,9 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, vt_stack_used += size; } } - if (vt_stack_used != 0 || vt_res_size != 0) { + if ((vt_stack_used != 0 || vt_res_size != 0) && + td->last_ins->opcode != MINT_INTRINS_BYREFERENCE_CTOR) { + /* FIXME Remove this once vtsp and sp are unified */ interp_add_ins (td, MINT_VTRESULT); td->last_ins->data [0] = vt_res_size; WRITE32_INS (td->last_ins, 1, &vt_stack_used); @@ -5008,8 +5010,12 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, /* the vtable of the field might not be initialized at this point */ mono_class_vtable_checked (domain, field_klass, error); goto_if_nok (error, exit); - - td->last_ins->data [1] = get_data_item_index (td, field_klass); + if (m_class_has_references (field_klass)) { + td->last_ins->data [1] = get_data_item_index (td, field_klass); + } else { + td->last_ins->opcode = MINT_STFLD_VT_NOREF; + td->last_ins->data [1] = mono_class_value_size (field_klass, NULL); + } } } }