From db7a7deb19afea76b6e23c526de70e3a2797ad52 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Thu, 11 Aug 2022 19:28:46 +0300 Subject: [PATCH 1/4] [mono][interp] Add suport for nint as index into array We previously assumend index is i32, but it can be either i32 or native int. In order to avoid code bloat by adding native int versions to all opcodes (LDELEM, STELEM and LDELEMA) for negligible perf gain, just add one additional data to these instructions which indicates whether to fetch the index var as a i32 or native int. On interp we don't zero extend by default to 8 byte when storing into locals (we should probably do this at some point), so we need to special handle nint argument. --- src/mono/mono/mini/interp/interp.c | 67 +++++++++++++++++---------- src/mono/mono/mini/interp/mintops.def | 54 ++++++++++----------- src/mono/mono/mini/interp/transform.c | 21 +++++++-- 3 files changed, 85 insertions(+), 57 deletions(-) diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index b89f8a7a181c7..cc11b827e9202 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -1223,24 +1223,27 @@ ves_array_create (MonoClass *klass, int param_count, stackval *values, MonoError return (MonoObject*) mono_array_new_full_checked (klass, lengths, lower_bounds, error); } -static gint32 -ves_array_calculate_index (MonoArray *ao, stackval *sp, gboolean safe) +static gsize +ves_array_calculate_index (MonoArray *ao, stackval *sp, gboolean native_int) { MonoClass *ac = ((MonoObject *) ao)->vtable->klass; - guint32 pos = 0; + gsize pos = 0; if (ao->bounds) { for (gint32 i = 0; i < m_class_get_rank (ac); i++) { gint32 idx = sp [i].data.i; gint32 lower = ao->bounds [i].lower_bound; guint32 len = ao->bounds [i].length; - if (safe && (idx < lower || (guint32)(idx - lower) >= len)) + if (idx < lower || (guint32)(idx - lower) >= len) return -1; pos = (pos * len) + (guint32)(idx - lower); } } else { - pos = sp [0].data.i; - if (safe && pos >= ao->max_length) + if (native_int) + pos = sp [0].data.nati; + else + pos = (gsize)sp [0].data.i; + if (pos >= ao->max_length) return -1; } return pos; @@ -1268,17 +1271,17 @@ ves_array_get (InterpFrame *frame, stackval *sp, stackval *retval, MonoMethodSig } static MonoException* -ves_array_element_address (InterpFrame *frame, MonoClass *required_type, MonoArray *ao, gpointer *ret, stackval *sp, gboolean needs_typecheck) +ves_array_element_address (InterpFrame *frame, MonoClass *required_type, MonoArray *ao, gpointer *ret, stackval *sp, gboolean native_int) { MonoClass *ac = ((MonoObject *) ao)->vtable->klass; g_assert (m_class_get_rank (ac) >= 1); - gint32 pos = ves_array_calculate_index (ao, sp, TRUE); + gsize pos = ves_array_calculate_index (ao, sp, native_int); if (pos == -1) return mono_get_exception_index_out_of_range (); - if (needs_typecheck && !mono_class_is_assignable_from_internal (m_class_get_element_class (mono_object_class ((MonoObject *) ao)), required_type)) + if (!mono_class_is_assignable_from_internal (m_class_get_element_class (mono_object_class ((MonoObject *) ao)), required_type)) return mono_get_exception_array_type_mismatch (); gint32 esize = mono_array_element_size (ac); *ret = mono_array_addr_with_size_fast (ao, esize, pos); @@ -3529,6 +3532,19 @@ static long total_executed_opcodes; #define LOCAL_VAR(offset,type) (*(type*)(locals + (offset))) +static MONO_ALWAYS_INLINE gsize +get_array_offset (unsigned char *locals, guint16 var_offset, gboolean native_int) +{ +#if SIZEOF_VOID_P == 8 + if (native_int) + return LOCAL_VAR (var_offset, gsize); + else + return (gsize)LOCAL_VAR (var_offset, guint32); +#else + return LOCAL_VAR (var_offset, gsize); +#endif +} + /* * If CLAUSE_ARGS is non-null, start executing from it. * The ERROR argument is used to avoid declaring an error object for every interp frame, its not used @@ -6102,12 +6118,12 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; /* No bounds, one direction */ MonoArray *ao = LOCAL_VAR (ip [2], MonoArray*); NULL_CHECK (ao); - guint32 index = LOCAL_VAR (ip [3], guint32); + gsize index = get_array_offset (locals, ip [3], ip [5]); if (index >= ao->max_length) THROW_EX (interp_get_exception_index_out_of_range (frame, ip), ip); guint16 size = ip [4]; LOCAL_VAR (ip [1], gpointer) = mono_array_addr_with_size_fast (ao, size, index); - ip += 5; + ip += 6; MINT_IN_BREAK; } MINT_IN_CASE(MINT_LDELEMA) { @@ -6119,7 +6135,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; NULL_CHECK (ao); g_assert (ao->bounds); - guint32 pos = 0; + gsize pos = 0; for (int i = 0; i < rank; i++) { gint32 idx = sp [i + 1].data.i; gint32 lower = ao->bounds [i].lower_bound; @@ -6140,22 +6156,23 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MonoObject *o = (MonoObject*) sp [0].data.o; NULL_CHECK (o); + gboolean native_int = ip [4]; MonoClass *klass = (MonoClass*)frame->imethod->data_items [ip [3]]; - MonoException *address_ex = ves_array_element_address (frame, klass, (MonoArray *) o, (gpointer*)(locals + ip [1]), sp + 1, TRUE); + MonoException *address_ex = ves_array_element_address (frame, klass, (MonoArray *) o, (gpointer*)(locals + ip [1]), sp + 1, native_int); if (address_ex) THROW_EX (address_ex, ip); - ip += 4; + ip += 5; MINT_IN_BREAK; } #define LDELEM(datatype,elemtype) do { \ MonoArray *o = LOCAL_VAR (ip [2], MonoArray*); \ NULL_CHECK (o); \ - guint32 aindex = LOCAL_VAR (ip [3], guint32); \ + gsize aindex = get_array_offset (locals, ip [3], ip [4]); \ if (aindex >= mono_array_length_internal (o)) \ THROW_EX (interp_get_exception_index_out_of_range (frame, ip), ip); \ LOCAL_VAR (ip [1], datatype) = mono_array_get_fast (o, elemtype, aindex); \ - ip += 4; \ + ip += 5; \ } while (0) MINT_IN_CASE(MINT_LDELEM_I1) LDELEM(gint32, gint8); MINT_IN_BREAK; MINT_IN_CASE(MINT_LDELEM_U1) LDELEM(gint32, guint8); MINT_IN_BREAK; @@ -6171,7 +6188,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_LDELEM_VT) { MonoArray *o = LOCAL_VAR (ip [2], MonoArray*); NULL_CHECK (o); - mono_u aindex = LOCAL_VAR (ip [3], gint32); + gsize aindex = get_array_offset (locals, ip [3], ip [5]); if (aindex >= mono_array_length_internal (o)) THROW_EX (interp_get_exception_index_out_of_range (frame, ip), ip); @@ -6179,23 +6196,23 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; char *src_addr = mono_array_addr_with_size_fast ((MonoArray *) o, size, aindex); memcpy (locals + ip [1], src_addr, size); - ip += 5; + ip += 6; MINT_IN_BREAK; } #define STELEM_PROLOG(o, aindex) do { \ o = LOCAL_VAR (ip [1], MonoArray*); \ NULL_CHECK (o); \ - aindex = LOCAL_VAR (ip [2], gint32); \ + aindex = get_array_offset (locals, ip [2], ip [4]); \ if (aindex >= mono_array_length_internal (o)) \ THROW_EX (interp_get_exception_index_out_of_range (frame, ip), ip); \ } while (0) #define STELEM(datatype, elemtype) do { \ MonoArray *o; \ - guint32 aindex; \ + gsize aindex; \ STELEM_PROLOG(o, aindex); \ mono_array_set_fast (o, elemtype, aindex, LOCAL_VAR (ip [3], datatype)); \ - ip += 4; \ + ip += 5; \ } while (0) MINT_IN_CASE(MINT_STELEM_I1) STELEM(gint32, gint8); MINT_IN_BREAK; MINT_IN_CASE(MINT_STELEM_U1) STELEM(gint32, guint8); MINT_IN_BREAK; @@ -6208,7 +6225,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_STELEM_R8) STELEM(double, double); MINT_IN_BREAK; MINT_IN_CASE(MINT_STELEM_REF) { MonoArray *o; - guint32 aindex; + gsize aindex; STELEM_PROLOG(o, aindex); MonoObject *ref = LOCAL_VAR (ip [3], MonoObject*); @@ -6219,14 +6236,14 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; THROW_EX (interp_get_exception_array_type_mismatch (frame, ip), ip); } mono_array_setref_fast ((MonoArray *) o, aindex, ref); - ip += 4; + ip += 5; MINT_IN_BREAK; } MINT_IN_CASE(MINT_STELEM_VT) { MonoArray *o = LOCAL_VAR (ip [1], MonoArray*); NULL_CHECK (o); - guint32 aindex = LOCAL_VAR (ip [2], guint32); + gsize aindex = get_array_offset (locals, ip [2], ip [6]); if (aindex >= mono_array_length_internal (o)) THROW_EX (interp_get_exception_index_out_of_range (frame, ip), ip); @@ -6234,7 +6251,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; char *dst_addr = mono_array_addr_with_size_fast ((MonoArray *) o, size, aindex); MonoClass *klass_vt = (MonoClass*)frame->imethod->data_items [ip [4]]; mono_value_copy_internal (dst_addr, locals + ip [3], klass_vt); - ip += 6; + ip += 7; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_I4_U4) { diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index b237b7a32d078..dd4ef7a6ce19a 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -375,34 +375,34 @@ OPDEF(MINT_LOCALLOC, "localloc", 3, 1, 1, MintOpNoArgs) OPDEF(MINT_INITLOCAL, "initlocal", 3, 1, 0, MintOpShortInt) OPDEF(MINT_INITLOCALS, "initlocals", 3, 0, 0, MintOpTwoShorts) -OPDEF(MINT_LDELEM_I, "ldelem.i", 4, 1, 2, MintOpNoArgs) -OPDEF(MINT_LDELEM_I1, "ldelem.i1", 4, 1, 2, MintOpNoArgs) -OPDEF(MINT_LDELEM_U1, "ldelem.u1", 4, 1, 2, MintOpNoArgs) -OPDEF(MINT_LDELEM_I2, "ldelem.i2", 4, 1, 2, MintOpNoArgs) -OPDEF(MINT_LDELEM_U2, "ldelem.u2", 4, 1, 2, MintOpNoArgs) -OPDEF(MINT_LDELEM_I4, "ldelem.i4", 4, 1, 2, MintOpNoArgs) -OPDEF(MINT_LDELEM_U4, "ldelem.u4", 4, 1, 2, MintOpNoArgs) -OPDEF(MINT_LDELEM_I8, "ldelem.i8", 4, 1, 2, MintOpNoArgs) -OPDEF(MINT_LDELEM_R4, "ldelem.r4", 4, 1, 2, MintOpNoArgs) -OPDEF(MINT_LDELEM_R8, "ldelem.r8", 4, 1, 2, MintOpNoArgs) -OPDEF(MINT_LDELEM_REF, "ldelem.ref", 4, 1, 2, MintOpNoArgs) -OPDEF(MINT_LDELEM_VT, "ldelem.vt", 5, 1, 2, MintOpShortInt) - -OPDEF(MINT_LDELEMA1, "ldelema1", 5, 1, 2, MintOpShortInt) +OPDEF(MINT_LDELEM_I, "ldelem.i", 5, 1, 2, MintOpNoArgs) +OPDEF(MINT_LDELEM_I1, "ldelem.i1", 5, 1, 2, MintOpNoArgs) +OPDEF(MINT_LDELEM_U1, "ldelem.u1", 5, 1, 2, MintOpNoArgs) +OPDEF(MINT_LDELEM_I2, "ldelem.i2", 5, 1, 2, MintOpNoArgs) +OPDEF(MINT_LDELEM_U2, "ldelem.u2", 5, 1, 2, MintOpNoArgs) +OPDEF(MINT_LDELEM_I4, "ldelem.i4", 5, 1, 2, MintOpNoArgs) +OPDEF(MINT_LDELEM_U4, "ldelem.u4", 5, 1, 2, MintOpNoArgs) +OPDEF(MINT_LDELEM_I8, "ldelem.i8", 5, 1, 2, MintOpNoArgs) +OPDEF(MINT_LDELEM_R4, "ldelem.r4", 5, 1, 2, MintOpNoArgs) +OPDEF(MINT_LDELEM_R8, "ldelem.r8", 5, 1, 2, MintOpNoArgs) +OPDEF(MINT_LDELEM_REF, "ldelem.ref", 5, 1, 2, MintOpNoArgs) +OPDEF(MINT_LDELEM_VT, "ldelem.vt", 6, 1, 2, MintOpShortInt) + +OPDEF(MINT_LDELEMA1, "ldelema1", 6, 1, 2, MintOpShortInt) OPDEF(MINT_LDELEMA, "ldelema", 5, 1, 1, MintOpTwoShorts) -OPDEF(MINT_LDELEMA_TC, "ldelema.tc", 4, 1, 1, MintOpTwoShorts) - -OPDEF(MINT_STELEM_I, "stelem.i", 4, 0, 3, MintOpNoArgs) -OPDEF(MINT_STELEM_I1, "stelem.i1", 4, 0, 3, MintOpNoArgs) -OPDEF(MINT_STELEM_U1, "stelem.u1", 4, 0, 3, MintOpNoArgs) -OPDEF(MINT_STELEM_I2, "stelem.i2", 4, 0, 3, MintOpNoArgs) -OPDEF(MINT_STELEM_U2, "stelem.u2", 4, 0, 3, MintOpNoArgs) -OPDEF(MINT_STELEM_I4, "stelem.i4", 4, 0, 3, MintOpNoArgs) -OPDEF(MINT_STELEM_I8, "stelem.i8", 4, 0, 3, MintOpNoArgs) -OPDEF(MINT_STELEM_R4, "stelem.r4", 4, 0, 3, MintOpNoArgs) -OPDEF(MINT_STELEM_R8, "stelem.r8", 4, 0, 3, MintOpNoArgs) -OPDEF(MINT_STELEM_REF, "stelem.ref", 4, 0, 3, MintOpNoArgs) -OPDEF(MINT_STELEM_VT, "stelem.vt", 6, 0, 3, MintOpTwoShorts) +OPDEF(MINT_LDELEMA_TC, "ldelema.tc", 5, 1, 1, MintOpTwoShorts) + +OPDEF(MINT_STELEM_I, "stelem.i", 5, 0, 3, MintOpNoArgs) +OPDEF(MINT_STELEM_I1, "stelem.i1", 5, 0, 3, MintOpNoArgs) +OPDEF(MINT_STELEM_U1, "stelem.u1", 5, 0, 3, MintOpNoArgs) +OPDEF(MINT_STELEM_I2, "stelem.i2", 5, 0, 3, MintOpNoArgs) +OPDEF(MINT_STELEM_U2, "stelem.u2", 5, 0, 3, MintOpNoArgs) +OPDEF(MINT_STELEM_I4, "stelem.i4", 5, 0, 3, MintOpNoArgs) +OPDEF(MINT_STELEM_I8, "stelem.i8", 5, 0, 3, MintOpNoArgs) +OPDEF(MINT_STELEM_R4, "stelem.r4", 5, 0, 3, MintOpNoArgs) +OPDEF(MINT_STELEM_R8, "stelem.r8", 5, 0, 3, MintOpNoArgs) +OPDEF(MINT_STELEM_REF, "stelem.ref", 5, 0, 3, MintOpNoArgs) +OPDEF(MINT_STELEM_VT, "stelem.vt", 7, 0, 3, MintOpTwoShorts) OPDEF(MINT_LDLEN, "ldlen", 3, 1, 1, MintOpNoArgs) OPDEF(MINT_LDLEN_SPAN, "ldlen.span", 4, 1, 1, MintOpShortInt) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index d76a5c121b789..8519fd983d1a7 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -4253,12 +4253,13 @@ static void handle_ldelem (TransformData *td, int op, int type) { CHECK_STACK (td, 2); - ENSURE_I4 (td, 1); + gboolean native_int = td->sp [-1].type != STACK_TYPE_I4; interp_add_ins (td, op); td->sp -= 2; interp_ins_set_sregs2 (td->last_ins, td->sp [0].local, td->sp [1].local); push_simple_type (td, type); interp_ins_set_dreg (td->last_ins, td->sp [-1].local); + td->last_ins->data [0] = native_int; ++td->ip; } @@ -4266,10 +4267,11 @@ static void handle_stelem (TransformData *td, int op) { CHECK_STACK (td, 3); - ENSURE_I4 (td, 2); + gboolean native_int = td->sp [-2].type != STACK_TYPE_I4; interp_add_ins (td, op); td->sp -= 3; interp_ins_set_sregs3 (td->last_ins, td->sp [0].local, td->sp [1].local, td->sp [2].local); + td->last_ins->data [0] = native_int; ++td->ip; } @@ -6308,7 +6310,6 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, case CEE_LDELEMA: { gint32 size; CHECK_STACK (td, 2); - ENSURE_I4 (td, 1); token = read32 (td->ip + 1); if (method->wrapper_type != MONO_WRAPPER_NONE) @@ -6318,6 +6319,8 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, CHECK_TYPELOAD (klass); + gboolean native_int = td->sp [-1].type != STACK_TYPE_I4; + if (!m_class_is_valuetype (klass) && method->wrapper_type == MONO_WRAPPER_NONE && !readonly) { /* * Check the class for failures before the type check, which can @@ -6334,6 +6337,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, push_simple_type (td, STACK_TYPE_MP); interp_ins_set_dreg (td->last_ins, td->sp [-1].local); td->last_ins->data [0] = get_data_item_index (td, klass); + td->last_ins->data [1] = native_int; td->last_ins->info.call_args = call_args; interp_ins_set_sreg (td->last_ins, MINT_CALL_ARGS_SREG); td->last_ins->flags |= INTERP_INST_FLAG_CALL; @@ -6346,6 +6350,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, mono_class_init_internal (klass); size = mono_class_array_element_size (klass); td->last_ins->data [0] = GINT32_TO_UINT16 (size); + td->last_ins->data [1] = native_int; } readonly = FALSE; @@ -6423,13 +6428,14 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, g_assert (size < G_MAXUINT16); CHECK_STACK (td, 2); - ENSURE_I4 (td, 1); + gboolean native_int = td->sp [-1].type != STACK_TYPE_I4; interp_add_ins (td, MINT_LDELEM_VT); td->sp -= 2; interp_ins_set_sregs2 (td->last_ins, td->sp [0].local, td->sp [1].local); push_type_vt (td, klass, size); interp_ins_set_dreg (td->last_ins, td->sp [-1].local); td->last_ins->data [0] = GINT_TO_UINT16 (size); + td->last_ins->data [1] = native_int; ++td->ip; break; } @@ -6504,9 +6510,14 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, int size = mono_class_value_size (klass, NULL); g_assert (size < G_MAXUINT16); - handle_stelem (td, MINT_STELEM_VT); + gboolean native_int = td->sp [-2].type != STACK_TYPE_I4; + interp_add_ins (td, MINT_STELEM_VT); + td->sp -= 3; + interp_ins_set_sregs3 (td->last_ins, td->sp [0].local, td->sp [1].local, td->sp [2].local); td->last_ins->data [0] = get_data_item_index (td, klass); td->last_ins->data [1] = GINT_TO_UINT16 (size); + td->last_ins->data [2] = native_int; + td->ip++; break; } default: { From 585810d0d277057fdbc8598f79ae56482d8bbf19 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Thu, 11 Aug 2022 19:35:55 +0300 Subject: [PATCH 2/4] [mono][interp] Remove dead code --- src/mono/mono/mini/interp/interp.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index cc11b827e9202..8c1045cce0560 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -1249,27 +1249,6 @@ ves_array_calculate_index (MonoArray *ao, stackval *sp, gboolean native_int) return pos; } -static MonoException* -ves_array_get (InterpFrame *frame, stackval *sp, stackval *retval, MonoMethodSignature *sig, gboolean safe) -{ - MonoObject *o = sp->data.o; - MonoArray *ao = (MonoArray *) o; - MonoClass *ac = o->vtable->klass; - - g_assert (m_class_get_rank (ac) >= 1); - - gint32 pos = ves_array_calculate_index (ao, sp + 1, safe); - if (pos == -1) - return mono_get_exception_index_out_of_range (); - - gint32 esize = mono_array_element_size (ac); - gconstpointer ea = mono_array_addr_with_size_fast (ao, esize, pos); - - MonoType *mt = sig->ret; - stackval_from_data (mt, retval, ea, FALSE); - return NULL; -} - static MonoException* ves_array_element_address (InterpFrame *frame, MonoClass *required_type, MonoArray *ao, gpointer *ret, stackval *sp, gboolean native_int) { From 6653d10a70ecc279aab9063e74a2b679ceaecbf5 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Thu, 11 Aug 2022 19:53:34 +0300 Subject: [PATCH 3/4] [mono][jit] Don't truncate the high bits when ldelema index is nint Remove MONO_ARCH_EMIT_BOUNDS_CHECK on amd64 since it was doing a I4 comparison, while the index reg is i8. Use MONO_EMIT_DEFAULT_BOUNDS_CHECK instead also on amd64. --- src/mono/mono/mini/method-to-ir.c | 11 ++++++++++- src/mono/mono/mini/mini-amd64.h | 10 ---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index 12fa5bbf1a450..2ca69f18e890b 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -4216,7 +4216,16 @@ mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, Mono mult_reg = alloc_preg (cfg); array_reg = arr->dreg; - realidx2_reg = index2_reg = mini_emit_sext_index_reg (cfg, index); + if (TARGET_SIZEOF_VOID_P == 8) { + // If index is not I4 don't sign extend otherwise we lose high word + if (index->type == STACK_I4) + index2_reg = mini_emit_sext_index_reg (cfg, index); + else + index2_reg = index->dreg; + } else { + index2_reg = index->dreg; + } + realidx2_reg = index2_reg; if (bounded) { bounds_reg = alloc_preg (cfg); diff --git a/src/mono/mono/mini/mini-amd64.h b/src/mono/mono/mini/mini-amd64.h index 80c570e58f5be..2c775c1585545 100644 --- a/src/mono/mono/mini/mini-amd64.h +++ b/src/mono/mono/mini/mini-amd64.h @@ -480,16 +480,6 @@ typedef struct { /* Used for optimization, not complete */ #define MONO_ARCH_IS_OP_MEMBASE(opcode) ((opcode) == OP_X86_PUSH_MEMBASE) -#define MONO_ARCH_EMIT_BOUNDS_CHECK(cfg, array_reg, offset, index_reg, ex_name) do { \ - MonoInst *inst; \ - MONO_INST_NEW ((cfg), inst, OP_AMD64_ICOMPARE_MEMBASE_REG); \ - inst->inst_basereg = array_reg; \ - inst->inst_offset = offset; \ - inst->sreg2 = index_reg; \ - MONO_ADD_INS ((cfg)->cbb, inst); \ - MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, ex_name); \ - } while (0) - // Does the ABI have a volatile non-parameter register, so tailcall // can pass context to generics or interfaces? #define MONO_ARCH_HAVE_VOLATILE_NON_PARAM_REGISTER 1 From a99b578dd4acf1b9e4fa8e6ff590ed5b022d9486 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Thu, 11 Aug 2022 19:56:46 +0300 Subject: [PATCH 4/4] Enable test --- src/tests/issues.targets | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/tests/issues.targets b/src/tests/issues.targets index c709d58ac4968..37c8ab39056dc 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -1426,9 +1426,6 @@ https://github.com/dotnet/runtime/issues/74223 - - https://github.com/dotnet/runtime/issues/71656 - https://github.com/dotnet/runtime/issues/56887