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] Clean up some FIXMEs in the jiterpreter #107562

Merged
merged 2 commits into from
Sep 10, 2024
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
30 changes: 14 additions & 16 deletions src/mono/browser/runtime/jiterpreter-trace-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -449,10 +449,9 @@ export function generateWasmBody (
if (pruneOpcodes) {
// We emit an unreachable opcode so that if execution somehow reaches a pruned opcode, we will abort
// This should be impossible anyway but it's also useful to have pruning visible in the wasm
// FIXME: Ideally we would stop generating opcodes after the first unreachable, but that causes v8 to hang
if (!hasEmittedUnreachable)
builder.appendU8(WasmOpcode.unreachable);
// Each unreachable opcode could generate a bunch of native code in a bad wasm jit so generate nops after it
// Don't generate multiple unreachable opcodes in a row
hasEmittedUnreachable = true;
}
break;
Expand All @@ -467,7 +466,7 @@ export function generateWasmBody (
}
case MintOpcode.MINT_LOCALLOC: {
// dest
append_ldloca(builder, getArgU16(ip, 1));
append_ldloca(builder, getArgU16(ip, 1), 0);
// len
append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load);
// frame
Expand Down Expand Up @@ -648,10 +647,12 @@ export function generateWasmBody (
// locals[ip[1]] = &locals[ip[2]]
const offset = getArgU16(ip, 2),
flag = isAddressTaken(builder, offset),
destOffset = getArgU16(ip, 1);
destOffset = getArgU16(ip, 1),
// Size value stored for us by emit_compacted_instruction so we can do invalidation
size = getArgU16(ip, 3);
if (!flag)
mono_log_error(`${traceName}: Expected local ${offset} to have address taken flag`);
append_ldloca(builder, offset);
append_ldloca(builder, offset, size);
append_stloc_tail(builder, destOffset, WasmOpcode.i32_store);
// Record this ldloca as a known constant so that later uses of it turn into a lea,
// and the wasm runtime can constant fold them with other constants. It's not uncommon
Expand Down Expand Up @@ -875,9 +876,8 @@ export function generateWasmBody (
}

case MintOpcode.MINT_LD_DELEGATE_METHOD_PTR: {
// FIXME: ldloca invalidation size
append_ldloca(builder, getArgU16(ip, 1), 8);
append_ldloca(builder, getArgU16(ip, 2), 8);
append_ldloca(builder, getArgU16(ip, 1), 4);
append_ldloca(builder, getArgU16(ip, 2), 4);
builder.callImport("ld_del_ptr");
break;
}
Expand Down Expand Up @@ -1383,7 +1383,9 @@ export function generateWasmBody (
(builder.callHandlerReturnAddresses.length <= maxCallHandlerReturnAddresses)
) {
// mono_log_info(`endfinally @0x${(<any>ip).toString(16)}. return addresses:`, builder.callHandlerReturnAddresses.map(ra => (<any>ra).toString(16)));
// FIXME: Clean this codegen up
// FIXME: Replace this with a chain of selects to more efficiently map from RA -> index, then
// a single jump table at the end to jump to the right place. This will generate much smaller
// code and be able to handle a larger number of return addresses.
// Load ret_ip
const clauseIndex = getArgU16(ip, 1),
clauseDataOffset = get_imethod_clause_data_offset(frame, clauseIndex);
Expand Down Expand Up @@ -1972,10 +1974,7 @@ function append_stloc_tail (builder: WasmBuilder, offset: number, opcodeOrPrefix

// Pass bytesInvalidated=0 if you are reading from the local and the address will never be
// used for writes
function append_ldloca (builder: WasmBuilder, localOffset: number, bytesInvalidated?: number) {
if (typeof (bytesInvalidated) !== "number")
bytesInvalidated = 512;
// FIXME: We need to know how big this variable is so we can invalidate the whole space it occupies
function append_ldloca (builder: WasmBuilder, localOffset: number, bytesInvalidated: number) {
if (bytesInvalidated > 0)
invalidate_local_range(localOffset, bytesInvalidated);
builder.lea("pLocals", localOffset);
Expand Down Expand Up @@ -2476,7 +2475,8 @@ function emit_sfieldop (
builder.ptr_const(pStaticData);
// src
append_ldloca(builder, localOffset, 0);
// FIXME: Use mono_gc_wbarrier_set_field_internal
// We don't need to use gc_wbarrier_set_field_internal here because there's no object
// reference, interp does a raw write
builder.callImport("copy_ptr");
return true;
case MintOpcode.MINT_LDSFLD_VT: {
Expand Down Expand Up @@ -2903,7 +2903,6 @@ function emit_branch (
);

cwraps.mono_jiterp_boost_back_branch_target(destination);
// FIXME: Should there be a safepoint here?
append_bailout(builder, destination, BailoutReason.BackwardBranch);
modifyCounter(JiterpCounter.BackBranchesNotEmitted, 1);
return true;
Expand Down Expand Up @@ -4036,7 +4035,6 @@ function emit_atomics (
if (!builder.options.enableAtomics)
return false;

// FIXME: memory barrier might be worthwhile to implement
// FIXME: We could probably unify most of the xchg/cmpxchg implementation into one implementation

const xchg = xchgTable[opcode];
Expand Down
13 changes: 0 additions & 13 deletions src/mono/browser/runtime/jiterpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -851,18 +851,6 @@ function generate_wasm (
// Get the exported trace function
const fn = traceInstance.exports[traceName];

// FIXME: Before threading can be supported, we will need to ensure that
// once we assign a function pointer index to a given trace, the trace is
// broadcast to all the JS workers and compiled + installed at the appropriate
// index in every worker's function pointer table. This also means that we
// would need to fill empty slots with a dummy function when growing the table
// so that any erroneous ENTERs will skip the opcode instead of crashing due
// to calling a null function pointer.
// Table grow operations will need to be synchronized between workers somehow,
// probably by storing the table size in a volatile global or something so that
// we know the range of indexes available to us and can ensure that threads
// independently jitting traces will not stomp on each other and all threads
// have a globally consistent view of which function pointer maps to each trace.
rejected = false;

let idx: number;
Expand Down Expand Up @@ -995,7 +983,6 @@ export function mono_interp_tier_prepare_jiterpreter (
if (!mostRecentOptions)
mostRecentOptions = getOptions();

// FIXME: We shouldn't need this check
if (!mostRecentOptions.enableTraces)
return JITERPRETER_NOT_JITTED;
else if (mostRecentOptions.wasmBytesLimit <= getCounter(JiterpCounter.BytesGenerated))
Expand Down
3 changes: 2 additions & 1 deletion src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -7657,7 +7657,8 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;

MINT_IN_CASE(MINT_LDLOCA_S)
LOCAL_VAR (ip [1], gpointer) = locals + ip [2];
ip += 3;
// ip[3] reserved for size data for jiterpreter
ip += 4;
MINT_IN_BREAK;

#define MOV(argtype1,argtype2) \
Expand Down
8 changes: 6 additions & 2 deletions src/mono/mono/mini/interp/mintops.def
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,11 @@ OPDEF(MINT_MOV_8_2, "mov.8.2", 5, 0, 0, MintOpPair2)
OPDEF(MINT_MOV_8_3, "mov.8.3", 7, 0, 0, MintOpPair3)
OPDEF(MINT_MOV_8_4, "mov.8.4", 9, 0, 0, MintOpPair4)

OPDEF(MINT_LDLOCA_S, "ldloca.s", 3, 1, 0, MintOpUShortInt)
// NOTE: We reserve an extra ushort at the end of this specifically to communicate information
// to the jiterpreter about how large the local is so that invalidation can be correct.
// FIXME: genmintops.py is way too simple to handle this having a different size on different targets,
// so it's got a size of 4 everywhere.
OPDEF(MINT_LDLOCA_S, "ldloca.s", 4, 1, 0, MintOpUShortInt)

OPDEF(MINT_LDIND_I1, "ldind.i1", 3, 1, 1, MintOpNoArgs)
OPDEF(MINT_LDIND_U1, "ldind.u1", 3, 1, 1, MintOpNoArgs)
Expand Down Expand Up @@ -838,7 +842,7 @@ OPDEF(MINT_INTRINS_WIDEN_ASCII_TO_UTF16, "intrins_widen_ascii_to_utf16", 5, 1, 3
OPDEF(MINT_METADATA_UPDATE_LDFLDA, "metadata_update.ldflda", 5, 1, 1, MintOpTwoShorts)

// This ifdef is fine because genmintops.py is generating output for HOST_BROWSER
#if HOST_BROWSER
#ifdef HOST_BROWSER
OPDEF(MINT_TIER_PREPARE_JITERPRETER, "tier_prepare_jiterpreter", 4, 0, 0, MintOpShortAndInt)
OPDEF(MINT_TIER_NOP_JITERPRETER, "tier_nop_jiterpreter", 4, 0, 0, MintOpShortAndInt)
OPDEF(MINT_TIER_ENTER_JITERPRETER, "tier_enter_jiterpreter", 4, 0, 0, MintOpShortAndInt)
Expand Down
6 changes: 6 additions & 0 deletions src/mono/mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -9241,6 +9241,12 @@ emit_compacted_instruction (TransformData *td, guint16* start_ip, InterpInst *in
} else if (opcode == MINT_LDLOCA_S) {
// This opcode receives a local but it is not viewed as a sreg since we don't load the value
*ip++ = GINT_TO_UINT16 (get_var_offset (td, ins->sregs [0]));

#if HOST_BROWSER
// We reserve an extra 2 bytes at the end of ldloca_s so the jiterpreter knows how large
// the var is when taking its address so that it can invalidate a properly sized range.
*ip++ = GINT_TO_UINT16 (td->vars [ins->sregs [0]].size);
#endif
}

int left = interp_get_ins_length (ins) - GPTRDIFF_TO_INT(ip - start_ip);
Expand Down
Loading