Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wasm] Implement more jiterpreter opcodes #82849

Merged
merged 2 commits into from
Mar 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/mono/mono/mini/interp/jiterpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,16 @@ mono_jiterp_try_newobj_inlined (MonoObject **destination, MonoVTable *vtable) {
return 1;
}

EMSCRIPTEN_KEEPALIVE int
mono_jiterp_try_newstr (MonoString **destination, int length) {
ERROR_DECL(error);
*destination = mono_string_new_size_checked(length, error);
if (!is_ok (error))
*destination = 0;
mono_error_cleanup (error); // FIXME: do not swallow the error
return *destination != 0;
}

EMSCRIPTEN_KEEPALIVE int
mono_jiterp_gettype_ref (
MonoObject **destination, MonoObject **source
Expand Down Expand Up @@ -667,6 +677,7 @@ jiterp_should_abort_trace (InterpInst *ins, gboolean *inside_branch_block)
case MINT_BOX:
case MINT_BOX_VT:
case MINT_UNBOX:
case MINT_NEWSTR:
case MINT_NEWOBJ_INLINED:
case MINT_NEWOBJ_VT_INLINED:
case MINT_LD_DELEGATE_METHOD_PTR:
Expand All @@ -680,6 +691,7 @@ jiterp_should_abort_trace (InterpInst *ins, gboolean *inside_branch_block)
case MINT_ADD_MUL_I4_IMM:
case MINT_ADD_MUL_I8_IMM:
case MINT_ARRAY_RANK:
case MINT_ARRAY_ELEMENT_SIZE:
case MINT_MONO_CMPXCHG_I4:
case MINT_MONO_CMPXCHG_I8:
return TRACE_CONTINUE;
Expand Down Expand Up @@ -1114,6 +1126,18 @@ mono_jiterp_get_array_rank (gint32 *dest, MonoObject **src)
return 1;
}

EMSCRIPTEN_KEEPALIVE int
mono_jiterp_get_array_element_size (gint32 *dest, MonoObject **src)
{
if (!src || !*src) {
*dest = 0;
return 0;
}

*dest = mono_array_element_size (mono_object_class (*src));
return 1;
}

// Returns 1 on success so that the trace can do br_if to bypass its bailout
EMSCRIPTEN_KEEPALIVE int
mono_jiterp_set_object_field (
Expand Down
53 changes: 37 additions & 16 deletions src/mono/wasm/runtime/jiterpreter-trace-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -665,12 +665,13 @@ export function generate_wasm_body (
break;
}

case MintOpcode.MINT_ARRAY_RANK: {
case MintOpcode.MINT_ARRAY_RANK:
case MintOpcode.MINT_ARRAY_ELEMENT_SIZE: {
builder.block();
// dest, src
append_ldloca(builder, getArgU16(ip, 1), 4, true);
append_ldloca(builder, getArgU16(ip, 2), 0);
builder.callImport("array_rank");
builder.callImport(opcode === MintOpcode.MINT_ARRAY_RANK ? "array_rank" : "a_elesize");
// If the array was null we will bail out, otherwise continue
builder.appendU8(WasmOpcode.br_if);
builder.appendULeb(0);
Expand Down Expand Up @@ -729,6 +730,21 @@ export function generate_wasm_body (
break;
}

case MintOpcode.MINT_NEWSTR: {
builder.block();
append_ldloca(builder, getArgU16(ip, 1), 4, true);
append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load);
builder.callImport("newstr");
// If the newstr operation succeeded, continue, otherwise bailout
// Note that this assumes the newstr operation will fail again when the interpreter does it
// (the only reason for a newstr to fail I can think of is an out-of-memory condition)
builder.appendU8(WasmOpcode.br_if);
builder.appendULeb(0);
append_bailout(builder, ip, BailoutReason.AllocFailed);
builder.endBlock();
break;
}

case MintOpcode.MINT_NEWOBJ_INLINED: {
builder.block();
// MonoObject *o = mono_gc_alloc_obj (vtable, m_class_get_instance_size (vtable->klass));
Expand Down Expand Up @@ -1842,11 +1858,8 @@ const binopTable : { [opcode: number]: OpRec3 | OpRec4 | undefined } = {
[MintOpcode.MINT_ADD_I8]: [WasmOpcode.i64_add, WasmOpcode.i64_load, WasmOpcode.i64_store],
[MintOpcode.MINT_SUB_I8]: [WasmOpcode.i64_sub, WasmOpcode.i64_load, WasmOpcode.i64_store],
[MintOpcode.MINT_MUL_I8]: [WasmOpcode.i64_mul, WasmOpcode.i64_load, WasmOpcode.i64_store],
// Overflow check is too hard to do for int64 right now
/*
[MintOpcode.MINT_DIV_I8]: [WasmOpcode.i64_div_s, WasmOpcode.i64_load, WasmOpcode.i64_store],
[MintOpcode.MINT_REM_I8]: [WasmOpcode.i64_rem_s, WasmOpcode.i64_load, WasmOpcode.i64_store],
*/
[MintOpcode.MINT_DIV_UN_I8]: [WasmOpcode.i64_div_u, WasmOpcode.i64_load, WasmOpcode.i64_store],
[MintOpcode.MINT_REM_UN_I8]: [WasmOpcode.i64_rem_u, WasmOpcode.i64_load, WasmOpcode.i64_store],
[MintOpcode.MINT_AND_I8]: [WasmOpcode.i64_and, WasmOpcode.i64_load, WasmOpcode.i64_store],
Expand Down Expand Up @@ -2017,13 +2030,17 @@ function emit_binop (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode

switch (opcode) {
case MintOpcode.MINT_DIV_I4:
case MintOpcode.MINT_DIV_I8:
case MintOpcode.MINT_DIV_UN_I4:
case MintOpcode.MINT_DIV_UN_I8:
case MintOpcode.MINT_REM_I4:
case MintOpcode.MINT_REM_I8:
case MintOpcode.MINT_REM_UN_I4:
case MintOpcode.MINT_REM_UN_I8: {
const is64 = (opcode === MintOpcode.MINT_DIV_UN_I8) ||
(opcode === MintOpcode.MINT_REM_UN_I8);
(opcode === MintOpcode.MINT_REM_UN_I8) ||
(opcode === MintOpcode.MINT_DIV_I8) ||
(opcode === MintOpcode.MINT_REM_I8);
lhsVar = is64 ? "math_lhs64" : "math_lhs32";
rhsVar = is64 ? "math_rhs64" : "math_rhs32";

Expand All @@ -2049,30 +2066,34 @@ function emit_binop (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode
// Also perform overflow check for signed division operations
if (
(opcode === MintOpcode.MINT_DIV_I4) ||
(opcode === MintOpcode.MINT_REM_I4)
(opcode === MintOpcode.MINT_REM_I4) ||
(opcode === MintOpcode.MINT_DIV_I8) ||
(opcode === MintOpcode.MINT_REM_I8)
) {
builder.block();
builder.local(rhsVar);
// If rhs is -1 and lhs is MININT32 this is an overflow
builder.i32_const(-1);
builder.appendU8(WasmOpcode.i32_ne);
// If rhs is -1 and lhs is INTnn_MIN this is an overflow
if (is64)
builder.i52_const(-1);
else
builder.i32_const(-1);
builder.appendU8(is64 ? WasmOpcode.i64_ne : WasmOpcode.i32_ne);
builder.appendU8(WasmOpcode.br_if);
builder.appendULeb(0);
// rhs was -1 since the previous br_if didn't execute. Now check lhs.
builder.local(lhsVar);
// G_MININT32
builder.i32_const(-2147483647-1);
builder.appendU8(WasmOpcode.i32_ne);
// INTnn_MIN
builder.appendU8(is64 ? WasmOpcode.i64_const : WasmOpcode.i32_const);
builder.appendBoundaryValue(is64 ? 64 : 32, -1);
builder.appendU8(is64 ? WasmOpcode.i64_ne : WasmOpcode.i32_ne);
builder.appendU8(WasmOpcode.br_if);
builder.appendULeb(0);
append_bailout(builder, ip, BailoutReason.Overflow);
builder.endBlock();
}
break;
}
case MintOpcode.MINT_DIV_I8:
// We have to check lhs against MININT64 which is not 52-bit safe
return false;

case MintOpcode.MINT_ADD_OVF_I4:
case MintOpcode.MINT_ADD_OVF_UN_I4:
case MintOpcode.MINT_MUL_OVF_I4:
Expand Down
8 changes: 8 additions & 0 deletions src/mono/wasm/runtime/jiterpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ function getTraceImports () {
["ckovr_i4", "overflow_check_i4", getRawCwrap("mono_jiterp_overflow_check_i4")],
["ckovr_u4", "overflow_check_i4", getRawCwrap("mono_jiterp_overflow_check_u4")],
importDef("newobj_i", getRawCwrap("mono_jiterp_try_newobj_inlined")),
importDef("newstr", getRawCwrap("mono_jiterp_try_newstr")),
importDef("ld_del_ptr", getRawCwrap("mono_jiterp_ld_delegate_method_ptr")),
importDef("ldtsflda", getRawCwrap("mono_jiterp_ldtsflda")),
importDef("conv", getRawCwrap("mono_jiterp_conv")),
Expand All @@ -271,6 +272,7 @@ function getTraceImports () {
importDef("hascsize", getRawCwrap("mono_jiterp_object_has_component_size")),
importDef("hasflag", getRawCwrap("mono_jiterp_enum_hasflag")),
importDef("array_rank", getRawCwrap("mono_jiterp_get_array_rank")),
["a_elesize", "array_rank", getRawCwrap("mono_jiterp_get_array_element_size")],
importDef("stfld_o", getRawCwrap("mono_jiterp_set_object_field")),
importDef("transfer", getRawCwrap("mono_jiterp_trace_transfer")),
importDef("cmpxchg_i32", getRawCwrap("mono_jiterp_cas_i32")),
Expand Down Expand Up @@ -421,6 +423,12 @@ function initialize_builder (builder: WasmBuilder) {
"vtable": WasmValtype.i32,
}, WasmValtype.i32, true
);
builder.defineType(
"newstr", {
"ppDestination": WasmValtype.i32,
"length": WasmValtype.i32,
}, WasmValtype.i32, true
);
builder.defineType(
"localloc", {
"destination": WasmValtype.i32,
Expand Down