diff --git a/src/mono/browser/runtime/jiterpreter-trace-generator.ts b/src/mono/browser/runtime/jiterpreter-trace-generator.ts index f8ac833956ff69..9b3002eae107ab 100644 --- a/src/mono/browser/runtime/jiterpreter-trace-generator.ts +++ b/src/mono/browser/runtime/jiterpreter-trace-generator.ts @@ -378,7 +378,20 @@ export function generateWasmBody( builder.callImport("localloc"); break; } - case MintOpcode.MINT_INITOBJ: { + case MintOpcode.MINT_ZEROBLK: { + // dest + append_ldloc(builder, getArgU16(ip, 1), WasmOpcode.i32_load); + // value + builder.i32_const(0); + // count + append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load); + // memset + builder.appendU8(WasmOpcode.PREFIX_sat); + builder.appendU8(11); + builder.appendU8(0); + break; + } + case MintOpcode.MINT_ZEROBLK_IMM: { append_ldloc(builder, getArgU16(ip, 1), WasmOpcode.i32_load); append_memset_dest(builder, 0, getArgU16(ip, 2)); break; diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index c16afc494011fd..070278d2cd0e84 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -7618,7 +7618,11 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; /* top of stack is result of filter */ frame->retval->data.i = LOCAL_VAR (ip [1], gint32); goto exit_clause; - MINT_IN_CASE(MINT_INITOBJ) + MINT_IN_CASE(MINT_ZEROBLK) + memset (LOCAL_VAR (ip [1], gpointer), 0, LOCAL_VAR (ip [2], gsize)); + ip += 3; + MINT_IN_BREAK; + MINT_IN_CASE(MINT_ZEROBLK_IMM) memset (LOCAL_VAR (ip [1], gpointer), 0, ip [2]); ip += 3; MINT_IN_BREAK; diff --git a/src/mono/mono/mini/interp/jiterpreter-opcode-values.h b/src/mono/mono/mini/interp/jiterpreter-opcode-values.h index bf9965dc148a5f..fb677b438d3871 100644 --- a/src/mono/mono/mini/interp/jiterpreter-opcode-values.h +++ b/src/mono/mono/mini/interp/jiterpreter-opcode-values.h @@ -132,7 +132,8 @@ OP(MINT_INTRINS_MEMORYMARSHAL_GETARRAYDATAREF, HIGH) OP(MINT_INITLOCAL, MASSIVE) OP(MINT_INITLOCALS, MASSIVE) OP(MINT_LOCALLOC, NORMAL) -OP(MINT_INITOBJ, MASSIVE) +OP(MINT_ZEROBLK, MASSIVE) +OP(MINT_ZEROBLK_IMM, HIGH) OP(MINT_INTRINS_RUNTIMEHELPERS_OBJECT_HAS_COMPONENT_SIZE, HIGH) OP(MINT_INTRINS_ENUM_HASFLAG, HIGH) OP(MINT_INTRINS_ORDINAL_IGNORE_CASE_ASCII, HIGH) diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index afd4bf10dea60d..87108ca73bff38 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -363,7 +363,8 @@ OPDEF(MINT_NEWOBJ_STRING, "newobj_string", 4, 1, 1, MintOpMethodToken) OPDEF(MINT_NEWOBJ, "newobj", 5, 1, 1, MintOpMethodToken) OPDEF(MINT_NEWOBJ_INLINED, "newobj_inlined", 3, 1, 0, MintOpVTableToken) OPDEF(MINT_NEWOBJ_VT, "newobj_vt", 5, 1, 1, MintOpMethodToken) -OPDEF(MINT_INITOBJ, "initobj", 3, 0, 1, MintOpShortInt) +OPDEF(MINT_ZEROBLK, "zeroblk", 3, 0, 2, MintOpNoArgs) +OPDEF(MINT_ZEROBLK_IMM, "zeroblk_imm", 3, 0, 1, MintOpShortInt) OPDEF(MINT_CASTCLASS, "castclass", 4, 1, 1, MintOpClassToken) OPDEF(MINT_ISINST, "isinst", 4, 1, 1, MintOpClassToken) OPDEF(MINT_CASTCLASS_INTERFACE, "castclass.interface", 4, 1, 1, MintOpClassToken) diff --git a/src/mono/mono/mini/interp/transform-opt.c b/src/mono/mono/mini/interp/transform-opt.c index 41473cabb0aabf..1b5e2b7a026b8b 100644 --- a/src/mono/mono/mini/interp/transform-opt.c +++ b/src/mono/mono/mini/interp/transform-opt.c @@ -3041,12 +3041,12 @@ interp_cprop (TransformData *td) interp_dump_ins (ins, td->data_items); } } - } else if (opcode == MINT_INITOBJ) { + } else if (opcode == MINT_ZEROBLK_IMM) { InterpInst *ldloca = get_var_value_def (td, sregs [0]); if (ldloca != NULL && ldloca->opcode == MINT_LDLOCA_S) { int size = ins->data [0]; int local = ldloca->sregs [0]; - // Replace LDLOCA + INITOBJ with or LDC + // Replace LDLOCA + ZEROBLK_IMM with or LDC if (size <= 4) ins->opcode = MINT_LDC_I4_0; else if (size <= 8) @@ -3057,7 +3057,7 @@ interp_cprop (TransformData *td) ins->dreg = local; if (td->verbose_level) { - g_print ("Replace ldloca/initobj pair :\n\t"); + g_print ("Replace ldloca/zeroblk pair :\n\t"); interp_dump_ins (ins, td->data_items); } } diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index ac654631313fe7..d791ea9d579e4d 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -1938,9 +1938,21 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas } } else if (in_corlib && !strcmp (klass_name_space, "System") && - !strcmp (klass_name, "SpanHelpers") && - !strcmp (tm, "ClearWithReferences")) { - *op = MINT_INTRINS_CLEAR_WITH_REFERENCES; + !strcmp (klass_name, "SpanHelpers")) { + if (!strcmp (tm, "ClearWithReferences")) { + *op = MINT_INTRINS_CLEAR_WITH_REFERENCES; + } else if (!strcmp (tm, "ClearWithoutReferences")) { + *op = MINT_ZEROBLK; + } else if (!strcmp (tm, "Fill") && csignature->param_count == 3) { + int align; + if (mono_type_size (csignature->params [2], &align) == 1) { + interp_add_ins (td, MINT_INITBLK); + td->sp -= 3; + interp_ins_set_sregs3 (td->last_ins, td->sp [0].var, td->sp [2].var, td->sp [1].var); + td->ip += 5; + return TRUE; + } + } } else if (in_corlib && !strcmp (klass_name_space, "System") && !strcmp (klass_name, "Marvin")) { if (!strcmp (tm, "Block")) { InterpInst *ldloca2 = td->last_ins; @@ -8125,7 +8137,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, CHECK_TYPELOAD (klass); if (m_class_is_valuetype (klass)) { --td->sp; - interp_add_ins (td, MINT_INITOBJ); + interp_add_ins (td, MINT_ZEROBLK_IMM); interp_ins_set_sreg (td->last_ins, td->sp [0].var); i32 = mono_class_value_size (klass, NULL); g_assert (i32 < G_MAXUINT16);