Skip to content

Commit

Permalink
Generate an unconditional bailout for MINT_SWITCH in jiterpreter trac…
Browse files Browse the repository at this point in the history
…es instead of aborting the trace (dotnet#107323)

Better diagnostic output when jiterp hits an invalid opcode
  • Loading branch information
kg authored and jtschuster committed Sep 17, 2024
1 parent d3b467b commit 5385a40
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 5 deletions.
2 changes: 2 additions & 0 deletions src/mono/browser/runtime/jiterpreter-enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export const enum BailoutReason {
Icall,
UnexpectedRetIp,
LeaveCheck,
Switch,
}

export const BailoutReasonNames = [
Expand Down Expand Up @@ -157,6 +158,7 @@ export const BailoutReasonNames = [
"Icall",
"UnexpectedRetIp",
"LeaveCheck",
"Switch",
];

export const enum JitQueue {
Expand Down
39 changes: 34 additions & 5 deletions src/mono/browser/runtime/jiterpreter-trace-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ function getArgI16 (ip: MintOpcodePtr, indexPlusOne: number) {
return getI16(<any>ip + (2 * indexPlusOne));
}

function getArgU32 (ip: MintOpcodePtr, indexPlusOne: number) {
const src = <any>ip + (2 * indexPlusOne);
return getU32_unaligned(src);
}

function getArgI32 (ip: MintOpcodePtr, indexPlusOne: number) {
const src = <any>ip + (2 * indexPlusOne);
return getI32_unaligned(src);
Expand Down Expand Up @@ -160,6 +165,24 @@ function get_known_constant_value (builder: WasmBuilder, localOffset: number): K
return undefined;
}

function getOpcodeLengthU16 (ip: MintOpcodePtr, opcode: MintOpcode) {
try {
const opLengthU16 = cwraps.mono_jiterp_get_opcode_info(opcode, OpcodeInfoType.Length);
let result = opLengthU16;
if (opcode === MintOpcode.MINT_SWITCH) {
// int n = READ32 (ip + 2);
// len = MINT_SWITCH_LEN (n);
const numDisplacements = getArgU32(ip, 2);
// #define MINT_SWITCH_LEN(n) (4 + (n) * 2)
result = 4 + (numDisplacements * 2);
}
return result;
} catch (err) {
mono_log_error(`Found invalid opcode ${opcode} at ip ${ip}`);
throw err;
}
}

// Perform a quick scan through the opcodes potentially in this trace to build a table of
// backwards branch targets, compatible with the layout of the old one that was generated in C.
// We do this here to match the exact way that the jiterp calculates branch targets, since
Expand All @@ -179,11 +202,8 @@ export function generateBackwardBranchTable (
// IP of the current opcode in U16s, relative to startOfBody. This is what the back branch table uses
const rip16 = (<any>ip - <any>startOfBody) / 2;
const opcode = <MintOpcode>getU16(ip);
// HACK
if (opcode === MintOpcode.MINT_SWITCH)
break;
const opLengthU16 = getOpcodeLengthU16(ip, opcode);

const opLengthU16 = cwraps.mono_jiterp_get_opcode_info(opcode, OpcodeInfoType.Length);
// Any opcode with a branch argtype will have a decoded displacement, even if we don't
// implement the opcode. Everything else will return undefined here and be skipped
const displacement = getBranchDisplacement(ip, opcode);
Expand Down Expand Up @@ -294,7 +314,7 @@ export function generateWasmBody (
let opcode = getU16(ip);
const numSregs = cwraps.mono_jiterp_get_opcode_info(opcode, OpcodeInfoType.Sregs),
numDregs = cwraps.mono_jiterp_get_opcode_info(opcode, OpcodeInfoType.Dregs),
opLengthU16 = cwraps.mono_jiterp_get_opcode_info(opcode, OpcodeInfoType.Length);
opLengthU16 = getOpcodeLengthU16(ip, opcode);

const isSimdIntrins = (opcode >= MintOpcode.MINT_SIMD_INTRINS_P_P) &&
(opcode <= MintOpcode.MINT_SIMD_INTRINS_P_PPP);
Expand Down Expand Up @@ -377,6 +397,11 @@ export function generateWasmBody (
}

switch (opcode) {
case MintOpcode.MINT_SWITCH: {
if (!emit_switch(builder, ip))
ip = abort;
break;
}
case MintOpcode.MINT_NOP: {
// This typically means the current opcode was disabled or pruned
if (pruneOpcodes) {
Expand Down Expand Up @@ -3996,3 +4021,7 @@ function emit_atomics (
return false;
}

function emit_switch (builder: WasmBuilder, ip: MintOpcodePtr) : boolean {
append_bailout(builder, ip, BailoutReason.Switch);
return true;
}
4 changes: 4 additions & 0 deletions src/mono/mono/mini/interp/jiterpreter-opcode-values.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ OP(MINT_LOG2_I8, HIGH)
OP(MINT_SHL_AND_I4, HIGH)
OP(MINT_SHL_AND_I8, HIGH)

// Produces a bailout at compile time, may produce an actual jump table
// later in the future. Treat it as a low value branch
OP(MINT_SWITCH, BRANCH)

// Produces either a backwards branch or a bailout depending on JIT-time
// information, so treat it as a low value branch
OP(MINT_ENDFINALLY, BRANCH)
Expand Down

0 comments on commit 5385a40

Please sign in to comment.