[wasm] Fetch interpreter opcode info from the runtime instead of generating a table...
authorKatelyn Gadd <kg@luminance.org>
Mon, 8 May 2023 15:52:55 +0000 (08:52 -0700)
committerGitHub <noreply@github.com>
Mon, 8 May 2023 15:52:55 +0000 (08:52 -0700)
* No longer generate a typescript opcode info table
* Fetch opcode info from the interpreter on-demand

src/mono/mono/mini/interp/interp-internals.h
src/mono/mono/mini/interp/interp.c
src/mono/wasm/runtime/cwraps.ts
src/mono/wasm/runtime/genmintops.py
src/mono/wasm/runtime/jiterpreter-opcodes.ts
src/mono/wasm/runtime/jiterpreter-trace-generator.ts
src/mono/wasm/runtime/jiterpreter.ts

index fb8e9e3..a2af6d6 100644 (file)
@@ -357,6 +357,9 @@ mono_jiterp_get_simd_intrinsic (int arity, int index);
 int
 mono_jiterp_get_simd_opcode (int arity, int index);
 
+int
+mono_jiterp_get_opcode_info (int opcode, int type);
+
 #endif
 
 #endif /* __MONO_MINI_INTERPRETER_INTERNALS_H__ */
index 32b6c4b..2abac1f 100644 (file)
@@ -8554,7 +8554,7 @@ interp_invalidate_transformed (void)
                        mono_internal_hash_table_apply (&jit_mm->interp_code_hash, invalidate_transform, NULL);
                        jit_mm_unlock (jit_mm);
                }
-               
+
                g_ptr_array_free (alcs, TRUE);
        }
 
@@ -8606,7 +8606,7 @@ interp_jit_info_foreach (InterpJitInfoFunc func, gpointer user_data)
                                g_free (copy_jit_info_data.jit_info_array);
                        }
                }
-               
+
                g_ptr_array_free (alcs, TRUE);
        }
 }
@@ -8896,4 +8896,31 @@ mono_jiterp_get_simd_opcode (int arity, int index)
 #endif
 }
 
+#define JITERP_OPINFO_TYPE_NAME 0
+#define JITERP_OPINFO_TYPE_LENGTH 1
+#define JITERP_OPINFO_TYPE_SREGS 2
+#define JITERP_OPINFO_TYPE_DREGS 3
+#define JITERP_OPINFO_TYPE_OPARGTYPE 4
+
+EMSCRIPTEN_KEEPALIVE int
+mono_jiterp_get_opcode_info (int opcode, int type)
+{
+       g_assert ((opcode >= 0) && (opcode <= MINT_LASTOP));
+       switch (type) {
+               case JITERP_OPINFO_TYPE_NAME:
+                       // We know this conversion is safe because wasm pointers are 32 bits
+                       return (int)(void*)(mono_interp_opname (opcode));
+               case JITERP_OPINFO_TYPE_LENGTH:
+                       return mono_interp_oplen [opcode];
+               case JITERP_OPINFO_TYPE_SREGS:
+                       return mono_interp_op_sregs [opcode];
+               case JITERP_OPINFO_TYPE_DREGS:
+                       return mono_interp_op_dregs [opcode];
+               case JITERP_OPINFO_TYPE_OPARGTYPE:
+                       return mono_interp_opargtype [opcode];
+               default:
+                       g_assert_not_reached();
+       }
+}
+
 #endif
index d13d10c..370bac0 100644 (file)
@@ -128,6 +128,7 @@ const fn_signatures: SigLine[] = [
     [true, "mono_jiterp_get_simd_intrinsic", "number", ["number", "number"]],
     [true, "mono_jiterp_get_simd_opcode", "number", ["number", "number"]],
     [true, "mono_jiterp_get_arg_offset", "number", ["number", "number", "number"]],
+    [true, "mono_jiterp_get_opcode_info", "number", ["number", "number"]],
     ...legacy_interop_cwraps
 ];
 
@@ -252,6 +253,7 @@ export interface t_Cwraps {
     mono_jiterp_get_simd_intrinsic(arity: number, index: number): VoidPtr;
     mono_jiterp_get_simd_opcode(arity: number, index: number): number;
     mono_jiterp_get_arg_offset (imethod: number, sig: number, index: number): number;
+    mono_jiterp_get_opcode_info(opcode: number, type: number): number;
 }
 
 const wrapped_c_functions: t_Cwraps = <any>{};
index de7f6e5..604c870 100755 (executable)
@@ -32,9 +32,6 @@ opdef_regex = r'\s(IR)?OPDEF\((\w+),\s*(.+?),\s*(MintOp\w+)\)'
 enum_values = re.sub(
     opdef_regex, lambda m : f"{m.group(2)},", header
 )
-metadata_table = re.sub(
-    opdef_regex, lambda m : f"[MintOpcode.{m.group(2)}]: [{m.group(3)}, MintOpArgType.{m.group(4)}],", header
-)
 
 simd_values_1 = []
 simd_values_2 = []
@@ -65,7 +62,7 @@ generated = f"""
 // Generated by genmintops.py from mintops.def.
 // Do not manually edit this file.
 
-import {{ OpcodeInfoTable, MintOpArgType, SimdInfoTable }} from "./jiterpreter-opcodes";
+import {{ MintOpArgType, SimdInfoTable }} from "./jiterpreter-opcodes";
 
 export const enum MintOpcode {{
 {enum_values}
@@ -73,10 +70,6 @@ export const enum MintOpcode {{
     MINT_LASTOP
 }}
 
-export const OpcodeInfo : OpcodeInfoTable = {{
-{metadata_table}
-}};
-
 export const enum SimdIntrinsic2 {{
     {splitter.join(simd_values_1)}
 }}
index 3d347bd..fdc5dd2 100644 (file)
@@ -3,6 +3,9 @@
 
 // Keep this file in sync with mintops.def. The order and values need to match exactly.
 
+import { Module } from "./globals";
+import cwraps from "./cwraps";
+
 export const enum MintOpArgType {
        MintOpNoArgs = 0,
        MintOpShortInt,
@@ -26,8 +29,27 @@ export const enum MintOpArgType {
        MintOpPair4
 }
 
-export type OpcodeInfoTable = {
-    [key: number]: [name: string, length_u16: number, dregs: number, sregs: number, optype: MintOpArgType];
+export const enum OpcodeInfoType {
+    Name = 0,
+    Length,
+    Sregs,
+    Dregs,
+    OpArgType
+}
+
+export type OpcodeNameTable = {
+    [key: number]: string;
+}
+
+const opcodeNameCache : OpcodeNameTable = {};
+
+export function getOpcodeName (opcode: number) : string {
+    let result = opcodeNameCache[opcode];
+    if (typeof (result) !== "string") {
+        const pName = cwraps.mono_jiterp_get_opcode_info(opcode, OpcodeInfoType.Name);
+        opcodeNameCache[opcode] = result = Module.UTF8ToString(<any>pName);
+    }
+    return result;
 }
 
 export type SimdInfoSubtable = Array<string>
index f9e9508..11ec48a 100644 (file)
@@ -8,9 +8,12 @@ import {
     getU16, getI16,
     getU32_unaligned, getI32_unaligned, getF32_unaligned, getF64_unaligned,
 } from "./memory";
-import { WasmOpcode, WasmSimdOpcode } from "./jiterpreter-opcodes";
 import {
-    MintOpcode, OpcodeInfo, SimdInfo,
+    WasmOpcode, WasmSimdOpcode,
+    getOpcodeName, OpcodeInfoType
+} from "./jiterpreter-opcodes";
+import {
+    MintOpcode, SimdInfo,
     SimdIntrinsic2, SimdIntrinsic3, SimdIntrinsic4
 } from "./mintops";
 import cwraps from "./cwraps";
@@ -172,7 +175,8 @@ export function generateWasmBody (
     eraseInferredState();
 
     // Skip over the enter opcode
-    ip += <any>(OpcodeInfo[MintOpcode.MINT_TIER_ENTER_JITERPRETER][1] * 2);
+    const enterSizeU16 = cwraps.mono_jiterp_get_opcode_info(MintOpcode.MINT_TIER_ENTER_JITERPRETER, OpcodeInfoType.Length);
+    ip += <any>(enterSizeU16 * 2);
     let rip = ip;
 
     builder.cfg.entry(ip);
@@ -207,7 +211,10 @@ export function generateWasmBody (
         }
 
         let opcode = getU16(ip);
-        const info = OpcodeInfo[opcode];
+        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);
+
         const isSimdIntrins = (opcode >= MintOpcode.MINT_SIMD_INTRINS_P_P) &&
             (opcode <= MintOpcode.MINT_SIMD_INTRINS_P_PPP);
         const simdIntrinsArgCount = isSimdIntrins
@@ -217,11 +224,11 @@ export function generateWasmBody (
             ? getArgU16(ip, 1 + simdIntrinsArgCount)
             : 0;
 
-        mono_assert(info, () => `invalid opcode ${opcode}`);
+        mono_assert((opcode >= 0) && (opcode < MintOpcode.MINT_LASTOP), () => `invalid opcode ${opcode}`);
 
         const opname = isSimdIntrins
             ? SimdInfo[simdIntrinsArgCount][simdIntrinsIndex]
-            : info[0];
+            : getOpcodeName(opcode);
         const _ip = ip;
         const isBackBranchTarget = builder.options.noExitBackwardBranches &&
             is_backward_branch_target(ip, startOfBody, backwardBranchTable),
@@ -1367,7 +1374,7 @@ export function generateWasmBody (
                 // This should have already happened, but it's possible there are opcodes where
                 //  our invalidation is incorrect so it's best to do this for safety reasons
                 const firstDreg = <any>ip + 2;
-                for (let r = 0; r < info[2]; r++) {
+                for (let r = 0; r < numDregs; r++) {
                     const dreg = getU16(firstDreg + (r * 2));
                     invalidate_local(dreg);
                 }
@@ -1376,18 +1383,18 @@ export function generateWasmBody (
             if ((trace > 1) || traceOnError || traceOnRuntimeError || mostRecentOptions!.dumpTraces || instrumentedTraceId) {
                 let stmtText = `${(<any>ip).toString(16)} ${opname} `;
                 const firstDreg = <any>ip + 2;
-                const firstSreg = firstDreg + (info[2] * 2);
+                const firstSreg = firstDreg + (numDregs * 2);
                 // print sregs
-                for (let r = 0; r < info[3]; r++) {
+                for (let r = 0; r < numSregs; r++) {
                     if (r !== 0)
                         stmtText += ", ";
                     stmtText += getU16(firstSreg + (r * 2));
                 }
 
                 // print dregs
-                if (info[2] > 0)
+                if (numDregs > 0)
                     stmtText += " -> ";
-                for (let r = 0; r < info[2]; r++) {
+                for (let r = 0; r < numDregs; r++) {
                     if (r !== 0)
                         stmtText += ", ";
                     stmtText += getU16(firstDreg + (r * 2));
@@ -1406,7 +1413,7 @@ export function generateWasmBody (
                 // console.log(`JITERP: opcode ${opname} did not abort but had value ${opcodeValue}`);
             }
 
-            ip += <any>(info[1] * 2);
+            ip += <any>(opLengthU16 * 2);
             if (<any>ip <= (<any>endOfBody))
                 rip = ip;
             // For debugging
@@ -2594,7 +2601,6 @@ function emit_branch (
     builder: WasmBuilder, ip: MintOpcodePtr,
     frame: NativePointer, opcode: MintOpcode, displacement?: number
 ) : boolean {
-    const info = OpcodeInfo[opcode];
     const isSafepoint = (opcode >= MintOpcode.MINT_BRFALSE_I4_SP) &&
         (opcode <= MintOpcode.MINT_BLT_UN_I8_IMM_SP);
     eraseInferredState();
@@ -2638,9 +2644,9 @@ function emit_branch (
                 } else {
                     if (destination < builder.cfg.entryIp) {
                         if ((traceBackBranches > 1) || (builder.cfg.trace > 1))
-                            console.log(`${info[0]} target 0x${destination.toString(16)} before start of trace`);
+                            console.log(`${getOpcodeName(opcode)} target 0x${destination.toString(16)} before start of trace`);
                     } else if ((traceBackBranches > 0) || (builder.cfg.trace > 0))
-                        console.log(`0x${(<any>ip).toString(16)} ${info[0]} target 0x${destination.toString(16)} not found in list ` +
+                        console.log(`0x${(<any>ip).toString(16)} ${getOpcodeName(opcode)} target 0x${destination.toString(16)} not found in list ` +
                             builder.backBranchOffsets.map(bbo => "0x" + (<any>bbo).toString(16)).join(", ")
                         );
 
@@ -2696,10 +2702,10 @@ function emit_branch (
             //  so we don't need to load anything. After the condition was loaded, we
             //  treat it like a brtrue
             if (relopbranchTable[opcode] === undefined)
-                throw new Error(`Unsupported relop branch opcode: ${opcode}`);
+                throw new Error(`Unsupported relop branch opcode: ${getOpcodeName(opcode)}`);
 
-            if (info[1] !== 4)
-                throw new Error(`Unsupported long branch opcode: ${info[0]}`);
+            if (cwraps.mono_jiterp_get_opcode_info(opcode, OpcodeInfoType.Length) !== 4)
+                throw new Error(`Unsupported long branch opcode: ${getOpcodeName(opcode)}`);
 
             builder.appendU8(WasmOpcode.i32_eqz);
             break;
@@ -2709,7 +2715,7 @@ function emit_branch (
     if (!displacement)
         throw new Error("Branch had no displacement");
     else if (traceBranchDisplacements)
-        console.log(`${info[0]} @${ip} displacement=${displacement}`);
+        console.log(`${getOpcodeName(opcode)} @${ip} displacement=${displacement}`);
 
     const destination = <any>ip + (displacement * 2);
 
@@ -2732,9 +2738,9 @@ function emit_branch (
         } else {
             if (destination < builder.cfg.entryIp) {
                 if ((traceBackBranches > 1) || (builder.cfg.trace > 1))
-                    console.log(`${info[0]} target 0x${destination.toString(16)} before start of trace`);
+                    console.log(`${getOpcodeName(opcode)} target 0x${destination.toString(16)} before start of trace`);
             } else if ((traceBackBranches > 0) || (builder.cfg.trace > 0))
-                console.log(`0x${(<any>ip).toString(16)} ${info[0]} target 0x${destination.toString(16)} not found in list ` +
+                console.log(`0x${(<any>ip).toString(16)} ${getOpcodeName(opcode)} target 0x${destination.toString(16)} not found in list ` +
                     builder.backBranchOffsets.map(bbo => "0x" + (<any>bbo).toString(16)).join(", ")
                 );
             // We didn't find a loop to branch to, so bail out
index 7c2e66b..2bb9354 100644 (file)
@@ -7,8 +7,8 @@ import { Module, runtimeHelpers } from "./globals";
 import {
     getU16, getU32_unaligned
 } from "./memory";
-import { WasmOpcode } from "./jiterpreter-opcodes";
-import { MintOpcode, OpcodeInfo } from "./mintops";
+import { WasmOpcode, getOpcodeName } from "./jiterpreter-opcodes";
+import { MintOpcode } from "./mintops";
 import cwraps from "./cwraps";
 import {
     MintOpcodePtr, WasmValtype, WasmBuilder, addWasmFunctionPointer,
@@ -980,7 +980,7 @@ export function trace_operands(a: number, b: number) {
 export function record_abort(traceIp: MintOpcodePtr, ip: MintOpcodePtr, traceName: string, reason: string | MintOpcode) {
     if (typeof (reason) === "number") {
         cwraps.mono_jiterp_adjust_abort_count(reason, 1);
-        reason = OpcodeInfo[<any>reason][0];
+        reason = getOpcodeName(reason);
     } else {
         let abortCount = abortCounts[reason];
         if (typeof (abortCount) !== "number")
@@ -1201,7 +1201,7 @@ export function jiterpreter_dump_stats(b?: boolean, concise?: boolean) {
             console.log(`// ${tuples[i][0]}: ${tuples[i][1]}`);
     } else {
         for (let i = 0; i < MintOpcode.MINT_LASTOP; i++) {
-            const opname = OpcodeInfo[<any>i][0];
+            const opname = getOpcodeName(i);
             const count = cwraps.mono_jiterp_adjust_abort_count(i, 0);
             if (count > 0)
                 abortCounts[opname] = count;