Skip to content

Commit 8025156

Browse files
authored
[mono] Add unchecked version of stelem_ref interpreter opcode (#99829)
* Introduce mint_stelem_ref_unchecked * Inline most of stelem_ref_unchecked in jiterpreter traces * Add more complete type check for stelem_ref_unchecked * Correctness fix and simplification for stelem_ref_unchecked
1 parent 4219e45 commit 8025156

File tree

5 files changed

+49
-4
lines changed

5 files changed

+49
-4
lines changed

src/mono/browser/runtime/jiterpreter-trace-generator.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3347,13 +3347,21 @@ function emit_arrayop (builder: WasmBuilder, frame: NativePointer, ip: MintOpcod
33473347
append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load);
33483348
// value
33493349
append_ldloc(builder, getArgU16(ip, 3), WasmOpcode.i32_load);
3350-
builder.callImport("stelem_ref");
3350+
builder.callImport("stelemr_tc");
33513351
builder.appendU8(WasmOpcode.br_if);
33523352
builder.appendULeb(0);
33533353
append_bailout(builder, ip, BailoutReason.ArrayStoreFailed);
33543354
builder.endBlock();
33553355
return true;
33563356
}
3357+
case MintOpcode.MINT_STELEM_REF_UNCHECKED: {
3358+
// dest
3359+
append_getelema1(builder, ip, objectOffset, indexOffset, 4);
3360+
// &value (src)
3361+
append_ldloca(builder, valueOffset, 0);
3362+
builder.callImport("copy_ptr");
3363+
return true;
3364+
}
33573365
case MintOpcode.MINT_LDELEM_REF:
33583366
elementSize = 4;
33593367
elementGetter = WasmOpcode.i32_load;

src/mono/browser/runtime/jiterpreter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ function getTraceImports () {
285285
importDef("stfld_o", getRawCwrap("mono_jiterp_set_object_field")),
286286
importDef("cmpxchg_i32", getRawCwrap("mono_jiterp_cas_i32")),
287287
importDef("cmpxchg_i64", getRawCwrap("mono_jiterp_cas_i64")),
288-
importDef("stelem_ref", getRawCwrap("mono_jiterp_stelem_ref")),
288+
["stelemr_tc", "stelemr", getRawCwrap("mono_jiterp_stelem_ref")],
289289
importDef("fma", getRawCwrap("fma")),
290290
importDef("fmaf", getRawCwrap("fmaf")),
291291
];
@@ -649,7 +649,7 @@ function initialize_builder (builder: WasmBuilder) {
649649
WasmValtype.void, true
650650
);
651651
builder.defineType(
652-
"stelem_ref",
652+
"stelemr",
653653
{
654654
"o": WasmValtype.i32,
655655
"aindex": WasmValtype.i32,

src/mono/mono/mini/interp/interp.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6660,6 +6660,14 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
66606660
MINT_IN_CASE(MINT_STELEM_I8) STELEM(gint64, gint64); MINT_IN_BREAK;
66616661
MINT_IN_CASE(MINT_STELEM_R4) STELEM(float, float); MINT_IN_BREAK;
66626662
MINT_IN_CASE(MINT_STELEM_R8) STELEM(double, double); MINT_IN_BREAK;
6663+
MINT_IN_CASE(MINT_STELEM_REF_UNCHECKED) {
6664+
MonoArray *o;
6665+
guint32 aindex;
6666+
STELEM_PROLOG(o, aindex);
6667+
mono_array_setref_fast ((MonoArray *) o, aindex, LOCAL_VAR (ip [3], MonoObject*));
6668+
ip += 4;
6669+
MINT_IN_BREAK;
6670+
}
66636671
MINT_IN_CASE(MINT_STELEM_REF) {
66646672
MonoArray *o;
66656673
guint32 aindex;
@@ -6676,7 +6684,6 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
66766684
ip += 4;
66776685
MINT_IN_BREAK;
66786686
}
6679-
66806687
MINT_IN_CASE(MINT_STELEM_VT) {
66816688
MonoArray *o = LOCAL_VAR (ip [1], MonoArray*);
66826689
NULL_CHECK (o);

src/mono/mono/mini/interp/mintops.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ OPDEF(MINT_STELEM_R8, "stelem.r8", 4, 0, 3, MintOpNoArgs)
413413
OPDEF(MINT_STELEM_REF, "stelem.ref", 4, 0, 3, MintOpNoArgs)
414414
OPDEF(MINT_STELEM_VT, "stelem.vt", 6, 0, 3, MintOpTwoShorts)
415415
OPDEF(MINT_STELEM_VT_NOREF, "stelem.vt.noref", 6, 0, 3, MintOpTwoShorts)
416+
OPDEF(MINT_STELEM_REF_UNCHECKED, "stelem.ref.unchecked", 4, 0, 3, MintOpNoArgs)
416417

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

src/mono/mono/mini/interp/transform.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4945,6 +4945,35 @@ handle_stelem (TransformData *td, int op)
49454945
interp_add_ins (td, op);
49464946
td->sp -= 3;
49474947
interp_ins_set_sregs3 (td->last_ins, td->sp [0].var, td->sp [1].var, td->sp [2].var);
4948+
4949+
if (op == MINT_STELEM_REF) {
4950+
InterpVar *array_var = &td->vars [td->last_ins->sregs [0]],
4951+
*value_var = &td->vars [td->last_ins->sregs [2]];
4952+
MonoClass *array_var_klass = mono_class_from_mono_type_internal (array_var->type),
4953+
*value_var_klass = mono_class_from_mono_type_internal (value_var->type);
4954+
4955+
if (m_class_is_array (array_var_klass)) {
4956+
MonoClass *array_element_klass = m_class_get_element_class (array_var_klass);
4957+
// If lhs is T[] and rhs is T and T is sealed, we can skip the runtime typecheck
4958+
if (
4959+
(array_element_klass == value_var_klass) &&
4960+
m_class_is_sealed(value_var_klass) &&
4961+
// HACK: Arrays are sealed, but it's possible to downcast string[][] to object[][],
4962+
// so we don't want to treat elements of array types as actually sealed.
4963+
// Our lhs of type object[][] might actually be of a different reference type.
4964+
!m_class_is_array(value_var_klass)
4965+
){
4966+
if (td->verbose_level > 2)
4967+
g_printf (
4968+
"MINT_STELEM_REF_UNCHECKED for %s in %s::%s\n",
4969+
m_class_get_name (value_var_klass),
4970+
m_class_get_name (td->method->klass), td->method->name
4971+
);
4972+
td->last_ins->opcode = MINT_STELEM_REF_UNCHECKED;
4973+
}
4974+
}
4975+
}
4976+
49484977
++td->ip;
49494978
}
49504979

0 commit comments

Comments
 (0)