From 91b9ff3e535c6d635a07a2d84696a1e333c38800 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Sat, 27 Jul 2019 17:37:00 +0300 Subject: [PATCH] [interp] Optimize ldelema (#15846) Makes the opcode 2-3x time faster --- mono/mini/interp/interp.c | 16 ++++++++++++++++ mono/mini/interp/mintops.def | 1 + mono/mini/interp/transform.c | 15 ++++++++++----- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/mono/mini/interp/interp.c b/mono/mini/interp/interp.c index 12d37b89da1..c9a1a2ebecc 100644 --- a/mono/mini/interp/interp.c +++ b/mono/mini/interp/interp.c @@ -5275,6 +5275,22 @@ interp_exec_method_full (InterpFrame *frame, ThreadContext *context, FrameClause sp [-1].data.i = m_class_get_rank (mono_object_class (sp [-1].data.p)); ip++; MINT_IN_BREAK; + MINT_IN_CASE(MINT_LDELEMA_FAST) { + /* No bounds, one direction */ + gint32 size = READ32 (ip + 1); + gint32 index = sp [-1].data.i; + + MonoArray *ao = (MonoArray*)sp [-2].data.o; + if (!ao) + THROW_EX (mono_get_exception_null_reference (), ip); + if (index >= ao->max_length) + THROW_EX (mono_get_exception_index_out_of_range (), ip); + sp [-2].data.p = mono_array_addr_with_size_fast (ao, size, index); + ip += 3; + sp --; + + MINT_IN_BREAK; + } MINT_IN_CASE(MINT_LDELEMA) MINT_IN_CASE(MINT_LDELEMA_TC) { gboolean needs_typecheck = *ip == MINT_LDELEMA_TC; diff --git a/mono/mini/interp/mintops.def b/mono/mini/interp/mintops.def index 092c6101ac2..0b2e887b03c 100644 --- a/mono/mini/interp/mintops.def +++ b/mono/mini/interp/mintops.def @@ -394,6 +394,7 @@ OPDEF(MINT_LDELEM_VT, "ldelem.vt", 3, MintOpInt) OPDEF(MINT_LDELEMA, "ldelema", 3, MintOpTwoShorts) OPDEF(MINT_LDELEMA_TC, "ldelema.tc", 3, MintOpTwoShorts) +OPDEF(MINT_LDELEMA_FAST, "ldelema.fast", 3, MintOpInt) OPDEF(MINT_STELEM_I, "stelem.i", 1, MintOpNoArgs) OPDEF(MINT_STELEM_I1, "stelem.i1", 1, MintOpNoArgs) diff --git a/mono/mini/interp/transform.c b/mono/mini/interp/transform.c index ad5695ca598..87ad5da4241 100644 --- a/mono/mini/interp/transform.c +++ b/mono/mini/interp/transform.c @@ -4749,7 +4749,8 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, SET_SIMPLE_TYPE (td->sp - 1, STACK_TYPE_I4); #endif break; - case CEE_LDELEMA: + case CEE_LDELEMA: { + gint32 size; CHECK_STACK (td, 2); ENSURE_I4 (td, 1); token = read32 (td->ip + 1); @@ -4769,18 +4770,22 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, mono_class_setup_vtable (klass); CHECK_TYPELOAD (klass); interp_add_ins (td, MINT_LDELEMA_TC); + td->last_ins->data [0] = get_data_item_index (td, klass); + td->last_ins->data [1] = 2; } else { - interp_add_ins (td, MINT_LDELEMA); + interp_add_ins (td, MINT_LDELEMA_FAST); + mono_class_init_internal (klass); + size = mono_class_array_element_size (klass); + WRITE32_INS (td->last_ins, 0, &size); } - td->last_ins->data [0] = get_data_item_index (td, klass); - /* according to spec, ldelema bytecode is only used for 1-dim arrays */ - td->last_ins->data [1] = 2; + readonly = FALSE; td->ip += 5; --td->sp; SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_MP); break; + } case CEE_LDELEM_I1: CHECK_STACK (td, 2); ENSURE_I4 (td, 1); -- 2.11.4.GIT