Skip to content

Commit 12ecfe7

Browse files
github-actions[bot]lambdageekkgjeffschwMSFT
authored
[release/9.0] [mono][mini] Interlocked.CompareExchange and Interlocked.Exchange intrinsics for small types and enums (#106897)
* [mono][mini][arm64] Interlocked.CompareExchange for byte/sbyte * rewrite cas_i1 with zext cmp and sign ext result * [sample] fixup HelloWorld to work with full aot * [mini][llvm] support OP_ATOMIC_CAS_U1 * [mini][amd64] support OP_ATOMIC_CAS_U1 * [mini][wasm] support OP_ATOMIC_CAS_U1 in LLVM AOT * make intrinsic must-expand on arm64,amd64,wasm on mono * [interp] MINT_MONO_CMPXCHG_U1 also add mono_atomic_cas_u8 utility function * [mini] CompareExchange(i16/u16) * [mono] must expand CompareExchange(i16/u16) * [interp] Interlocked.CompareExchange(u16/i16) * fix gcc intrinsics build * fix amd64 supported ops * [mini] zext unsigned CAS results for small types * [interp] signed small CAS ops * HACK: fix x64 crashes? maybe we can't actually do a 1 or 2 byte move from RAX ? * [amd64] fixup 8- and 16-bit cmpxchg encoding * fix operand order * ok to always emit rex? * Apply suggestions from code review fixup u16 win32 atomic * [interp] remove if guarding a switch * Interlocked.Exchange u1/i1/u2/i2 interp,llvm,amd64,arm64 * fix windows build * [amd64] give u2 CMPXCHG and XCHG one more byte for the 16-bit addressing prefix * If jiterpreter is engaged before the thread is fully initialized, just fail to allocate a table index and generate a warning. This shouldn't happen in prod anyway Implement cmpxchg atomics natively in jiterpreter Remove unnecessary jiterp cas helpers Do cmpxchg result fixups as needed Add runtime option for jiterpreter atomics Implement atomic exchanges in the jiterpreter * Interlocked.Exchange(int) for interp and jiterp --------- Co-authored-by: Aleksey Kliger <alklig@microsoft.com> Co-authored-by: Aleksey Kliger <aleksey@lambdageek.org> Co-authored-by: Katelyn Gadd <kg@luminance.org> Co-authored-by: Jeff Schwartz <jeffschw@microsoft.com>
1 parent e107da8 commit 12ecfe7

24 files changed

+711
-104
lines changed

src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public static short Exchange(ref short location1, short value) =>
8484
[MethodImpl(MethodImplOptions.AggressiveInlining)]
8585
public static unsafe byte Exchange(ref byte location1, byte value)
8686
{
87-
#if !MONO && (TARGET_X86 || TARGET_AMD64 || TARGET_ARM64)
87+
#if (MONO && (TARGET_AMD64 || TARGET_ARM64 || TARGET_WASM)) || (!MONO && (TARGET_X86 || TARGET_AMD64 || TARGET_ARM64))
8888
return Exchange(ref location1, value); // Must expand intrinsic
8989
#else
9090
// this relies on GC keeping 4B alignment for refs and on subtracting to such alignment being in the same object
@@ -123,7 +123,7 @@ public static unsafe byte Exchange(ref byte location1, byte value)
123123
[CLSCompliant(false)]
124124
public static unsafe ushort Exchange(ref ushort location1, ushort value)
125125
{
126-
#if !MONO && (TARGET_X86 || TARGET_AMD64 || TARGET_ARM64)
126+
#if ((MONO && (TARGET_AMD64 || TARGET_ARM64 || TARGET_WASM)) || !MONO && (TARGET_X86 || TARGET_AMD64 || TARGET_ARM64))
127127
return Exchange(ref location1, value); // Must expand intrinsic
128128
#else
129129
// this relies on GC keeping 4B alignment for refs and on subtracting to such alignment being in the same object
@@ -322,7 +322,7 @@ public static short CompareExchange(ref short location1, short value, short comp
322322
[MethodImpl(MethodImplOptions.AggressiveInlining)]
323323
public static unsafe byte CompareExchange(ref byte location1, byte value, byte comparand)
324324
{
325-
#if !MONO && (TARGET_X86 || TARGET_AMD64 || TARGET_ARM64)
325+
#if (MONO && (TARGET_ARM64 || TARGET_AMD64 || TARGET_WASM)) || (!MONO && (TARGET_X86 || TARGET_AMD64 || TARGET_ARM64))
326326
return CompareExchange(ref location1, value, comparand); // Must expand intrinsic
327327
#else
328328
// this relies on GC keeping 4B alignment for refs and on subtracting to such alignment being in the same object
@@ -365,7 +365,7 @@ public static unsafe byte CompareExchange(ref byte location1, byte value, byte c
365365
[CLSCompliant(false)]
366366
public static unsafe ushort CompareExchange(ref ushort location1, ushort value, ushort comparand)
367367
{
368-
#if !MONO && (TARGET_X86 || TARGET_AMD64 || TARGET_ARM64)
368+
#if (MONO && (TARGET_ARM64 || TARGET_AMD64 || TARGET_WASM)) || (!MONO && (TARGET_X86 || TARGET_AMD64 || TARGET_ARM64))
369369
return CompareExchange(ref location1, value, comparand); // Must expand intrinsic
370370
#else
371371
// this relies on GC keeping 4B alignment for refs and on subtracting to such alignment being in the same object

src/mono/browser/runtime/jiterpreter-opcodes.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,3 +511,73 @@ export const enum WasmSimdOpcode {
511511
i32x4_extadd_pairwise_i16x8_s = 0x7e,
512512
i32x4_extadd_pairwise_i16x8_u = 0x7f,
513513
}
514+
515+
export const enum WasmAtomicOpcode {
516+
memory_atomic_notify = 0x00,
517+
memory_atomic_wait32 = 0x01,
518+
memory_atomic_wait64 = 0x02,
519+
atomic_fence = 0x03,
520+
i32_atomic_load = 0x10,
521+
i64_atomic_load = 0x11,
522+
i32_atomic_load8_u = 0x12,
523+
i32_atomic_load16_u = 0x13,
524+
i64_atomic_load8_u = 0x14,
525+
i64_atomic_load16_u = 0x15,
526+
i64_atomic_load32_u = 0x16,
527+
i32_atomic_store = 0x17,
528+
i64_atomic_store = 0x18,
529+
i32_atomic_store8 = 0x19,
530+
i32_atomic_store16 = 0x1A,
531+
i64_atomic_store8 = 0x1B,
532+
i64_atomic_store16 = 0x1C,
533+
i64_atomic_store32 = 0x1D,
534+
i32_atomic_rmw_add = 0x1E,
535+
i64_atomic_rmw_add = 0x1F,
536+
i32_atomic_rmw8_add_u = 0x20,
537+
i32_atomic_rmw16_add_u = 0x21,
538+
i64_atomic_rmw8_add_u = 0x22,
539+
i64_atomic_rmw16_add_u = 0x23,
540+
i64_atomic_rmw32_add_u = 0x24,
541+
i32_atomic_rmw_sub = 0x25,
542+
i64_atomic_rmw_sub = 0x26,
543+
i32_atomic_rmw8_sub_u = 0x27,
544+
i32_atomic_rmw16_sub_u = 0x28,
545+
i64_atomic_rmw8_sub_u = 0x29,
546+
i64_atomic_rmw16_sub_u = 0x2A,
547+
i64_atomic_rmw32_sub_u = 0x2B,
548+
i32_atomic_rmw_and = 0x2C,
549+
i64_atomic_rmw_and = 0x2D,
550+
i32_atomic_rmw8_and_u = 0x2E,
551+
i32_atomic_rmw16_and_u = 0x2F,
552+
i64_atomic_rmw8_and_u = 0x30,
553+
i64_atomic_rmw16_and_u = 0x31,
554+
i64_atomic_rmw32_and_u = 0x32,
555+
i32_atomic_rmw_or = 0x33,
556+
i64_atomic_rmw_or = 0x34,
557+
i32_atomic_rmw8_or_u = 0x35,
558+
i32_atomic_rmw16_or_u = 0x36,
559+
i64_atomic_rmw8_or_u = 0x37,
560+
i64_atomic_rmw16_or_u = 0x38,
561+
i64_atomic_rmw32_or_u = 0x39,
562+
i32_atomic_rmw_xor = 0x3A,
563+
i64_atomic_rmw_xor = 0x3B,
564+
i32_atomic_rmw8_xor_u = 0x3C,
565+
i32_atomic_rmw16_xor_u = 0x3D,
566+
i64_atomic_rmw8_xor_u = 0x3E,
567+
i64_atomic_rmw16_xor_u = 0x3F,
568+
i64_atomic_rmw32_xor_u = 0x40,
569+
i32_atomic_rmw_xchg = 0x41,
570+
i64_atomic_rmw_xchg = 0x42,
571+
i32_atomic_rmw8_xchg_u = 0x43,
572+
i32_atomic_rmw16_xchg_u = 0x44,
573+
i64_atomic_rmw8_xchg_u = 0x45,
574+
i64_atomic_rmw16_xchg_u = 0x46,
575+
i64_atomic_rmw32_xchg_u = 0x47,
576+
i32_atomic_rmw_cmpxchg = 0x48,
577+
i64_atomic_rmw_cmpxchg = 0x49,
578+
i32_atomic_rmw8_cmpxchg_u = 0x4A,
579+
i32_atomic_rmw16_cmpxchg_u = 0x4B,
580+
i64_atomic_rmw8_cmpxchg_u = 0x4C,
581+
i64_atomic_rmw16_cmpxchg_u = 0x4D,
582+
i64_atomic_rmw32_cmpxchg_u = 0x4E,
583+
}

src/mono/browser/runtime/jiterpreter-support.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import WasmEnableThreads from "consts:wasmEnableThreads";
55
import { NativePointer, ManagedPointer, VoidPtr } from "./types/emscripten";
66
import { Module, mono_assert, runtimeHelpers } from "./globals";
7-
import { WasmOpcode, WasmSimdOpcode, WasmValtype } from "./jiterpreter-opcodes";
7+
import { WasmOpcode, WasmSimdOpcode, WasmAtomicOpcode, WasmValtype } from "./jiterpreter-opcodes";
88
import { MintOpcode } from "./mintops";
99
import cwraps from "./cwraps";
1010
import { mono_log_error, mono_log_info } from "./logging";
@@ -105,6 +105,9 @@ export class WasmBuilder {
105105
nextConstantSlot = 0;
106106
backBranchTraceLevel = 0;
107107

108+
containsSimd!: boolean;
109+
containsAtomics!: boolean;
110+
108111
compressImportNames = false;
109112
lockImports = false;
110113

@@ -153,6 +156,9 @@ export class WasmBuilder {
153156
this.callHandlerReturnAddresses.length = 0;
154157

155158
this.allowNullCheckOptimization = this.options.eliminateNullChecks;
159+
160+
this.containsSimd = false;
161+
this.containsAtomics = false;
156162
}
157163

158164
_push () {
@@ -257,11 +263,18 @@ export class WasmBuilder {
257263

258264
appendSimd (value: WasmSimdOpcode, allowLoad?: boolean) {
259265
this.current.appendU8(WasmOpcode.PREFIX_simd);
260-
// Yes that's right. We're using LEB128 to encode 8-bit opcodes. Why? I don't know
261266
mono_assert(((value | 0) !== 0) || ((value === WasmSimdOpcode.v128_load) && (allowLoad === true)), "Expected non-v128_load simd opcode or allowLoad==true");
267+
// Yes that's right. We're using LEB128 to encode 8-bit opcodes. Why? I don't know
262268
return this.current.appendULeb(value);
263269
}
264270

271+
appendAtomic (value: WasmAtomicOpcode, allowNotify?: boolean) {
272+
this.current.appendU8(WasmOpcode.PREFIX_atomic);
273+
mono_assert(((value | 0) !== 0) || ((value === WasmAtomicOpcode.memory_atomic_notify) && (allowNotify === true)), "Expected non-notify atomic opcode or allowNotify==true");
274+
// Unlike SIMD, the spec appears to say that atomic opcodes are just two sequential bytes with explicit values.
275+
return this.current.appendU8(value);
276+
}
277+
265278
appendU32 (value: number) {
266279
return this.current.appendU32(value);
267280
}
@@ -517,7 +530,7 @@ export class WasmBuilder {
517530
// memtype (limits = 0x03 n:u32 m:u32 => {min n, max m, shared})
518531
this.appendU8(0x02);
519532
this.appendU8(0x03);
520-
// emcc seems to generate this min/max by default
533+
// HACK: emcc seems to generate this min/max by default
521534
this.appendULeb(256);
522535
this.appendULeb(32768);
523536
} else {
@@ -1900,6 +1913,7 @@ export type JiterpreterOptions = {
19001913
enableCallResume: boolean;
19011914
enableWasmEh: boolean;
19021915
enableSimd: boolean;
1916+
enableAtomics: boolean;
19031917
zeroPageOptimization: boolean;
19041918
cprop: boolean;
19051919
// For locations where the jiterpreter heuristic says we will be unable to generate
@@ -1946,6 +1960,7 @@ const optionNames: { [jsName: string]: string } = {
19461960
"enableCallResume": "jiterpreter-call-resume-enabled",
19471961
"enableWasmEh": "jiterpreter-wasm-eh-enabled",
19481962
"enableSimd": "jiterpreter-simd-enabled",
1963+
"enableAtomics": "jiterpreter-atomics-enabled",
19491964
"zeroPageOptimization": "jiterpreter-zero-page-optimization",
19501965
"cprop": "jiterpreter-constant-propagation",
19511966
"enableStats": "jiterpreter-stats-enabled",

src/mono/browser/runtime/jiterpreter-tables.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
import {
5-
WasmOpcode, WasmSimdOpcode, JiterpSpecialOpcode
5+
WasmOpcode, WasmSimdOpcode, WasmAtomicOpcode, JiterpSpecialOpcode
66
} from "./jiterpreter-opcodes";
77
import {
88
MintOpcode, SimdIntrinsic2, SimdIntrinsic3, SimdIntrinsic4
@@ -325,6 +325,24 @@ export const mathIntrinsicTable: { [opcode: number]: [isUnary: boolean, isF32: b
325325
[MintOpcode.MINT_REM_R4]: [false, true, "fmodf"],
326326
};
327327

328+
export const xchgTable: { [opcode: number]: [wasmOpcode: WasmAtomicOpcode, resultFixupOpcode: WasmOpcode, alignmentPower: number] } = {
329+
[MintOpcode.MINT_MONO_EXCHANGE_U1]: [WasmAtomicOpcode.i32_atomic_rmw8_xchg_u, WasmOpcode.unreachable, 0],
330+
[MintOpcode.MINT_MONO_EXCHANGE_I1]: [WasmAtomicOpcode.i32_atomic_rmw8_xchg_u, WasmOpcode.i32_extend_8_s, 0],
331+
[MintOpcode.MINT_MONO_EXCHANGE_U2]: [WasmAtomicOpcode.i32_atomic_rmw16_xchg_u, WasmOpcode.unreachable, 1],
332+
[MintOpcode.MINT_MONO_EXCHANGE_I2]: [WasmAtomicOpcode.i32_atomic_rmw16_xchg_u, WasmOpcode.i32_extend_16_s, 1],
333+
[MintOpcode.MINT_MONO_EXCHANGE_I4]: [WasmAtomicOpcode.i32_atomic_rmw_xchg, WasmOpcode.unreachable, 2],
334+
[MintOpcode.MINT_MONO_EXCHANGE_I8]: [WasmAtomicOpcode.i64_atomic_rmw_xchg, WasmOpcode.unreachable, 3],
335+
};
336+
337+
export const cmpxchgTable: { [opcode: number]: [wasmOpcode: WasmAtomicOpcode, resultFixupOpcode: WasmOpcode, alignmentPower: number] } = {
338+
[MintOpcode.MINT_MONO_CMPXCHG_U1]: [WasmAtomicOpcode.i32_atomic_rmw8_cmpxchg_u, WasmOpcode.unreachable, 0],
339+
[MintOpcode.MINT_MONO_CMPXCHG_I1]: [WasmAtomicOpcode.i32_atomic_rmw8_cmpxchg_u, WasmOpcode.i32_extend_8_s, 0],
340+
[MintOpcode.MINT_MONO_CMPXCHG_U2]: [WasmAtomicOpcode.i32_atomic_rmw16_cmpxchg_u, WasmOpcode.unreachable, 1],
341+
[MintOpcode.MINT_MONO_CMPXCHG_I2]: [WasmAtomicOpcode.i32_atomic_rmw16_cmpxchg_u, WasmOpcode.i32_extend_16_s, 1],
342+
[MintOpcode.MINT_MONO_CMPXCHG_I4]: [WasmAtomicOpcode.i32_atomic_rmw_cmpxchg, WasmOpcode.unreachable, 2],
343+
[MintOpcode.MINT_MONO_CMPXCHG_I8]: [WasmAtomicOpcode.i64_atomic_rmw_cmpxchg, WasmOpcode.unreachable, 3],
344+
};
345+
328346
export const simdCreateSizes = {
329347
[MintOpcode.MINT_SIMD_V128_I1_CREATE]: 1,
330348
[MintOpcode.MINT_SIMD_V128_I2_CREATE]: 2,

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

Lines changed: 61 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import {
5454
bitmaskTable, createScalarTable,
5555
simdExtractTable, simdReplaceTable,
5656
simdLoadTable, simdStoreTable,
57+
xchgTable, cmpxchgTable,
5758
} from "./jiterpreter-tables";
5859
import { mono_log_error, mono_log_info } from "./logging";
5960
import { mono_assert, runtimeHelpers } from "./globals";
@@ -244,7 +245,6 @@ export function generateWasmBody (
244245
): number {
245246
const abort = <MintOpcodePtr><any>0;
246247
let isFirstInstruction = true, isConditionallyExecuted = false,
247-
containsSimd = false,
248248
pruneOpcodes = false, hasEmittedUnreachable = false;
249249
let result = 0,
250250
prologueOpcodeCounter = 0,
@@ -1465,26 +1465,6 @@ export function generateWasmBody (
14651465
break;
14661466
}
14671467

1468-
case MintOpcode.MINT_MONO_CMPXCHG_I4:
1469-
builder.local("pLocals");
1470-
append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load); // dest
1471-
append_ldloc(builder, getArgU16(ip, 3), WasmOpcode.i32_load); // newVal
1472-
append_ldloc(builder, getArgU16(ip, 4), WasmOpcode.i32_load); // expected
1473-
builder.callImport("cmpxchg_i32");
1474-
append_stloc_tail(builder, getArgU16(ip, 1), WasmOpcode.i32_store);
1475-
break;
1476-
case MintOpcode.MINT_MONO_CMPXCHG_I8:
1477-
// because i64 values can't pass through JS cleanly (c.f getRawCwrap and
1478-
// EMSCRIPTEN_KEEPALIVE), we pass addresses of newVal, expected and the return value
1479-
// to the helper function. The "dest" for the compare-exchange is already a
1480-
// pointer, so load it normally
1481-
append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load); // dest
1482-
append_ldloca(builder, getArgU16(ip, 3), 0); // newVal
1483-
append_ldloca(builder, getArgU16(ip, 4), 0); // expected
1484-
append_ldloca(builder, getArgU16(ip, 1), 8); // oldVal
1485-
builder.callImport("cmpxchg_i64");
1486-
break;
1487-
14881468
case MintOpcode.MINT_LOG2_I4:
14891469
case MintOpcode.MINT_LOG2_I8: {
14901470
const isI64 = (opcode === MintOpcode.MINT_LOG2_I8);
@@ -1647,13 +1627,19 @@ export function generateWasmBody (
16471627
(opcode >= MintOpcode.MINT_SIMD_V128_LDC) &&
16481628
(opcode <= MintOpcode.MINT_SIMD_INTRINS_P_PPP)
16491629
) {
1630+
builder.containsSimd = true;
16501631
if (!emit_simd(builder, ip, opcode, opname, simdIntrinsArgCount, simdIntrinsIndex))
16511632
ip = abort;
1652-
else {
1653-
containsSimd = true;
1633+
else
16541634
// We need to do dreg invalidation differently for simd, especially to handle ldc
16551635
skipDregInvalidation = true;
1656-
}
1636+
} else if (
1637+
(opcode >= MintOpcode.MINT_MONO_MEMORY_BARRIER) &&
1638+
(opcode <= MintOpcode.MINT_MONO_CMPXCHG_I8)
1639+
) {
1640+
builder.containsAtomics = true;
1641+
if (!emit_atomics(builder, ip, opcode))
1642+
ip = abort;
16571643
} else if (opcodeValue === 0) {
16581644
// This means it was explicitly marked as no-value in the opcode value table
16591645
// so we can just skip over it. This is done for things like nops.
@@ -1740,7 +1726,7 @@ export function generateWasmBody (
17401726
// HACK: Traces containing simd will be *much* shorter than non-simd traces,
17411727
// which will cause both the heuristic and our length requirement outside
17421728
// to reject them. For now, just add a big constant to the length
1743-
if (containsSimd)
1729+
if (builder.containsSimd)
17441730
result += 10240;
17451731
return result;
17461732
}
@@ -3963,3 +3949,53 @@ function emit_simd_4 (builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrin
39633949
return false;
39643950
}
39653951
}
3952+
3953+
function emit_atomics (
3954+
builder: WasmBuilder, ip: MintOpcodePtr, opcode: number
3955+
) {
3956+
if (!builder.options.enableAtomics)
3957+
return false;
3958+
3959+
// FIXME: memory barrier might be worthwhile to implement
3960+
// FIXME: We could probably unify most of the xchg/cmpxchg implementation into one implementation
3961+
3962+
const xchg = xchgTable[opcode];
3963+
if (xchg) {
3964+
const is64 = xchg[2] > 2;
3965+
// TODO: Generate alignment check to produce a better runtime error when address is not aligned?
3966+
builder.local("pLocals"); // stloc head
3967+
append_ldloc_cknull(builder, getArgU16(ip, 2), ip, true); // address
3968+
append_ldloc(builder, getArgU16(ip, 3), is64 ? WasmOpcode.i64_load : WasmOpcode.i32_load); // replacement
3969+
builder.appendAtomic(xchg[0], false);
3970+
builder.appendMemarg(0, xchg[2]);
3971+
// Fixup the result if necessary
3972+
if (xchg[1] !== WasmOpcode.unreachable)
3973+
builder.appendU8(xchg[1]);
3974+
// store old value
3975+
append_stloc_tail(builder, getArgU16(ip, 1), is64 ? WasmOpcode.i64_store : WasmOpcode.i32_store);
3976+
return true;
3977+
}
3978+
3979+
const cmpxchg = cmpxchgTable[opcode];
3980+
if (cmpxchg) {
3981+
const is64 = cmpxchg[2] > 2;
3982+
// TODO: Generate alignment check to produce a better runtime error when address is not aligned?
3983+
builder.local("pLocals"); // stloc head
3984+
append_ldloc_cknull(builder, getArgU16(ip, 2), ip, true); // address
3985+
// FIXME: Do these loads need to be sized? I think it's well-defined even if there are garbage bytes in the i32,
3986+
// based on language from the spec that looks like this: 'expected wrapped from i32 to i8, 8-bit compare equal'
3987+
append_ldloc(builder, getArgU16(ip, 4), is64 ? WasmOpcode.i64_load : WasmOpcode.i32_load); // expected
3988+
append_ldloc(builder, getArgU16(ip, 3), is64 ? WasmOpcode.i64_load : WasmOpcode.i32_load); // replacement
3989+
builder.appendAtomic(cmpxchg[0], false);
3990+
builder.appendMemarg(0, cmpxchg[2]);
3991+
// Fixup the result if necessary
3992+
if (cmpxchg[1] !== WasmOpcode.unreachable)
3993+
builder.appendU8(cmpxchg[1]);
3994+
// store old value
3995+
append_stloc_tail(builder, getArgU16(ip, 1), is64 ? WasmOpcode.i64_store : WasmOpcode.i32_store);
3996+
return true;
3997+
}
3998+
3999+
return false;
4000+
}
4001+

src/mono/browser/runtime/jiterpreter.ts

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,6 @@ function getTraceImports () {
283283
importDef("array_rank", getRawCwrap("mono_jiterp_get_array_rank")),
284284
["a_elesize", "array_rank", getRawCwrap("mono_jiterp_get_array_element_size")],
285285
importDef("stfld_o", getRawCwrap("mono_jiterp_set_object_field")),
286-
importDef("cmpxchg_i32", getRawCwrap("mono_jiterp_cas_i32")),
287-
importDef("cmpxchg_i64", getRawCwrap("mono_jiterp_cas_i64")),
288286
["stelemr_tc", "stelemr", getRawCwrap("mono_jiterp_stelem_ref")],
289287
importDef("fma", getRawCwrap("fma")),
290288
importDef("fmaf", getRawCwrap("fmaf")),
@@ -629,25 +627,6 @@ function initialize_builder (builder: WasmBuilder) {
629627
},
630628
WasmValtype.void, true
631629
);
632-
builder.defineType(
633-
"cmpxchg_i32",
634-
{
635-
"dest": WasmValtype.i32,
636-
"newVal": WasmValtype.i32,
637-
"expected": WasmValtype.i32,
638-
},
639-
WasmValtype.i32, true
640-
);
641-
builder.defineType(
642-
"cmpxchg_i64",
643-
{
644-
"dest": WasmValtype.i32,
645-
"newVal": WasmValtype.i32,
646-
"expected": WasmValtype.i32,
647-
"oldVal": WasmValtype.i32,
648-
},
649-
WasmValtype.void, true
650-
);
651630
builder.defineType(
652631
"stelemr",
653632
{
@@ -896,7 +875,12 @@ function generate_wasm (
896875
} catch (exc: any) {
897876
threw = true;
898877
rejected = false;
899-
mono_log_error(`${methodFullName || traceName} code generation failed: ${exc} ${exc.stack}`);
878+
let desc = builder.containsSimd
879+
? " (simd)"
880+
: "";
881+
if (builder.containsAtomics)
882+
desc += " (atomics)";
883+
mono_log_error(`${methodFullName || traceName}${desc} code generation failed: ${exc} ${exc.stack}`);
900884
recordFailure();
901885
return 0;
902886
} finally {

0 commit comments

Comments
 (0)