Skip to content

Commit

Permalink
[mono][interp] Small improvements to get span item (#77331)
Browse files Browse the repository at this point in the history
* [mono][interp] Improve GETITEM_SPAN intrinsic

Field offsets are known at compile time, they don't need to be included in the code stream.

* [mono][interp] Add version of getitemspan that doesn't use indirection

* [mono][interp] Add general MonoSpanOfVoid struct and use it in interp opcodes
  • Loading branch information
BrzVlad authored Oct 23, 2022
1 parent 4e85471 commit 72eb39c
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 11 deletions.
1 change: 1 addition & 0 deletions src/mono/mono/metadata/object-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ struct _MonoArray {
} name;

MONO_DEFINE_SPAN_OF_T (MonoSpanOfObjects, MonoObject*)
MONO_DEFINE_SPAN_OF_T (MonoSpanOfVoid, void)

#define MONO_SIZEOF_MONO_ARRAY (MONO_STRUCT_OFFSET_CONSTANT (MonoArray, vector))

Expand Down
26 changes: 18 additions & 8 deletions src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -6061,23 +6061,33 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_GETITEM_SPAN) {
guint8 *span = LOCAL_VAR (ip [2], guint8*);
MonoSpanOfVoid *span = LOCAL_VAR (ip [2], MonoSpanOfVoid*);
int index = LOCAL_VAR (ip [3], int);
NULL_CHECK (span);

gsize offset_length = (gsize)(gint16)ip [5];

const gint32 length = *(gint32 *) (span + offset_length);
gint32 length = span->_length;
if (index < 0 || index >= length)
THROW_EX (interp_get_exception_index_out_of_range (frame, ip), ip);

gsize element_size = (gsize)(gint16)ip [4];
gsize offset_pointer = (gsize)(gint16)ip [6];
LOCAL_VAR (ip [1], gpointer) = (guint8*)span->_reference + index * element_size;

const gpointer pointer = *(gpointer *)(span + offset_pointer);
LOCAL_VAR (ip [1], gpointer) = (guint8 *) pointer + index * element_size;
ip += 5;
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_GETITEM_LOCALSPAN) {
// Same as getitem span but we know the offset of the span structure on the stack
MonoSpanOfVoid *span = (MonoSpanOfVoid*)(locals + ip [2]);
int index = LOCAL_VAR (ip [3], int);

ip += 7;
gint32 length = span->_length;
if (index < 0 || index >= length)
THROW_EX (interp_get_exception_index_out_of_range (frame, ip), ip);

gsize element_size = (gsize)(gint16)ip [4];
LOCAL_VAR (ip [1], gpointer) = (guint8*)span->_reference + index * element_size;

ip += 5;
MINT_IN_BREAK;
}
MINT_IN_CASE(MINT_STRLEN) {
Expand Down
3 changes: 2 additions & 1 deletion src/mono/mono/mini/interp/mintops.def
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,8 @@ OPDEF(MINT_STELEM_VT, "stelem.vt", 6, 0, 3, MintOpTwoShorts)

OPDEF(MINT_LDLEN, "ldlen", 3, 1, 1, MintOpNoArgs)

OPDEF(MINT_GETITEM_SPAN, "getitem.span", 7, 1, 2, MintOpTwoShorts)
OPDEF(MINT_GETITEM_SPAN, "getitem.span", 5, 1, 2, MintOpTwoShorts)
OPDEF(MINT_GETITEM_LOCALSPAN, "getitem.localspan", 5, 1, 2, MintOpTwoShorts)

/* binops */
OPDEF(MINT_ADD_I4, "add.i4", 4, 1, 2, MintOpNoArgs)
Expand Down
15 changes: 13 additions & 2 deletions src/mono/mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -2134,16 +2134,16 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas
MonoClassField *length_field = mono_class_get_field_from_name_full (target_method->klass, "_length", NULL);
g_assert (length_field);
int offset_length = m_field_get_offset (length_field) - sizeof (MonoObject);
g_assert (offset_length == TARGET_SIZEOF_VOID_P);

MonoClassField *ptr_field = mono_class_get_field_from_name_full (target_method->klass, "_reference", NULL);
g_assert (ptr_field);
int offset_pointer = m_field_get_offset (ptr_field) - sizeof (MonoObject);
g_assert (offset_pointer == 0);

int size = mono_class_array_element_size (param_class);
interp_add_ins (td, MINT_GETITEM_SPAN);
td->last_ins->data [0] = GINT_TO_UINT16 (size);
td->last_ins->data [1] = GINT_TO_UINT16 (offset_length);
td->last_ins->data [2] = GINT_TO_UINT16 (offset_pointer);

td->sp -= 2;
interp_ins_set_sregs2 (td->last_ins, td->sp [0].local, td->sp [1].local);
Expand Down Expand Up @@ -8996,6 +8996,17 @@ interp_cprop (TransformData *td)
}
needs_retry = TRUE;
}
} else if (opcode == MINT_GETITEM_SPAN) {
InterpInst *ldloca = local_defs [sregs [0]].ins;
if (ldloca != NULL && ldloca->opcode == MINT_LDLOCA_S) {
int local = ldloca->sregs [0];
// Allow ldloca instruction to be killed
local_ref_count [sregs [0]]--;
// Instead of loading from the indirect pointer pass directly the vt var
ins->opcode = MINT_GETITEM_LOCALSPAN;
sregs [0] = local;
needs_retry = TRUE;
}
}
ins_index++;
}
Expand Down

0 comments on commit 72eb39c

Please sign in to comment.