Skip to content

Commit ed1e1d4

Browse files
kgsirntar
authored andcommitted
[wasm] Clean up some FIXMEs in the jiterpreter (dotnet#107562)
* Cleanup some fixmes in the jiterpreter * Flow through size of the var in MINT_LDLOCA_S so jiterpreter can do accurate invalidation
1 parent a20eea8 commit ed1e1d4

File tree

5 files changed

+28
-32
lines changed

5 files changed

+28
-32
lines changed

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

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -449,10 +449,9 @@ export function generateWasmBody (
449449
if (pruneOpcodes) {
450450
// We emit an unreachable opcode so that if execution somehow reaches a pruned opcode, we will abort
451451
// This should be impossible anyway but it's also useful to have pruning visible in the wasm
452-
// FIXME: Ideally we would stop generating opcodes after the first unreachable, but that causes v8 to hang
453452
if (!hasEmittedUnreachable)
454453
builder.appendU8(WasmOpcode.unreachable);
455-
// Each unreachable opcode could generate a bunch of native code in a bad wasm jit so generate nops after it
454+
// Don't generate multiple unreachable opcodes in a row
456455
hasEmittedUnreachable = true;
457456
}
458457
break;
@@ -467,7 +466,7 @@ export function generateWasmBody (
467466
}
468467
case MintOpcode.MINT_LOCALLOC: {
469468
// dest
470-
append_ldloca(builder, getArgU16(ip, 1));
469+
append_ldloca(builder, getArgU16(ip, 1), 0);
471470
// len
472471
append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load);
473472
// frame
@@ -648,10 +647,12 @@ export function generateWasmBody (
648647
// locals[ip[1]] = &locals[ip[2]]
649648
const offset = getArgU16(ip, 2),
650649
flag = isAddressTaken(builder, offset),
651-
destOffset = getArgU16(ip, 1);
650+
destOffset = getArgU16(ip, 1),
651+
// Size value stored for us by emit_compacted_instruction so we can do invalidation
652+
size = getArgU16(ip, 3);
652653
if (!flag)
653654
mono_log_error(`${traceName}: Expected local ${offset} to have address taken flag`);
654-
append_ldloca(builder, offset);
655+
append_ldloca(builder, offset, size);
655656
append_stloc_tail(builder, destOffset, WasmOpcode.i32_store);
656657
// Record this ldloca as a known constant so that later uses of it turn into a lea,
657658
// and the wasm runtime can constant fold them with other constants. It's not uncommon
@@ -875,9 +876,8 @@ export function generateWasmBody (
875876
}
876877

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

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

29052905
cwraps.mono_jiterp_boost_back_branch_target(destination);
2906-
// FIXME: Should there be a safepoint here?
29072906
append_bailout(builder, destination, BailoutReason.BackwardBranch);
29082907
modifyCounter(JiterpCounter.BackBranchesNotEmitted, 1);
29092908
return true;
@@ -4036,7 +4035,6 @@ function emit_atomics (
40364035
if (!builder.options.enableAtomics)
40374036
return false;
40384037

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

40424040
const xchg = xchgTable[opcode];

src/mono/browser/runtime/jiterpreter.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -851,18 +851,6 @@ function generate_wasm (
851851
// Get the exported trace function
852852
const fn = traceInstance.exports[traceName];
853853

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

868856
let idx: number;
@@ -995,7 +983,6 @@ export function mono_interp_tier_prepare_jiterpreter (
995983
if (!mostRecentOptions)
996984
mostRecentOptions = getOptions();
997985

998-
// FIXME: We shouldn't need this check
999986
if (!mostRecentOptions.enableTraces)
1000987
return JITERPRETER_NOT_JITTED;
1001988
else if (mostRecentOptions.wasmBytesLimit <= getCounter(JiterpCounter.BytesGenerated))

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7657,7 +7657,8 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK;
76577657

76587658
MINT_IN_CASE(MINT_LDLOCA_S)
76597659
LOCAL_VAR (ip [1], gpointer) = locals + ip [2];
7660-
ip += 3;
7660+
// ip[3] reserved for size data for jiterpreter
7661+
ip += 4;
76617662
MINT_IN_BREAK;
76627663

76637664
#define MOV(argtype1,argtype2) \

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,11 @@ OPDEF(MINT_MOV_8_2, "mov.8.2", 5, 0, 0, MintOpPair2)
128128
OPDEF(MINT_MOV_8_3, "mov.8.3", 7, 0, 0, MintOpPair3)
129129
OPDEF(MINT_MOV_8_4, "mov.8.4", 9, 0, 0, MintOpPair4)
130130

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

133137
OPDEF(MINT_LDIND_I1, "ldind.i1", 3, 1, 1, MintOpNoArgs)
134138
OPDEF(MINT_LDIND_U1, "ldind.u1", 3, 1, 1, MintOpNoArgs)
@@ -838,7 +842,7 @@ OPDEF(MINT_INTRINS_WIDEN_ASCII_TO_UTF16, "intrins_widen_ascii_to_utf16", 5, 1, 3
838842
OPDEF(MINT_METADATA_UPDATE_LDFLDA, "metadata_update.ldflda", 5, 1, 1, MintOpTwoShorts)
839843

840844
// This ifdef is fine because genmintops.py is generating output for HOST_BROWSER
841-
#if HOST_BROWSER
845+
#ifdef HOST_BROWSER
842846
OPDEF(MINT_TIER_PREPARE_JITERPRETER, "tier_prepare_jiterpreter", 4, 0, 0, MintOpShortAndInt)
843847
OPDEF(MINT_TIER_NOP_JITERPRETER, "tier_nop_jiterpreter", 4, 0, 0, MintOpShortAndInt)
844848
OPDEF(MINT_TIER_ENTER_JITERPRETER, "tier_enter_jiterpreter", 4, 0, 0, MintOpShortAndInt)

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9241,6 +9241,12 @@ emit_compacted_instruction (TransformData *td, guint16* start_ip, InterpInst *in
92419241
} else if (opcode == MINT_LDLOCA_S) {
92429242
// This opcode receives a local but it is not viewed as a sreg since we don't load the value
92439243
*ip++ = GINT_TO_UINT16 (get_var_offset (td, ins->sregs [0]));
9244+
9245+
#if HOST_BROWSER
9246+
// We reserve an extra 2 bytes at the end of ldloca_s so the jiterpreter knows how large
9247+
// the var is when taking its address so that it can invalidate a properly sized range.
9248+
*ip++ = GINT_TO_UINT16 (td->vars [ins->sregs [0]].size);
9249+
#endif
92449250
}
92459251

92469252
int left = interp_get_ins_length (ins) - GPTRDIFF_TO_INT(ip - start_ip);

0 commit comments

Comments
 (0)