Skip to content

Commit

Permalink
[mono][interp] Revert short branch removal (#106178)
Browse files Browse the repository at this point in the history
* Revert "[wasm] Fix long branches in jiterpreter (#106030)"

This reverts commit 9fa8fd5.

* Revert "[mono][interp] Remove short branches (#105386)"

This reverts commit ac89819.
  • Loading branch information
BrzVlad committed Aug 9, 2024
1 parent 26da849 commit 07f9843
Show file tree
Hide file tree
Showing 11 changed files with 535 additions and 161 deletions.
3 changes: 2 additions & 1 deletion src/mono/browser/runtime/jiterpreter-opcodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const enum MintOpArgType {
MintOpFloat,
MintOpDouble,
MintOpBranch,
MintOpShortBranch,
MintOpSwitch,
MintOpMethodToken,
MintOpFieldToken,
Expand All @@ -44,7 +45,7 @@ export const enum MintOpArgType {
MintOpTwoShorts,
MintOpTwoInts,
MintOpShortAndInt,
MintOpShortAndBranch,
MintOpShortAndShortBranch,
MintOpPair2,
MintOpPair3,
MintOpPair4
Expand Down
82 changes: 41 additions & 41 deletions src/mono/browser/runtime/jiterpreter-tables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,16 +194,16 @@ export const binopTable: { [opcode: number]: OpRec3 | OpRec4 | undefined } = {
};

export const relopbranchTable: { [opcode: number]: [comparisonOpcode: MintOpcode, immediateOpcode: WasmOpcode | false, isSafepoint: boolean] | MintOpcode | undefined } = {
[MintOpcode.MINT_BEQ_I4]: MintOpcode.MINT_CEQ_I4,
[MintOpcode.MINT_BNE_UN_I4]: MintOpcode.MINT_CNE_I4,
[MintOpcode.MINT_BGT_I4]: MintOpcode.MINT_CGT_I4,
[MintOpcode.MINT_BGT_UN_I4]: MintOpcode.MINT_CGT_UN_I4,
[MintOpcode.MINT_BLT_I4]: MintOpcode.MINT_CLT_I4,
[MintOpcode.MINT_BLT_UN_I4]: MintOpcode.MINT_CLT_UN_I4,
[MintOpcode.MINT_BGE_I4]: MintOpcode.MINT_CGE_I4,
[MintOpcode.MINT_BGE_UN_I4]: MintOpcode.MINT_CGE_UN_I4,
[MintOpcode.MINT_BLE_I4]: MintOpcode.MINT_CLE_I4,
[MintOpcode.MINT_BLE_UN_I4]: MintOpcode.MINT_CLE_UN_I4,
[MintOpcode.MINT_BEQ_I4_S]: MintOpcode.MINT_CEQ_I4,
[MintOpcode.MINT_BNE_UN_I4_S]: MintOpcode.MINT_CNE_I4,
[MintOpcode.MINT_BGT_I4_S]: MintOpcode.MINT_CGT_I4,
[MintOpcode.MINT_BGT_UN_I4_S]: MintOpcode.MINT_CGT_UN_I4,
[MintOpcode.MINT_BLT_I4_S]: MintOpcode.MINT_CLT_I4,
[MintOpcode.MINT_BLT_UN_I4_S]: MintOpcode.MINT_CLT_UN_I4,
[MintOpcode.MINT_BGE_I4_S]: MintOpcode.MINT_CGE_I4,
[MintOpcode.MINT_BGE_UN_I4_S]: MintOpcode.MINT_CGE_UN_I4,
[MintOpcode.MINT_BLE_I4_S]: MintOpcode.MINT_CLE_I4,
[MintOpcode.MINT_BLE_UN_I4_S]: MintOpcode.MINT_CLE_UN_I4,

[MintOpcode.MINT_BEQ_I4_SP]: [MintOpcode.MINT_CEQ_I4, false, true],
[MintOpcode.MINT_BNE_UN_I4_SP]: [MintOpcode.MINT_CNE_I4, false, true],
Expand All @@ -227,16 +227,16 @@ export const relopbranchTable: { [opcode: number]: [comparisonOpcode: MintOpcode
[MintOpcode.MINT_BLE_I4_IMM_SP]: [MintOpcode.MINT_CLE_I4, WasmOpcode.i32_const, true],
[MintOpcode.MINT_BLE_UN_I4_IMM_SP]: [MintOpcode.MINT_CLE_UN_I4, WasmOpcode.i32_const, true],

[MintOpcode.MINT_BEQ_I8]: MintOpcode.MINT_CEQ_I8,
[MintOpcode.MINT_BNE_UN_I8]: MintOpcode.MINT_CNE_I8,
[MintOpcode.MINT_BGT_I8]: MintOpcode.MINT_CGT_I8,
[MintOpcode.MINT_BGT_UN_I8]: MintOpcode.MINT_CGT_UN_I8,
[MintOpcode.MINT_BLT_I8]: MintOpcode.MINT_CLT_I8,
[MintOpcode.MINT_BLT_UN_I8]: MintOpcode.MINT_CLT_UN_I8,
[MintOpcode.MINT_BGE_I8]: MintOpcode.MINT_CGE_I8,
[MintOpcode.MINT_BGE_UN_I8]: MintOpcode.MINT_CGE_UN_I8,
[MintOpcode.MINT_BLE_I8]: MintOpcode.MINT_CLE_I8,
[MintOpcode.MINT_BLE_UN_I8]: MintOpcode.MINT_CLE_UN_I8,
[MintOpcode.MINT_BEQ_I8_S]: MintOpcode.MINT_CEQ_I8,
[MintOpcode.MINT_BNE_UN_I8_S]: MintOpcode.MINT_CNE_I8,
[MintOpcode.MINT_BGT_I8_S]: MintOpcode.MINT_CGT_I8,
[MintOpcode.MINT_BGT_UN_I8_S]: MintOpcode.MINT_CGT_UN_I8,
[MintOpcode.MINT_BLT_I8_S]: MintOpcode.MINT_CLT_I8,
[MintOpcode.MINT_BLT_UN_I8_S]: MintOpcode.MINT_CLT_UN_I8,
[MintOpcode.MINT_BGE_I8_S]: MintOpcode.MINT_CGE_I8,
[MintOpcode.MINT_BGE_UN_I8_S]: MintOpcode.MINT_CGE_UN_I8,
[MintOpcode.MINT_BLE_I8_S]: MintOpcode.MINT_CLE_I8,
[MintOpcode.MINT_BLE_UN_I8_S]: MintOpcode.MINT_CLE_UN_I8,

[MintOpcode.MINT_BEQ_I8_IMM_SP]: [MintOpcode.MINT_CEQ_I8, WasmOpcode.i64_const, true],
// FIXME: Missing compare opcode
Expand All @@ -250,27 +250,27 @@ export const relopbranchTable: { [opcode: number]: [comparisonOpcode: MintOpcode
[MintOpcode.MINT_BLE_I8_IMM_SP]: [MintOpcode.MINT_CLE_I8, WasmOpcode.i64_const, true],
[MintOpcode.MINT_BLE_UN_I8_IMM_SP]: [MintOpcode.MINT_CLE_UN_I8, WasmOpcode.i64_const, true],

[MintOpcode.MINT_BEQ_R4]: MintOpcode.MINT_CEQ_R4,
[MintOpcode.MINT_BNE_UN_R4]: <any>JiterpSpecialOpcode.CNE_UN_R4,
[MintOpcode.MINT_BGT_R4]: MintOpcode.MINT_CGT_R4,
[MintOpcode.MINT_BGT_UN_R4]: MintOpcode.MINT_CGT_UN_R4,
[MintOpcode.MINT_BLT_R4]: MintOpcode.MINT_CLT_R4,
[MintOpcode.MINT_BLT_UN_R4]: MintOpcode.MINT_CLT_UN_R4,
[MintOpcode.MINT_BGE_R4]: MintOpcode.MINT_CGE_R4,
[MintOpcode.MINT_BGE_UN_R4]: <any>JiterpSpecialOpcode.CGE_UN_R4,
[MintOpcode.MINT_BLE_R4]: MintOpcode.MINT_CLE_R4,
[MintOpcode.MINT_BLE_UN_R4]: <any>JiterpSpecialOpcode.CLE_UN_R4,

[MintOpcode.MINT_BEQ_R8]: MintOpcode.MINT_CEQ_R8,
[MintOpcode.MINT_BNE_UN_R8]: <any>JiterpSpecialOpcode.CNE_UN_R8,
[MintOpcode.MINT_BGT_R8]: MintOpcode.MINT_CGT_R8,
[MintOpcode.MINT_BGT_UN_R8]: MintOpcode.MINT_CGT_UN_R8,
[MintOpcode.MINT_BLT_R8]: MintOpcode.MINT_CLT_R8,
[MintOpcode.MINT_BLT_UN_R8]: MintOpcode.MINT_CLT_UN_R8,
[MintOpcode.MINT_BGE_R8]: MintOpcode.MINT_CGE_R8,
[MintOpcode.MINT_BGE_UN_R8]: <any>JiterpSpecialOpcode.CGE_UN_R8,
[MintOpcode.MINT_BLE_R8]: MintOpcode.MINT_CLE_R8,
[MintOpcode.MINT_BLE_UN_R8]: <any>JiterpSpecialOpcode.CLE_UN_R8,
[MintOpcode.MINT_BEQ_R4_S]: MintOpcode.MINT_CEQ_R4,
[MintOpcode.MINT_BNE_UN_R4_S]: <any>JiterpSpecialOpcode.CNE_UN_R4,
[MintOpcode.MINT_BGT_R4_S]: MintOpcode.MINT_CGT_R4,
[MintOpcode.MINT_BGT_UN_R4_S]: MintOpcode.MINT_CGT_UN_R4,
[MintOpcode.MINT_BLT_R4_S]: MintOpcode.MINT_CLT_R4,
[MintOpcode.MINT_BLT_UN_R4_S]: MintOpcode.MINT_CLT_UN_R4,
[MintOpcode.MINT_BGE_R4_S]: MintOpcode.MINT_CGE_R4,
[MintOpcode.MINT_BGE_UN_R4_S]: <any>JiterpSpecialOpcode.CGE_UN_R4,
[MintOpcode.MINT_BLE_R4_S]: MintOpcode.MINT_CLE_R4,
[MintOpcode.MINT_BLE_UN_R4_S]: <any>JiterpSpecialOpcode.CLE_UN_R4,

[MintOpcode.MINT_BEQ_R8_S]: MintOpcode.MINT_CEQ_R8,
[MintOpcode.MINT_BNE_UN_R8_S]: <any>JiterpSpecialOpcode.CNE_UN_R8,
[MintOpcode.MINT_BGT_R8_S]: MintOpcode.MINT_CGT_R8,
[MintOpcode.MINT_BGT_UN_R8_S]: MintOpcode.MINT_CGT_UN_R8,
[MintOpcode.MINT_BLT_R8_S]: MintOpcode.MINT_CLT_R8,
[MintOpcode.MINT_BLT_UN_R8_S]: MintOpcode.MINT_CLT_UN_R8,
[MintOpcode.MINT_BGE_R8_S]: MintOpcode.MINT_CGE_R8,
[MintOpcode.MINT_BGE_UN_R8_S]: <any>JiterpSpecialOpcode.CGE_UN_R8,
[MintOpcode.MINT_BLE_R8_S]: MintOpcode.MINT_CLE_R8,
[MintOpcode.MINT_BLE_UN_R8_S]: <any>JiterpSpecialOpcode.CLE_UN_R8,
};

export const mathIntrinsicTable: { [opcode: number]: [isUnary: boolean, isF32: boolean, opcodeOrFuncName: WasmOpcode | string] } = {
Expand Down
83 changes: 39 additions & 44 deletions src/mono/browser/runtime/jiterpreter-trace-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ export function generateBackwardBranchTable (

switch (opcode) {
case MintOpcode.MINT_CALL_HANDLER:
case MintOpcode.MINT_CALL_HANDLER_S:
// While this formally isn't a backward branch target, we want to record
// the offset of its following instruction so that the jiterpreter knows
// to generate the necessary dispatch code to enable branching back to it.
Expand Down Expand Up @@ -505,15 +506,21 @@ export function generateWasmBody (
}

// Other conditional branch types are handled by the relop table.
case MintOpcode.MINT_BRFALSE_I4_S:
case MintOpcode.MINT_BRTRUE_I4_S:
case MintOpcode.MINT_BRFALSE_I4_SP:
case MintOpcode.MINT_BRTRUE_I4_SP:
case MintOpcode.MINT_BRFALSE_I8_S:
case MintOpcode.MINT_BRTRUE_I8_S:
if (!emit_branch(builder, ip, frame, opcode))
ip = abort;
else
isConditionallyExecuted = true;
break;

case MintOpcode.MINT_BR_S:
case MintOpcode.MINT_CALL_HANDLER:
case MintOpcode.MINT_CALL_HANDLER_S:
if (!emit_branch(builder, ip, frame, opcode))
ip = abort;
else {
Expand Down Expand Up @@ -1286,6 +1293,7 @@ export function generateWasmBody (
// These are generated in place of regular LEAVEs inside of the body of a catch clause.
// We can safely assume that during normal execution, catch clauses won't be running.
case MintOpcode.MINT_LEAVE_CHECK:
case MintOpcode.MINT_LEAVE_S_CHECK:
append_bailout(builder, ip, BailoutReason.LeaveCheck);
pruneOpcodes = true;
break;
Expand Down Expand Up @@ -2735,9 +2743,10 @@ function emit_unop (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode)

function append_call_handler_store_ret_ip (
builder: WasmBuilder, ip: MintOpcodePtr,
frame: NativePointer
frame: NativePointer, opcode: MintOpcode
) {
const retIp = <any>ip + (4 * 2),
const shortOffset = (opcode === MintOpcode.MINT_CALL_HANDLER_S),
retIp = shortOffset ? <any>ip + (3 * 2) : <any>ip + (4 * 2),
clauseIndex = getU16(retIp - 2),
clauseDataOffset = get_imethod_clause_data_offset(frame, clauseIndex);

Expand All @@ -2752,21 +2761,6 @@ function append_call_handler_store_ret_ip (
builder.callHandlerReturnAddresses.push(retIp);
}

function getBranchImmediate (
ip: MintOpcodePtr, opcode: MintOpcode
): number | undefined {
const opArgType = cwraps.mono_jiterp_get_opcode_info(opcode, OpcodeInfoType.OpArgType),
payloadOffset = cwraps.mono_jiterp_get_opcode_info(opcode, OpcodeInfoType.Sregs),
payloadAddress = <any>ip + 2 + (payloadOffset * 2);

switch (opArgType) {
case MintOpArgType.MintOpShortAndBranch:
return getI16(payloadAddress);
default:
return undefined;
}
}

function getBranchDisplacement (
ip: MintOpcodePtr, opcode: MintOpcode
): number | undefined {
Expand All @@ -2779,8 +2773,11 @@ function getBranchDisplacement (
case MintOpArgType.MintOpBranch:
result = getI32_unaligned(payloadAddress);
break;
case MintOpArgType.MintOpShortAndBranch:
result = getI32_unaligned(payloadAddress + 2);
case MintOpArgType.MintOpShortBranch:
result = getI16(payloadAddress);
break;
case MintOpArgType.MintOpShortAndShortBranch:
result = getI16(payloadAddress + 2);
break;
default:
return undefined;
Expand All @@ -2800,10 +2797,8 @@ function emit_branch (
(opcode <= MintOpcode.MINT_BLT_UN_I8_IMM_SP);

const displacement = getBranchDisplacement(ip, opcode);
if (typeof (displacement) !== "number") {
// mono_log_info(`Failed to decode branch displacement for ${getOpcodeName(opcode)}`);
if (typeof (displacement) !== "number")
return false;
}

// If the branch is taken we bail out to allow the interpreter to do it.
// So for brtrue, we want to do 'cond == 0' to produce a bailout only
Expand All @@ -2813,8 +2808,11 @@ function emit_branch (
// branch target (if possible), bailing out at the end otherwise
switch (opcode) {
case MintOpcode.MINT_CALL_HANDLER:
case MintOpcode.MINT_BR: {
const isCallHandler = opcode === MintOpcode.MINT_CALL_HANDLER;
case MintOpcode.MINT_CALL_HANDLER_S:
case MintOpcode.MINT_BR:
case MintOpcode.MINT_BR_S: {
const isCallHandler = (opcode === MintOpcode.MINT_CALL_HANDLER) ||
(opcode === MintOpcode.MINT_CALL_HANDLER_S);

const destination = <any>ip + (displacement * 2);

Expand All @@ -2826,7 +2824,7 @@ function emit_branch (
if (builder.backBranchTraceLevel > 1)
mono_log_info(`0x${(<any>ip).toString(16)} performing backward branch to 0x${destination.toString(16)}`);
if (isCallHandler)
append_call_handler_store_ret_ip(builder, ip, frame);
append_call_handler_store_ret_ip(builder, ip, frame, opcode);
builder.cfg.branch(destination, true, CfgBranchType.Unconditional);
modifyCounter(JiterpCounter.BackBranchesEmitted, 1);
return true;
Expand All @@ -2851,32 +2849,32 @@ function emit_branch (
// the current branch block after updating eip
builder.branchTargets.add(destination);
if (isCallHandler)
append_call_handler_store_ret_ip(builder, ip, frame);
append_call_handler_store_ret_ip(builder, ip, frame, opcode);
builder.cfg.branch(destination, false, CfgBranchType.Unconditional);
return true;
}
}

case MintOpcode.MINT_BRTRUE_I4:
case MintOpcode.MINT_BRFALSE_I4:
case MintOpcode.MINT_BRTRUE_I4_S:
case MintOpcode.MINT_BRFALSE_I4_S:
case MintOpcode.MINT_BRTRUE_I4_SP:
case MintOpcode.MINT_BRFALSE_I4_SP:
case MintOpcode.MINT_BRTRUE_I8:
case MintOpcode.MINT_BRFALSE_I8: {
const is64 = (opcode === MintOpcode.MINT_BRTRUE_I8) ||
(opcode === MintOpcode.MINT_BRFALSE_I8);
case MintOpcode.MINT_BRTRUE_I8_S:
case MintOpcode.MINT_BRFALSE_I8_S: {
const is64 = (opcode === MintOpcode.MINT_BRTRUE_I8_S) ||
(opcode === MintOpcode.MINT_BRFALSE_I8_S);

// Load the condition

append_ldloc(builder, getArgU16(ip, 1), is64 ? WasmOpcode.i64_load : WasmOpcode.i32_load);
if (
(opcode === MintOpcode.MINT_BRFALSE_I4) ||
(opcode === MintOpcode.MINT_BRFALSE_I4_S) ||
(opcode === MintOpcode.MINT_BRFALSE_I4_SP)
)
builder.appendU8(WasmOpcode.i32_eqz);
else if (opcode === MintOpcode.MINT_BRFALSE_I8) {
else if (opcode === MintOpcode.MINT_BRFALSE_I8_S) {
builder.appendU8(WasmOpcode.i64_eqz);
} else if (opcode === MintOpcode.MINT_BRTRUE_I8) {
} else if (opcode === MintOpcode.MINT_BRTRUE_I8_S) {
// do (i64 == 0) == 0 because br_if can only branch on an i32 operand
builder.appendU8(WasmOpcode.i64_eqz);
builder.appendU8(WasmOpcode.i32_eqz);
Expand All @@ -2891,6 +2889,9 @@ function emit_branch (
if (relopbranchTable[opcode] === undefined)
throw new Error(`Unsupported relop branch opcode: ${getOpcodeName(opcode)}`);

if (cwraps.mono_jiterp_get_opcode_info(opcode, OpcodeInfoType.Length) !== 4)
throw new Error(`Unsupported long branch opcode: ${getOpcodeName(opcode)}`);

break;
}
}
Expand Down Expand Up @@ -2934,10 +2935,8 @@ function emit_relop_branch (
frame: NativePointer, opcode: MintOpcode
): boolean {
const relopBranchInfo = relopbranchTable[opcode];
if (!relopBranchInfo) {
// mono_log_info(`No info for relop branch ${getOpcodeName(opcode)}`);
if (!relopBranchInfo)
return false;
}

const relop = Array.isArray(relopBranchInfo)
? relopBranchInfo[0]
Expand All @@ -2946,10 +2945,8 @@ function emit_relop_branch (
const relopInfo = binopTable[relop];
const intrinsicFpBinop = intrinsicFpBinops[relop];

if (!relopInfo && !intrinsicFpBinop) {
// mono_log_info(`No info for relop ${getOpcodeName(opcode)} -> ${getOpcodeName(relop)}`);
if (!relopInfo && !intrinsicFpBinop)
return false;
}

const operandLoadOp = relopInfo
? relopInfo[1]
Expand All @@ -2966,13 +2963,11 @@ function emit_relop_branch (

// Compare with immediate
if (Array.isArray(relopBranchInfo) && relopBranchInfo[1]) {
const immediate = getBranchImmediate(ip, opcode);
mono_assert(immediate !== undefined, `Failed to decode immediate for branch opcode ${getOpcodeName(opcode)}`);
// For i8 immediates we need to generate an i64.const even though
// the immediate is 16 bits, so we store the relevant opcode
// in the relop branch info table
builder.appendU8(relopBranchInfo[1]);
builder.appendLeb(immediate);
builder.appendLeb(getArgI16(ip, 2));
} else
append_ldloc(builder, getArgU16(ip, 2), operandLoadOp);

Expand Down
Loading

0 comments on commit 07f9843

Please sign in to comment.