From ac898195da4ba1c6cb2431c47aab0a71cdee25a8 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Fri, 2 Aug 2024 15:20:27 +0300 Subject: [PATCH] [mono][interp] Remove short branches (#105386) * [mono][interp] Make all branch super instructions operate on long offsets Previously they were all short branches without long counterparts. This was buggy and awkward because we tried to compute early conservatively whether a branch is short or long, at superins generation time. The conditions would always hold and we had no fallback if the branch didn't turn out to actually be short. Having a long offset for these branches should have negligible perf impact. * [mono][wasm] Fix jiterp for branch superins * [mono][interp] Don't compute native offset estimate during super ins pass We generate superins without caring if the branch is long or short since the superinstructions use a long offset now. * [mono][interp] Completely remove short branches They don't seem to have any benefit at the expense of a lot of code and added complexity. --- .../browser/runtime/jiterpreter-opcodes.ts | 2 +- .../browser/runtime/jiterpreter-tables.ts | 82 +++--- .../runtime/jiterpreter-trace-generator.ts | 49 ++-- src/mono/mono/mini/interp/interp.c | 247 +----------------- .../mini/interp/jiterpreter-opcode-values.h | 5 +- src/mono/mono/mini/interp/jiterpreter.c | 2 - src/mono/mono/mini/interp/mintops.def | 146 ++++------- src/mono/mono/mini/interp/mintops.h | 11 +- src/mono/mono/mini/interp/transform-opt.c | 8 +- src/mono/mono/mini/interp/transform.c | 106 +------- src/mono/mono/mini/interp/transform.h | 3 +- 11 files changed, 134 insertions(+), 527 deletions(-) diff --git a/src/mono/browser/runtime/jiterpreter-opcodes.ts b/src/mono/browser/runtime/jiterpreter-opcodes.ts index d535070df2ae8..1680016d2a670 100644 --- a/src/mono/browser/runtime/jiterpreter-opcodes.ts +++ b/src/mono/browser/runtime/jiterpreter-opcodes.ts @@ -45,7 +45,7 @@ export const enum MintOpArgType { MintOpTwoShorts, MintOpTwoInts, MintOpShortAndInt, - MintOpShortAndShortBranch, + MintOpShortAndBranch, MintOpPair2, MintOpPair3, MintOpPair4 diff --git a/src/mono/browser/runtime/jiterpreter-tables.ts b/src/mono/browser/runtime/jiterpreter-tables.ts index a345844e9d904..76a76798f7ea8 100644 --- a/src/mono/browser/runtime/jiterpreter-tables.ts +++ b/src/mono/browser/runtime/jiterpreter-tables.ts @@ -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_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]: 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_SP]: [MintOpcode.MINT_CEQ_I4, false, true], [MintOpcode.MINT_BNE_UN_I4_SP]: [MintOpcode.MINT_CNE_I4, false, true], @@ -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_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]: 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_IMM_SP]: [MintOpcode.MINT_CEQ_I8, WasmOpcode.i64_const, true], // FIXME: Missing compare opcode @@ -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_S]: MintOpcode.MINT_CEQ_R4, - [MintOpcode.MINT_BNE_UN_R4_S]: 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]: JiterpSpecialOpcode.CGE_UN_R4, - [MintOpcode.MINT_BLE_R4_S]: MintOpcode.MINT_CLE_R4, - [MintOpcode.MINT_BLE_UN_R4_S]: JiterpSpecialOpcode.CLE_UN_R4, - - [MintOpcode.MINT_BEQ_R8_S]: MintOpcode.MINT_CEQ_R8, - [MintOpcode.MINT_BNE_UN_R8_S]: 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]: JiterpSpecialOpcode.CGE_UN_R8, - [MintOpcode.MINT_BLE_R8_S]: MintOpcode.MINT_CLE_R8, - [MintOpcode.MINT_BLE_UN_R8_S]: JiterpSpecialOpcode.CLE_UN_R8, + [MintOpcode.MINT_BEQ_R4]: MintOpcode.MINT_CEQ_R4, + [MintOpcode.MINT_BNE_UN_R4]: 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]: JiterpSpecialOpcode.CGE_UN_R4, + [MintOpcode.MINT_BLE_R4]: MintOpcode.MINT_CLE_R4, + [MintOpcode.MINT_BLE_UN_R4]: JiterpSpecialOpcode.CLE_UN_R4, + + [MintOpcode.MINT_BEQ_R8]: MintOpcode.MINT_CEQ_R8, + [MintOpcode.MINT_BNE_UN_R8]: 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]: JiterpSpecialOpcode.CGE_UN_R8, + [MintOpcode.MINT_BLE_R8]: MintOpcode.MINT_CLE_R8, + [MintOpcode.MINT_BLE_UN_R8]: JiterpSpecialOpcode.CLE_UN_R8, }; export const mathIntrinsicTable: { [opcode: number]: [isUnary: boolean, isF32: boolean, opcodeOrFuncName: WasmOpcode | string] } = { diff --git a/src/mono/browser/runtime/jiterpreter-trace-generator.ts b/src/mono/browser/runtime/jiterpreter-trace-generator.ts index e81c9b6683cbc..dab0be4b2abed 100644 --- a/src/mono/browser/runtime/jiterpreter-trace-generator.ts +++ b/src/mono/browser/runtime/jiterpreter-trace-generator.ts @@ -218,7 +218,6 @@ 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. @@ -506,21 +505,15 @@ 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 { @@ -1293,7 +1286,6 @@ 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; @@ -2743,10 +2735,9 @@ function emit_unop (builder: WasmBuilder, ip: MintOpcodePtr, opcode: MintOpcode) function append_call_handler_store_ret_ip ( builder: WasmBuilder, ip: MintOpcodePtr, - frame: NativePointer, opcode: MintOpcode + frame: NativePointer ) { - const shortOffset = (opcode === MintOpcode.MINT_CALL_HANDLER_S), - retIp = shortOffset ? ip + (3 * 2) : ip + (4 * 2), + const retIp = ip + (4 * 2), clauseIndex = getU16(retIp - 2), clauseDataOffset = get_imethod_clause_data_offset(frame, clauseIndex); @@ -2773,11 +2764,8 @@ function getBranchDisplacement ( case MintOpArgType.MintOpBranch: result = getI32_unaligned(payloadAddress); break; - case MintOpArgType.MintOpShortBranch: - result = getI16(payloadAddress); - break; - case MintOpArgType.MintOpShortAndShortBranch: - result = getI16(payloadAddress + 2); + case MintOpArgType.MintOpShortAndBranch: + result = getI32_unaligned(payloadAddress + 2); break; default: return undefined; @@ -2808,11 +2796,8 @@ function emit_branch ( // branch target (if possible), bailing out at the end otherwise switch (opcode) { case 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); + case MintOpcode.MINT_BR: { + const isCallHandler = opcode === MintOpcode.MINT_CALL_HANDLER; const destination = ip + (displacement * 2); @@ -2824,7 +2809,7 @@ function emit_branch ( if (builder.backBranchTraceLevel > 1) mono_log_info(`0x${(ip).toString(16)} performing backward branch to 0x${destination.toString(16)}`); if (isCallHandler) - append_call_handler_store_ret_ip(builder, ip, frame, opcode); + append_call_handler_store_ret_ip(builder, ip, frame); builder.cfg.branch(destination, true, CfgBranchType.Unconditional); modifyCounter(JiterpCounter.BackBranchesEmitted, 1); return true; @@ -2849,32 +2834,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, opcode); + append_call_handler_store_ret_ip(builder, ip, frame); builder.cfg.branch(destination, false, CfgBranchType.Unconditional); return true; } } - case MintOpcode.MINT_BRTRUE_I4_S: - case MintOpcode.MINT_BRFALSE_I4_S: + case MintOpcode.MINT_BRTRUE_I4: + case MintOpcode.MINT_BRFALSE_I4: case MintOpcode.MINT_BRTRUE_I4_SP: case MintOpcode.MINT_BRFALSE_I4_SP: - 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); + case MintOpcode.MINT_BRTRUE_I8: + case MintOpcode.MINT_BRFALSE_I8: { + const is64 = (opcode === MintOpcode.MINT_BRTRUE_I8) || + (opcode === MintOpcode.MINT_BRFALSE_I8); // Load the condition append_ldloc(builder, getArgU16(ip, 1), is64 ? WasmOpcode.i64_load : WasmOpcode.i32_load); if ( - (opcode === MintOpcode.MINT_BRFALSE_I4_S) || + (opcode === MintOpcode.MINT_BRFALSE_I4) || (opcode === MintOpcode.MINT_BRFALSE_I4_SP) ) builder.appendU8(WasmOpcode.i32_eqz); - else if (opcode === MintOpcode.MINT_BRFALSE_I8_S) { + else if (opcode === MintOpcode.MINT_BRFALSE_I8) { builder.appendU8(WasmOpcode.i64_eqz); - } else if (opcode === MintOpcode.MINT_BRTRUE_I8_S) { + } else if (opcode === MintOpcode.MINT_BRTRUE_I8) { // do (i64 == 0) == 0 because br_if can only branch on an i32 operand builder.appendU8(WasmOpcode.i64_eqz); builder.appendU8(WasmOpcode.i32_eqz); diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 61e1ff55d2f9b..cb951d6206a6c 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -4474,12 +4474,6 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause #define BACK_BRANCH_PROFILE(offset) #endif - MINT_IN_CASE(MINT_BR_S) { - short br_offset = (short) *(ip + 1); - BACK_BRANCH_PROFILE (br_offset); - ip += br_offset; - MINT_IN_BREAK; - } MINT_IN_CASE(MINT_BR) { gint32 br_offset = (gint32) READ32(ip + 1); BACK_BRANCH_PROFILE (br_offset); @@ -4487,14 +4481,6 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause MINT_IN_BREAK; } -#define ZEROP_S(datatype, op) \ - if (LOCAL_VAR (ip [1], datatype) op 0) { \ - gint16 br_offset = (gint16) ip [2]; \ - BACK_BRANCH_PROFILE (br_offset); \ - ip += br_offset; \ - } else \ - ip += 3; - #define ZEROP(datatype, op) \ if (LOCAL_VAR (ip [1], datatype) op 0) { \ gint32 br_offset = (gint32)READ32(ip + 2); \ @@ -4503,39 +4489,18 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause } else \ ip += 4; - MINT_IN_CASE(MINT_BRFALSE_I4_S) - ZEROP_S(gint32, ==); - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BRFALSE_I8_S) - ZEROP_S(gint64, ==); - MINT_IN_BREAK; MINT_IN_CASE(MINT_BRFALSE_I4) ZEROP(gint32, ==); MINT_IN_BREAK; MINT_IN_CASE(MINT_BRFALSE_I8) ZEROP(gint64, ==); MINT_IN_BREAK; - MINT_IN_CASE(MINT_BRTRUE_I4_S) - ZEROP_S(gint32, !=); - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BRTRUE_I8_S) - ZEROP_S(gint64, !=); - MINT_IN_BREAK; MINT_IN_CASE(MINT_BRTRUE_I4) ZEROP(gint32, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_BRTRUE_I8) ZEROP(gint64, !=); MINT_IN_BREAK; -#define CONDBR_S(cond) \ - if (cond) { \ - gint16 br_offset = (gint16) ip [3]; \ - BACK_BRANCH_PROFILE (br_offset); \ - ip += br_offset; \ - } else \ - ip += 4; -#define BRELOP_S(datatype, op) \ - CONDBR_S(LOCAL_VAR (ip [1], datatype) op LOCAL_VAR (ip [2], datatype)) #define CONDBR(cond) \ if (cond) { \ @@ -4548,24 +4513,6 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause #define BRELOP(datatype, op) \ CONDBR(LOCAL_VAR (ip [1], datatype) op LOCAL_VAR (ip [2], datatype)) - MINT_IN_CASE(MINT_BEQ_I4_S) - BRELOP_S(gint32, ==) - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BEQ_I8_S) - BRELOP_S(gint64, ==) - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BEQ_R4_S) { - float f1 = LOCAL_VAR (ip [1], float); - float f2 = LOCAL_VAR (ip [2], float); - CONDBR_S(!isunordered (f1, f2) && f1 == f2) - MINT_IN_BREAK; - } - MINT_IN_CASE(MINT_BEQ_R8_S) { - double d1 = LOCAL_VAR (ip [1], double); - double d2 = LOCAL_VAR (ip [2], double); - CONDBR_S(!mono_isunordered (d1, d2) && d1 == d2) - MINT_IN_BREAK; - } MINT_IN_CASE(MINT_BEQ_I4) BRELOP(gint32, ==) MINT_IN_BREAK; @@ -4584,24 +4531,6 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause CONDBR(!mono_isunordered (d1, d2) && d1 == d2) MINT_IN_BREAK; } - MINT_IN_CASE(MINT_BGE_I4_S) - BRELOP_S(gint32, >=) - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BGE_I8_S) - BRELOP_S(gint64, >=) - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BGE_R4_S) { - float f1 = LOCAL_VAR (ip [1], float); - float f2 = LOCAL_VAR (ip [2], float); - CONDBR_S(!isunordered (f1, f2) && f1 >= f2) - MINT_IN_BREAK; - } - MINT_IN_CASE(MINT_BGE_R8_S) { - double d1 = LOCAL_VAR (ip [1], double); - double d2 = LOCAL_VAR (ip [2], double); - CONDBR_S(!mono_isunordered (d1, d2) && d1 >= d2) - MINT_IN_BREAK; - } MINT_IN_CASE(MINT_BGE_I4) BRELOP(gint32, >=) MINT_IN_BREAK; @@ -4620,24 +4549,6 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause CONDBR(!mono_isunordered (d1, d2) && d1 >= d2) MINT_IN_BREAK; } - MINT_IN_CASE(MINT_BGT_I4_S) - BRELOP_S(gint32, >) - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BGT_I8_S) - BRELOP_S(gint64, >) - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BGT_R4_S) { - float f1 = LOCAL_VAR (ip [1], float); - float f2 = LOCAL_VAR (ip [2], float); - CONDBR_S(!isunordered (f1, f2) && f1 > f2) - MINT_IN_BREAK; - } - MINT_IN_CASE(MINT_BGT_R8_S) { - double d1 = LOCAL_VAR (ip [1], double); - double d2 = LOCAL_VAR (ip [2], double); - CONDBR_S(!mono_isunordered (d1, d2) && d1 > d2) - MINT_IN_BREAK; - } MINT_IN_CASE(MINT_BGT_I4) BRELOP(gint32, >) MINT_IN_BREAK; @@ -4656,24 +4567,6 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause CONDBR(!mono_isunordered (d1, d2) && d1 > d2) MINT_IN_BREAK; } - MINT_IN_CASE(MINT_BLT_I4_S) - BRELOP_S(gint32, <) - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BLT_I8_S) - BRELOP_S(gint64, <) - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BLT_R4_S) { - float f1 = LOCAL_VAR (ip [1], float); - float f2 = LOCAL_VAR (ip [2], float); - CONDBR_S(!isunordered (f1, f2) && f1 < f2) - MINT_IN_BREAK; - } - MINT_IN_CASE(MINT_BLT_R8_S) { - double d1 = LOCAL_VAR (ip [1], double); - double d2 = LOCAL_VAR (ip [2], double); - CONDBR_S(!mono_isunordered (d1, d2) && d1 < d2) - MINT_IN_BREAK; - } MINT_IN_CASE(MINT_BLT_I4) BRELOP(gint32, <) MINT_IN_BREAK; @@ -4692,24 +4585,6 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause CONDBR(!mono_isunordered (d1, d2) && d1 < d2) MINT_IN_BREAK; } - MINT_IN_CASE(MINT_BLE_I4_S) - BRELOP_S(gint32, <=) - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BLE_I8_S) - BRELOP_S(gint64, <=) - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BLE_R4_S) { - float f1 = LOCAL_VAR (ip [1], float); - float f2 = LOCAL_VAR (ip [2], float); - CONDBR_S(!isunordered (f1, f2) && f1 <= f2) - MINT_IN_BREAK; - } - MINT_IN_CASE(MINT_BLE_R8_S) { - double d1 = LOCAL_VAR (ip [1], double); - double d2 = LOCAL_VAR (ip [2], double); - CONDBR_S(!mono_isunordered (d1, d2) && d1 <= d2) - MINT_IN_BREAK; - } MINT_IN_CASE(MINT_BLE_I4) BRELOP(gint32, <=) MINT_IN_BREAK; @@ -4728,24 +4603,6 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause CONDBR(!mono_isunordered (d1, d2) && d1 <= d2) MINT_IN_BREAK; } - MINT_IN_CASE(MINT_BNE_UN_I4_S) - BRELOP_S(gint32, !=) - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BNE_UN_I8_S) - BRELOP_S(gint64, !=) - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BNE_UN_R4_S) { - float f1 = LOCAL_VAR (ip [1], float); - float f2 = LOCAL_VAR (ip [2], float); - CONDBR_S(isunordered (f1, f2) || f1 != f2) - MINT_IN_BREAK; - } - MINT_IN_CASE(MINT_BNE_UN_R8_S) { - double d1 = LOCAL_VAR (ip [1], double); - double d2 = LOCAL_VAR (ip [2], double); - CONDBR_S(mono_isunordered (d1, d2) || d1 != d2) - MINT_IN_BREAK; - } MINT_IN_CASE(MINT_BNE_UN_I4) BRELOP(gint32, !=) MINT_IN_BREAK; @@ -4765,14 +4622,6 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause MINT_IN_BREAK; } -#define BRELOP_S_CAST(datatype, op) \ - if (LOCAL_VAR (ip [1], datatype) op LOCAL_VAR (ip [2], datatype)) { \ - gint16 br_offset = (gint16) ip [3]; \ - BACK_BRANCH_PROFILE (br_offset); \ - ip += br_offset; \ - } else \ - ip += 4; - #define BRELOP_CAST(datatype, op) \ if (LOCAL_VAR (ip [1], datatype) op LOCAL_VAR (ip [2], datatype)) { \ gint32 br_offset = (gint32)READ32(ip + 3); \ @@ -4781,24 +4630,6 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause } else \ ip += 5; - MINT_IN_CASE(MINT_BGE_UN_I4_S) - BRELOP_S_CAST(guint32, >=); - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BGE_UN_I8_S) - BRELOP_S_CAST(guint64, >=); - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BGE_UN_R4_S) { - float f1 = LOCAL_VAR (ip [1], float); - float f2 = LOCAL_VAR (ip [2], float); - CONDBR_S(isunordered (f1, f2) || f1 >= f2) - MINT_IN_BREAK; - } - MINT_IN_CASE(MINT_BGE_UN_R8_S) { - double d1 = LOCAL_VAR (ip [1], double); - double d2 = LOCAL_VAR (ip [2], double); - CONDBR_S(mono_isunordered (d1, d2) || d1 >= d2) - MINT_IN_BREAK; - } MINT_IN_CASE(MINT_BGE_UN_I4) BRELOP_CAST(guint32, >=); MINT_IN_BREAK; @@ -4817,24 +4648,6 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause CONDBR(mono_isunordered (d1, d2) || d1 >= d2) MINT_IN_BREAK; } - MINT_IN_CASE(MINT_BGT_UN_I4_S) - BRELOP_S_CAST(guint32, >); - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BGT_UN_I8_S) - BRELOP_S_CAST(guint64, >); - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BGT_UN_R4_S) { - float f1 = LOCAL_VAR (ip [1], float); - float f2 = LOCAL_VAR (ip [2], float); - CONDBR_S(isunordered (f1, f2) || f1 > f2) - MINT_IN_BREAK; - } - MINT_IN_CASE(MINT_BGT_UN_R8_S) { - double d1 = LOCAL_VAR (ip [1], double); - double d2 = LOCAL_VAR (ip [2], double); - CONDBR_S(mono_isunordered (d1, d2) || d1 > d2) - MINT_IN_BREAK; - } MINT_IN_CASE(MINT_BGT_UN_I4) BRELOP_CAST(guint32, >); MINT_IN_BREAK; @@ -4853,24 +4666,6 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause CONDBR(mono_isunordered (d1, d2) || d1 > d2) MINT_IN_BREAK; } - MINT_IN_CASE(MINT_BLE_UN_I4_S) - BRELOP_S_CAST(guint32, <=); - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BLE_UN_I8_S) - BRELOP_S_CAST(guint64, <=); - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BLE_UN_R4_S) { - float f1 = LOCAL_VAR (ip [1], float); - float f2 = LOCAL_VAR (ip [2], float); - CONDBR_S(isunordered (f1, f2) || f1 <= f2) - MINT_IN_BREAK; - } - MINT_IN_CASE(MINT_BLE_UN_R8_S) { - double d1 = LOCAL_VAR (ip [1], double); - double d2 = LOCAL_VAR (ip [2], double); - CONDBR_S(mono_isunordered (d1, d2) || d1 <= d2) - MINT_IN_BREAK; - } MINT_IN_CASE(MINT_BLE_UN_I4) BRELOP_CAST(guint32, <=); MINT_IN_BREAK; @@ -4889,24 +4684,6 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause CONDBR(mono_isunordered (d1, d2) || d1 <= d2) MINT_IN_BREAK; } - MINT_IN_CASE(MINT_BLT_UN_I4_S) - BRELOP_S_CAST(guint32, <); - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BLT_UN_I8_S) - BRELOP_S_CAST(guint64, <); - MINT_IN_BREAK; - MINT_IN_CASE(MINT_BLT_UN_R4_S) { - float f1 = LOCAL_VAR (ip [1], float); - float f2 = LOCAL_VAR (ip [2], float); - CONDBR_S(isunordered (f1, f2) || f1 < f2) - MINT_IN_BREAK; - } - MINT_IN_CASE(MINT_BLT_UN_R8_S) { - double d1 = LOCAL_VAR (ip [1], double); - double d2 = LOCAL_VAR (ip [2], double); - CONDBR_S(mono_isunordered (d1, d2) || d1 < d2) - MINT_IN_BREAK; - } MINT_IN_CASE(MINT_BLT_UN_I4) BRELOP_CAST(guint32, <); MINT_IN_BREAK; @@ -4928,12 +4705,12 @@ mono_interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClause #define ZEROP_SP(datatype, op) \ if (LOCAL_VAR (ip [1], datatype) op 0) { \ - gint16 br_offset = (gint16) ip [2]; \ + gint32 br_offset = (gint32)READ32(ip + 2); \ BACK_BRANCH_PROFILE (br_offset); \ SAFEPOINT; \ ip += br_offset; \ } else \ - ip += 3; + ip += 4; MINT_IN_CASE(MINT_BRFALSE_I4_SP) ZEROP_SP(gint32, ==); MINT_IN_BREAK; MINT_IN_CASE(MINT_BRFALSE_I8_SP) ZEROP_SP(gint64, ==); MINT_IN_BREAK; @@ -4942,12 +4719,12 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; #define CONDBR_SP(cond) \ if (cond) { \ - gint16 br_offset = (gint16) ip [3]; \ + gint32 br_offset = (gint32)READ32(ip + 3); \ BACK_BRANCH_PROFILE (br_offset); \ SAFEPOINT; \ ip += br_offset; \ } else \ - ip += 4; + ip += 5; #define BRELOP_SP(datatype, op) \ CONDBR_SP(LOCAL_VAR (ip [1], datatype) op LOCAL_VAR (ip [2], datatype)) @@ -7128,31 +6905,25 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; ip = ret_ip; MINT_IN_BREAK; } - MINT_IN_CASE(MINT_CALL_HANDLER) - MINT_IN_CASE(MINT_CALL_HANDLER_S) { - gboolean short_offset = *ip == MINT_CALL_HANDLER_S; - const guint16 *ret_ip = short_offset ? (ip + 3) : (ip + 4); + MINT_IN_CASE(MINT_CALL_HANDLER) { + const guint16 *ret_ip = ip + 4; guint16 clause_index = *(ret_ip - 1); *(const guint16**)(locals + frame->imethod->clause_data_offsets [clause_index]) = ret_ip; // jump to clause - ip += short_offset ? (gint16)*(ip + 1) : (gint32)READ32 (ip + 1); + ip += (gint32)READ32 (ip + 1); MINT_IN_BREAK; } - MINT_IN_CASE(MINT_LEAVE_CHECK) - MINT_IN_CASE(MINT_LEAVE_S_CHECK) { - int leave_opcode = *ip; - + MINT_IN_CASE(MINT_LEAVE_CHECK) { if (frame->imethod->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE) { MonoException *abort_exc = mono_interp_leave (frame); if (abort_exc) THROW_EX (abort_exc, ip); } - gboolean const short_offset = leave_opcode == MINT_LEAVE_S_CHECK; - ip += short_offset ? (gint16)*(ip + 1) : (gint32)READ32 (ip + 1); + ip += (gint32)READ32 (ip + 1); MINT_IN_BREAK; } MINT_IN_CASE(MINT_ICALL) { diff --git a/src/mono/mono/mini/interp/jiterpreter-opcode-values.h b/src/mono/mono/mini/interp/jiterpreter-opcode-values.h index c3926ccb4c479..3c0abb17c08a9 100644 --- a/src/mono/mono/mini/interp/jiterpreter-opcode-values.h +++ b/src/mono/mono/mini/interp/jiterpreter-opcode-values.h @@ -25,8 +25,8 @@ // // Put ranges first so we can override individual opcodes after // -OPRANGE(MINT_BR, MINT_BR_S, BEGIN_BRANCH_BLOCK) -OPRANGE(MINT_CALL_HANDLER, MINT_CALL_HANDLER_S, BEGIN_BRANCH_BLOCK) +OP(MINT_BR, BEGIN_BRANCH_BLOCK) +OP(MINT_CALL_HANDLER, BEGIN_BRANCH_BLOCK) OPRANGE(MINT_BRFALSE_I4, MINT_BLT_UN_I8_IMM_SP, BEGIN_BRANCH_BLOCK) OPRANGE(MINT_CALL, MINT_CALLI_NAT_FAST, ABORT_OUTSIDE_BRANCH_BLOCK_NONE) @@ -85,7 +85,6 @@ OP(MINT_SDB_SEQ_POINT, NONE) // These are only generated inside catch clauses, so it's safe to assume that // during normal execution they won't run, and compile them as a bailout. OP(MINT_LEAVE_CHECK, NONE) -OP(MINT_LEAVE_S_CHECK, NONE) OP(MINT_CKNULL, NORMAL) OP(MINT_LDLOCA_S, NORMAL) diff --git a/src/mono/mono/mini/interp/jiterpreter.c b/src/mono/mono/mini/interp/jiterpreter.c index 43b71e70cd3d5..f3891f4b0eb9b 100644 --- a/src/mono/mono/mini/interp/jiterpreter.c +++ b/src/mono/mono/mini/interp/jiterpreter.c @@ -636,9 +636,7 @@ jiterp_get_opcode_value (InterpInst *ins, gboolean *inside_branch_block) // operations please put them in the values table header // Please keep this in sync with jiterpreter.ts:generate_wasm_body case MINT_BR: - case MINT_BR_S: case MINT_CALL_HANDLER: - case MINT_CALL_HANDLER_S: // Detect backwards branches if (ins->info.target_bb->il_offset <= ins->il_offset) { if (*inside_branch_block) diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index 7edb4f53e3fb7..eca8c5727665f 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -179,11 +179,8 @@ OPDEF(MINT_STIND_OFFSET_IMM_I4, "stind_off_imm.i4", 4, 0, 2, MintOpShortInt) OPDEF(MINT_STIND_OFFSET_IMM_I8, "stind_off_imm.i8", 4, 0, 2, MintOpShortInt) OPDEF(MINT_BR, "br", 3, 0, 0, MintOpBranch) -OPDEF(MINT_BR_S, "br.s", 2, 0, 0, MintOpShortBranch) OPDEF(MINT_LEAVE_CHECK, "leave.check", 3, 0, 0, MintOpBranch) -OPDEF(MINT_LEAVE_S_CHECK, "leave.s.check", 2, 0, 0, MintOpShortBranch) OPDEF(MINT_CALL_HANDLER, "call_handler", 4, 0, 0, MintOpBranch) -OPDEF(MINT_CALL_HANDLER_S, "call_handler.s", 3, 0, 0, MintOpShortBranch) OPDEF(MINT_THROW, "throw", 2, 0, 1, MintOpNoArgs) OPDEF(MINT_RETHROW, "rethrow", 2, 0, 0, MintOpUShortInt) @@ -197,11 +194,6 @@ OPDEF(MINT_BRFALSE_I8, "brfalse.i8", 4, 0, 1, MintOpBranch) OPDEF(MINT_BRTRUE_I4, "brtrue.i4", 4, 0, 1, MintOpBranch) OPDEF(MINT_BRTRUE_I8, "brtrue.i8", 4, 0, 1, MintOpBranch) -OPDEF(MINT_BRFALSE_I4_S, "brfalse.i4.s", 3, 0, 1, MintOpShortBranch) -OPDEF(MINT_BRFALSE_I8_S, "brfalse.i8.s", 3, 0, 1, MintOpShortBranch) -OPDEF(MINT_BRTRUE_I4_S, "brtrue.i4.s", 3, 0, 1, MintOpShortBranch) -OPDEF(MINT_BRTRUE_I8_S, "brtrue.i8.s", 3, 0, 1, MintOpShortBranch) - OPDEF(MINT_BEQ_I4, "beq.i4", 5, 0, 2, MintOpBranch) OPDEF(MINT_BEQ_I8, "beq.i8", 5, 0, 2, MintOpBranch) OPDEF(MINT_BEQ_R4, "beq.r4", 5, 0, 2, MintOpBranch) @@ -244,96 +236,54 @@ OPDEF(MINT_BLT_UN_I8, "blt.un.i8", 5, 0, 2, MintOpBranch) OPDEF(MINT_BLT_UN_R4, "blt.un.r4", 5, 0, 2, MintOpBranch) OPDEF(MINT_BLT_UN_R8, "blt.un.r8", 5, 0, 2, MintOpBranch) -OPDEF(MINT_BEQ_I4_S, "beq.i4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BEQ_I8_S, "beq.i8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BEQ_R4_S, "beq.r4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BEQ_R8_S, "beq.r8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGE_I4_S, "bge.i4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGE_I8_S, "bge.i8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGE_R4_S, "bge.r4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGE_R8_S, "bge.r8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGT_I4_S, "bgt.i4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGT_I8_S, "bgt.i8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGT_R4_S, "bgt.r4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGT_R8_S, "bgt.r8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLT_I4_S, "blt.i4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLT_I8_S, "blt.i8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLT_R4_S, "blt.r4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLT_R8_S, "blt.r8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLE_I4_S, "ble.i4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLE_I8_S, "ble.i8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLE_R4_S, "ble.r4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLE_R8_S, "ble.r8.s", 4, 0, 2, MintOpShortBranch) - -OPDEF(MINT_BNE_UN_I4_S, "bne.un.i4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BNE_UN_I8_S, "bne.un.i8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BNE_UN_R4_S, "bne.un.r4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BNE_UN_R8_S, "bne.un.r8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGE_UN_I4_S, "bge.un.i4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGE_UN_I8_S, "bge.un.i8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGE_UN_R4_S, "bge.un.r4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGE_UN_R8_S, "bge.un.r8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGT_UN_I4_S, "bgt.un.i4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGT_UN_I8_S, "bgt.un.i8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGT_UN_R4_S, "bgt.un.r4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGT_UN_R8_S, "bgt.un.r8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLE_UN_I4_S, "ble.un.i4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLE_UN_I8_S, "ble.un.i8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLE_UN_R4_S, "ble.un.r4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLE_UN_R8_S, "ble.un.r8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLT_UN_I4_S, "blt.un.i4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLT_UN_I8_S, "blt.un.i8.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLT_UN_R4_S, "blt.un.r4.s", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLT_UN_R8_S, "blt.un.r8.s", 4, 0, 2, MintOpShortBranch) - -OPDEF(MINT_BRFALSE_I4_SP, "brfalse.i4.sp", 3, 0, 1, MintOpShortBranch) -OPDEF(MINT_BRFALSE_I8_SP, "brfalse.i8.sp", 3, 0, 1, MintOpShortBranch) -OPDEF(MINT_BRTRUE_I4_SP, "brtrue.i4.sp", 3, 0, 1, MintOpShortBranch) -OPDEF(MINT_BRTRUE_I8_SP, "brtrue.i8.sp", 3, 0, 1, MintOpShortBranch) - -OPDEF(MINT_BEQ_I4_SP, "beq.i4.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BEQ_I8_SP, "beq.i8.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGE_I4_SP, "bge.i4.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGE_I8_SP, "bge.i8.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGT_I4_SP, "bgt.i4.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGT_I8_SP, "bgt.i8.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLT_I4_SP, "blt.i4.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLT_I8_SP, "blt.i8.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLE_I4_SP, "ble.i4.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLE_I8_SP, "ble.i8.sp", 4, 0, 2, MintOpShortBranch) - -OPDEF(MINT_BNE_UN_I4_SP, "bne.un.i4.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BNE_UN_I8_SP, "bne.un.i8.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGE_UN_I4_SP, "bge.un.i4.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGE_UN_I8_SP, "bge.un.i8.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGT_UN_I4_SP, "bgt.un.i4.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BGT_UN_I8_SP, "bgt.un.i8.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLE_UN_I4_SP, "ble.un.i4.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLE_UN_I8_SP, "ble.un.i8.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLT_UN_I4_SP, "blt.un.i4.sp", 4, 0, 2, MintOpShortBranch) -OPDEF(MINT_BLT_UN_I8_SP, "blt.un.i8.sp", 4, 0, 2, MintOpShortBranch) - -OPDEF(MINT_BEQ_I4_IMM_SP, "beq.i4.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BEQ_I8_IMM_SP, "beq.i8.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BGE_I4_IMM_SP, "bge.i4.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BGE_I8_IMM_SP, "bge.i8.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BGT_I4_IMM_SP, "bgt.i4.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BGT_I8_IMM_SP, "bgt.i8.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BLT_I4_IMM_SP, "blt.i4.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BLT_I8_IMM_SP, "blt.i8.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BLE_I4_IMM_SP, "ble.i4.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BLE_I8_IMM_SP, "ble.i8.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) - -OPDEF(MINT_BNE_UN_I4_IMM_SP, "bne.un.i4.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BNE_UN_I8_IMM_SP, "bne.un.i8.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BGE_UN_I4_IMM_SP, "bge.un.i4.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BGE_UN_I8_IMM_SP, "bge.un.i8.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BGT_UN_I4_IMM_SP, "bgt.un.i4.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BGT_UN_I8_IMM_SP, "bgt.un.i8.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BLE_UN_I4_IMM_SP, "ble.un.i4.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BLE_UN_I8_IMM_SP, "ble.un.i8.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BLT_UN_I4_IMM_SP, "blt.un.i4.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) -OPDEF(MINT_BLT_UN_I8_IMM_SP, "blt.un.i8.imm.sp", 4, 0, 1, MintOpShortAndShortBranch) +OPDEF(MINT_BRFALSE_I4_SP, "brfalse.i4.sp", 4, 0, 1, MintOpBranch) +OPDEF(MINT_BRFALSE_I8_SP, "brfalse.i8.sp", 4, 0, 1, MintOpBranch) +OPDEF(MINT_BRTRUE_I4_SP, "brtrue.i4.sp", 4, 0, 1, MintOpBranch) +OPDEF(MINT_BRTRUE_I8_SP, "brtrue.i8.sp", 4, 0, 1, MintOpBranch) + +OPDEF(MINT_BEQ_I4_SP, "beq.i4.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BEQ_I8_SP, "beq.i8.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BGE_I4_SP, "bge.i4.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BGE_I8_SP, "bge.i8.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BGT_I4_SP, "bgt.i4.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BGT_I8_SP, "bgt.i8.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BLT_I4_SP, "blt.i4.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BLT_I8_SP, "blt.i8.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BLE_I4_SP, "ble.i4.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BLE_I8_SP, "ble.i8.sp", 5, 0, 2, MintOpBranch) + +OPDEF(MINT_BNE_UN_I4_SP, "bne.un.i4.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BNE_UN_I8_SP, "bne.un.i8.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BGE_UN_I4_SP, "bge.un.i4.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BGE_UN_I8_SP, "bge.un.i8.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BGT_UN_I4_SP, "bgt.un.i4.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BGT_UN_I8_SP, "bgt.un.i8.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BLE_UN_I4_SP, "ble.un.i4.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BLE_UN_I8_SP, "ble.un.i8.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BLT_UN_I4_SP, "blt.un.i4.sp", 5, 0, 2, MintOpBranch) +OPDEF(MINT_BLT_UN_I8_SP, "blt.un.i8.sp", 5, 0, 2, MintOpBranch) + +OPDEF(MINT_BEQ_I4_IMM_SP, "beq.i4.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BEQ_I8_IMM_SP, "beq.i8.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BGE_I4_IMM_SP, "bge.i4.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BGE_I8_IMM_SP, "bge.i8.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BGT_I4_IMM_SP, "bgt.i4.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BGT_I8_IMM_SP, "bgt.i8.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BLT_I4_IMM_SP, "blt.i4.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BLT_I8_IMM_SP, "blt.i8.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BLE_I4_IMM_SP, "ble.i4.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BLE_I8_IMM_SP, "ble.i8.imm.sp", 5, 0, 1, MintOpShortAndBranch) + +OPDEF(MINT_BNE_UN_I4_IMM_SP, "bne.un.i4.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BNE_UN_I8_IMM_SP, "bne.un.i8.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BGE_UN_I4_IMM_SP, "bge.un.i4.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BGE_UN_I8_IMM_SP, "bge.un.i8.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BGT_UN_I4_IMM_SP, "bgt.un.i4.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BGT_UN_I8_IMM_SP, "bgt.un.i8.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BLE_UN_I4_IMM_SP, "ble.un.i4.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BLE_UN_I8_IMM_SP, "ble.un.i8.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BLT_UN_I4_IMM_SP, "blt.un.i4.imm.sp", 5, 0, 1, MintOpShortAndBranch) +OPDEF(MINT_BLT_UN_I8_IMM_SP, "blt.un.i8.imm.sp", 5, 0, 1, MintOpShortAndBranch) OPDEF(MINT_SWITCH, "switch", 0, 0, 1, MintOpSwitch) diff --git a/src/mono/mono/mini/interp/mintops.h b/src/mono/mono/mini/interp/mintops.h index 5acc555b3a4ee..e289e60197cd6 100644 --- a/src/mono/mono/mini/interp/mintops.h +++ b/src/mono/mono/mini/interp/mintops.h @@ -19,7 +19,6 @@ typedef enum MintOpFloat, MintOpDouble, MintOpBranch, - MintOpShortBranch, MintOpSwitch, MintOpMethodToken, MintOpFieldToken, @@ -28,7 +27,7 @@ typedef enum MintOpTwoShorts, MintOpTwoInts, MintOpShortAndInt, - MintOpShortAndShortBranch, + MintOpShortAndBranch, MintOpPair2, MintOpPair3, MintOpPair4 @@ -212,10 +211,10 @@ typedef enum { #define MINT_IS_NOP(op) ((op) == MINT_NOP || (op) == MINT_DEF || (op) == MINT_DEF_ARG || (op) == MINT_DUMMY_USE || (op) == MINT_IL_SEQ_POINT) #define MINT_IS_EMIT_NOP(op) ((op) == MINT_NOP || (op) == MINT_DEF || (op) == MINT_DEF_ARG || (op) == MINT_DEF_TIER_VAR || (op) == MINT_DUMMY_USE) #define MINT_IS_MOV(op) ((op) >= MINT_MOV_I4_I1 && (op) <= MINT_MOV_VT) -#define MINT_IS_UNCONDITIONAL_BRANCH(op) ((op) >= MINT_BR && (op) <= MINT_CALL_HANDLER_S) -#define MINT_IS_CONDITIONAL_BRANCH(op) ((op) >= MINT_BRFALSE_I4 && (op) <= MINT_BLT_UN_R8_S) -#define MINT_IS_UNOP_CONDITIONAL_BRANCH(op) ((op) >= MINT_BRFALSE_I4 && (op) <= MINT_BRTRUE_I8_S) -#define MINT_IS_BINOP_CONDITIONAL_BRANCH(op) ((op) >= MINT_BEQ_I4 && (op) <= MINT_BLT_UN_R8_S) +#define MINT_IS_UNCONDITIONAL_BRANCH(op) ((op) >= MINT_BR && (op) <= MINT_CALL_HANDLER) +#define MINT_IS_CONDITIONAL_BRANCH(op) ((op) >= MINT_BRFALSE_I4 && (op) <= MINT_BLT_UN_R8) +#define MINT_IS_UNOP_CONDITIONAL_BRANCH(op) ((op) >= MINT_BRFALSE_I4 && (op) <= MINT_BRTRUE_I8) +#define MINT_IS_BINOP_CONDITIONAL_BRANCH(op) ((op) >= MINT_BEQ_I4 && (op) <= MINT_BLT_UN_R8) #define MINT_IS_COMPARE(op) ((op) >= MINT_CEQ_I4 && (op) <= MINT_CLT_UN_R8) #define MINT_IS_SUPER_BRANCH(op) ((op) >= MINT_BRFALSE_I4_SP && (op) <= MINT_BLT_UN_I8_IMM_SP) #define MINT_IS_CALL(op) ((op) >= MINT_CALL && (op) <= MINT_JIT_CALL) diff --git a/src/mono/mono/mini/interp/transform-opt.c b/src/mono/mono/mini/interp/transform-opt.c index b259e116c1440..7b74e4ac5485e 100644 --- a/src/mono/mono/mini/interp/transform-opt.c +++ b/src/mono/mono/mini/interp/transform-opt.c @@ -3387,15 +3387,12 @@ can_propagate_var_def (TransformData *td, int var, InterpLivenessPosition cur_li static void interp_super_instructions (TransformData *td) { - interp_compute_native_offset_estimates (td, FALSE); - // Add some actual super instructions for (int bb_dfs_index = 0; bb_dfs_index < td->bblocks_count_eh; bb_dfs_index++) { InterpBasicBlock *bb = td->bblocks [bb_dfs_index]; // Set cbb since we do some instruction inserting below td->cbb = bb; - int noe = bb->native_offset_estimate; InterpLivenessPosition current_liveness; current_liveness.bb_dfs_index = bb->dfs_index; current_liveness.ins_index = 0; @@ -3720,7 +3717,7 @@ interp_super_instructions (TransformData *td) interp_clear_ins (def); td->var_values [obj_sreg].ref_count--; } - } else if (MINT_IS_BINOP_CONDITIONAL_BRANCH (opcode) && interp_is_short_offset (noe, ins->info.target_bb->native_offset_estimate)) { + } else if (MINT_IS_BINOP_CONDITIONAL_BRANCH (opcode)) { gint32 imm; int imm_mt; int sreg_imm = ins->sregs [1]; @@ -3757,7 +3754,7 @@ interp_super_instructions (TransformData *td) } } } - } else if (MINT_IS_UNOP_CONDITIONAL_BRANCH (opcode) && interp_is_short_offset (noe, ins->info.target_bb->native_offset_estimate)) { + } else if (MINT_IS_UNOP_CONDITIONAL_BRANCH (opcode)) { if (opcode == MINT_BRFALSE_I4 || opcode == MINT_BRTRUE_I4) { gboolean negate = opcode == MINT_BRFALSE_I4; int cond_sreg = ins->sregs [0]; @@ -3867,7 +3864,6 @@ interp_super_instructions (TransformData *td) } } } - noe += interp_get_ins_length (ins); } } } diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 1af7c2d514b23..a08933678de5b 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -1424,15 +1424,6 @@ interp_dump_ins_data (InterpInst *ins, gint32 ins_offset, const guint16 *data, i g_string_append_printf (str, " %g", * (double *)&tmp); break; } - case MintOpShortBranch: - if (ins) { - /* the target IL is already embedded in the instruction */ - g_string_append_printf (str, " BB%d", ins->info.target_bb->index); - } else { - target = ins_offset + *(gint16*)data; - g_string_append_printf (str, " IR_%04x", target); - } - break; case MintOpBranch: if (ins) { g_string_append_printf (str, " BB%d", ins->info.target_bb->index); @@ -1459,12 +1450,12 @@ interp_dump_ins_data (InterpInst *ins, gint32 ins_offset, const guint16 *data, i g_string_append_printf (str, ")"); break; } - case MintOpShortAndShortBranch: + case MintOpShortAndBranch: if (ins) { /* the target IL is already embedded in the instruction */ g_string_append_printf (str, " %u, BB%d", *(guint16*)data, ins->info.target_bb->index); } else { - target = ins_offset + *(gint16*)(data + 1); + target = ins_offset + (gint32)READ32 (data + 1); g_string_append_printf (str, " %u, IR_%04x", *(guint16*)data, target); } break; @@ -8661,10 +8652,6 @@ handle_relocations (TransformData *td) int offset = reloc->target_bb->native_offset - reloc->offset; switch (reloc->type) { - case RELOC_SHORT_BRANCH: - g_assert (td->new_code [reloc->offset + reloc->skip + 1] == 0xdead); - td->new_code [reloc->offset + reloc->skip + 1] = GINT_TO_UINT16 (offset); - break; case RELOC_LONG_BRANCH: { guint16 *v = (guint16 *)&offset; g_assert (td->new_code [reloc->offset + reloc->skip + 1] == 0xdead); @@ -8751,18 +8738,14 @@ interp_foreach_ins_var (TransformData *td, InterpInst *ins, gpointer data, void } int -interp_compute_native_offset_estimates (TransformData *td, gboolean final_code) +interp_compute_native_offset_estimates (TransformData *td) { InterpBasicBlock *bb; int noe = 0; for (bb = td->entry_bb; bb != NULL; bb = bb->next_bb) { InterpInst *ins; - // FIXME This doesn't currently hold because of bblock reordering potentially - // inserting additional instructions after the estimate is computed. - // - // if (bb->native_offset_estimate) - // g_assert (bb->native_offset_estimate >= noe); + bb->native_offset_estimate = noe; if (!td->optimized && bb->patchpoint_bb) noe += 2; @@ -8782,19 +8765,6 @@ interp_compute_native_offset_estimates (TransformData *td, gboolean final_code) continue; noe += interp_get_ins_length (ins); - if (!final_code && td->optimized && - (ins->flags & INTERP_INST_FLAG_CALL) && - ins->info.call_info && - ins->info.call_info->call_args) { - // When code is optimized, for a call, the offset allocator - // might end up inserting additional moves for the arguments - int *call_args = ins->info.call_info->call_args; - while (*call_args != -1) { - noe += 4; // mono_interp_oplen [MINT_MOV_VT]; - call_args++; - } - } - if (!td->optimized) interp_foreach_ins_var (td, ins, NULL, alloc_unopt_global_local); } @@ -8807,39 +8777,6 @@ interp_compute_native_offset_estimates (TransformData *td, gboolean final_code) return noe; } -gboolean -interp_is_short_offset (int src_offset, int dest_offset) -{ - int diff = dest_offset - src_offset; - if (diff >= G_MININT16 && diff <= G_MAXINT16) - return TRUE; - return FALSE; -} - -static int -get_short_brop (int opcode) -{ - if (MINT_IS_UNCONDITIONAL_BRANCH (opcode)) { - if (opcode == MINT_BR) - return MINT_BR_S; - else if (opcode == MINT_LEAVE_CHECK) - return MINT_LEAVE_S_CHECK; - else if (opcode == MINT_CALL_HANDLER) - return MINT_CALL_HANDLER_S; - else - return opcode; - } - - if (opcode >= MINT_BRFALSE_I4 && opcode <= MINT_BRTRUE_I8) - return opcode + MINT_BRFALSE_I4_S - MINT_BRFALSE_I4; - - if (opcode >= MINT_BEQ_I4 && opcode <= MINT_BLT_UN_R8) - return opcode + MINT_BEQ_I4_S - MINT_BEQ_I4; - - // Already short branch - return opcode; -} - static void interp_mark_ref_slots_for_vt (TransformData *td, int base_offset, MonoClass *klass) { @@ -8995,45 +8932,20 @@ emit_compacted_instruction (TransformData *td, guint16* start_ip, InterpInst *in if (ins->info.target_bb->native_offset >= 0) { int offset = ins->info.target_bb->native_offset - br_offset; - // Backwards branch. We can already patch it. - if (interp_is_short_offset (br_offset, ins->info.target_bb->native_offset)) { - // Replace the long opcode we added at the start - *start_ip = GINT_TO_OPCODE (get_short_brop (opcode)); - *ip++ = GINT_TO_UINT16 (ins->info.target_bb->native_offset - br_offset); - } else { - WRITE32 (ip, &offset); - } + WRITE32 (ip, &offset); } else if (opcode == MINT_BR && ins->info.target_bb == td->cbb->next_bb) { // Ignore branch to the next basic block. Revert the added MINT_BR. ip--; } else { - // If the estimate offset is short, then surely the real offset is short - // otherwise we conservatively have to use long branch opcodes - int cur_estimation_error = td->cbb->native_offset_estimate - td->cbb->native_offset; - int target_bb_estimated_offset = ins->info.target_bb->native_offset_estimate - cur_estimation_error; - gboolean is_short = interp_is_short_offset (br_offset, target_bb_estimated_offset); - if (is_short) - *start_ip = GINT_TO_OPCODE (get_short_brop (opcode)); - else if (MINT_IS_SUPER_BRANCH (opcode)) { - g_printf ( - "long superbranch detected with opcode %d (%s) in method %s.%s\n", - opcode, mono_interp_opname (opcode), - m_class_get_name (td->method->klass), td->method->name - ); - // FIXME missing handling for long branch - g_assert (FALSE); - } - // We don't know the in_offset of the target, add a reloc Reloc *reloc = (Reloc*)mono_mempool_alloc0 (td->mempool, sizeof (Reloc)); - reloc->type = is_short ? RELOC_SHORT_BRANCH : RELOC_LONG_BRANCH; + reloc->type = RELOC_LONG_BRANCH; reloc->skip = mono_interp_op_sregs [opcode] + has_imm; reloc->offset = br_offset; reloc->target_bb = ins->info.target_bb; g_ptr_array_add (td->relocs, reloc); *ip++ = 0xdead; - if (!is_short) - *ip++ = 0xbeef; + *ip++ = 0xbeef; } if (opcode == MINT_CALL_HANDLER) *ip++ = ins->data [2]; @@ -9233,9 +9145,7 @@ generate_compacted_code (InterpMethod *rtm, TransformData *td) td->relocs = g_ptr_array_new (); InterpBasicBlock *bb; - // This iteration could be avoided at the cost of less precise size result, following - // super instruction pass - size = interp_compute_native_offset_estimates (td, TRUE); + size = interp_compute_native_offset_estimates (td); // Generate the compacted stream of instructions td->new_code = ip = (guint16*)imethod_alloc0 (td, size * sizeof (guint16)); diff --git a/src/mono/mono/mini/interp/transform.h b/src/mono/mono/mini/interp/transform.h index 0379cf1682f6a..9432eebf39614 100644 --- a/src/mono/mono/mini/interp/transform.h +++ b/src/mono/mono/mini/interp/transform.h @@ -182,7 +182,6 @@ struct _InterpCallInfo { }; typedef enum { - RELOC_SHORT_BRANCH, RELOC_LONG_BRANCH, RELOC_SWITCH } RelocType; @@ -522,7 +521,7 @@ void interp_link_bblocks (TransformData *td, InterpBasicBlock *from, InterpBasicBlock *to); int -interp_compute_native_offset_estimates (TransformData *td, gboolean final_code); +interp_compute_native_offset_estimates (TransformData *td); void interp_optimize_code (TransformData *td);