Skip to content

Commit 9de9d05

Browse files
authored
[threads] Allow i31refs of mixed shareability to compare equal (#6752)
Normally, values of different types can never compare equal to each other, but since i31refs are not actually allocations, `ref.eq` has no way to differentiate a shared i31ref and an unshared i31ref with the same value, so it will report them as equal. Update the implementation of value equality to reflect this correctly.
1 parent ee43476 commit 9de9d05

2 files changed

Lines changed: 20 additions & 3 deletions

File tree

src/wasm/literal.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,14 @@ void Literal::getBits(uint8_t (&buf)[16]) const {
412412
}
413413

414414
bool Literal::operator==(const Literal& other) const {
415+
// As a special case, shared and unshared i31 can compare equal even if their
416+
// types are different (because one is shared and the other is not).
417+
if (type.isRef() && other.type.isRef() && type.getHeapType().isBasic() &&
418+
other.type.getHeapType().isBasic() &&
419+
type.getHeapType().getBasic(Unshared) == HeapType::i31 &&
420+
other.type.getHeapType().getBasic(Unshared) == HeapType::i31) {
421+
return i32 == other.i32;
422+
}
415423
if (type != other.type) {
416424
return false;
417425
}
@@ -445,9 +453,7 @@ bool Literal::operator==(const Literal& other) const {
445453
if (type.isData()) {
446454
return gcData == other.gcData;
447455
}
448-
if (type.getHeapType() == HeapType::i31) {
449-
return i32 == other.i32;
450-
}
456+
// i31 already handled.
451457
WASM_UNREACHABLE("unexpected type");
452458
}
453459
WASM_UNREACHABLE("unexpected type");

test/spec/shared-polymorphism.wast

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,14 @@
2323
(extern.convert_any (local.get 0))
2424
)
2525
)
26+
27+
(module
28+
(func (export "eq") (param i32 i32) (result i32)
29+
(ref.eq (ref.i31 (local.get 0)) (ref.i31_shared (local.get 1)))
30+
)
31+
)
32+
33+
(assert_return (invoke "eq" (i32.const 0) (i32.const 0)) (i32.const 1))
34+
(assert_return (invoke "eq" (i32.const 0) (i32.const 1)) (i32.const 0))
35+
(assert_return (invoke "eq" (i32.const 1) (i32.const 0)) (i32.const 0))
36+
(assert_return (invoke "eq" (i32.const 1) (i32.const 1)) (i32.const 1))

0 commit comments

Comments
 (0)