Skip to content

Commit c384a95

Browse files
Gemini fix
1 parent ea261c4 commit c384a95

3 files changed

Lines changed: 107 additions & 31 deletions

File tree

‎src/tools/wasm-ctor-eval.cpp‎

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -890,14 +890,23 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface {
890890
value.type.getHeapType().isMaybeShared(HeapType::i31));
891891
}
892892

893-
// GC data (structs and arrays) must be handled with the special global-
894-
// creating logic later down. But MVP types as well as i31s (even
895-
// externalized i31s) can be handled by the general makeConstantExpression
896-
// logic (which knows how to handle externalization, for i31s; and it also
897-
// can handle string constants).
898-
if (!value.isData() || value.isString()) {
893+
// GC data (structs and arrays) and waitqueues must be handled with the
894+
// special global-creating logic later down. But MVP types as well as i31s
895+
// (even externalized i31s) can be handled by the general
896+
// makeConstantExpression logic (which knows how to handle externalization,
897+
// for i31s; and it also can handle string constants).
898+
bool isWaitqueue =
899+
value.type.isRef() &&
900+
value.type.getHeapType().isMaybeShared(HeapType::waitqueue);
901+
if ((!value.isData() && !isWaitqueue) || value.isString()) {
899902
return builder.makeConstantExpression(original);
900903
}
904+
if (isWaitqueue && !wasm->features.hasGC()) {
905+
// Without GC we cannot refer to a defining global in another global's
906+
// initializer, and waitqueue identity cannot be observed without
907+
// struct.wait.
908+
return builder.makeWaitqueueNew();
909+
}
901910

902911
// This is GC data, which we must handle in a more careful way.
903912
auto* data = value.getGCData().get();
@@ -911,7 +920,7 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface {
911920
definingGlobalName = it->second.name;
912921
} else {
913922
// This is the first usage of this data. Generate a struct.new /
914-
// array.new for it.
923+
// array.new / waitqueue.new for it.
915924
std::vector<Expression*> args;
916925

917926
// The initial values for this allocation may themselves be GC
@@ -933,31 +942,35 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface {
933942
definingGlobals[data] = DefiningGlobalInfo{definingGlobalName, type};
934943
}
935944

936-
for (size_t i = 0; i < value.getNumElements(); i++) {
937-
auto* serialized = getSerialization(value.getElement(i));
938-
if (!serialized) {
939-
return nullptr;
945+
Expression* init;
946+
auto heapType = type.getHeapType();
947+
if (heapType.isMaybeShared(HeapType::waitqueue)) {
948+
init = builder.makeWaitqueueNew();
949+
} else {
950+
for (size_t i = 0; i < value.getNumElements(); i++) {
951+
auto* serialized = getSerialization(value.getElement(i));
952+
if (!serialized) {
953+
return nullptr;
954+
}
955+
args.push_back(serialized);
940956
}
941-
args.push_back(serialized);
942-
}
943957

944-
Expression* desc = nullptr;
945-
if (data->desc.getGCData()) {
946-
desc = getSerialization(data->desc);
947-
if (!desc) {
948-
return nullptr;
958+
Expression* desc = nullptr;
959+
if (data->desc.getGCData()) {
960+
desc = getSerialization(data->desc);
961+
if (!desc) {
962+
return nullptr;
963+
}
949964
}
950-
}
951965

952-
Expression* init;
953-
auto heapType = type.getHeapType();
954-
if (heapType.isStruct()) {
955-
init = builder.makeStructNew(heapType, args, desc);
956-
} else if (heapType.isArray()) {
957-
// TODO: for repeated identical values, can use ArrayNew
958-
init = builder.makeArrayNewFixed(heapType, args);
959-
} else {
960-
WASM_UNREACHABLE("bad gc type");
966+
if (heapType.isStruct()) {
967+
init = builder.makeStructNew(heapType, args, desc);
968+
} else if (heapType.isArray()) {
969+
// TODO: for repeated identical values, can use ArrayNew
970+
init = builder.makeArrayNewFixed(heapType, args);
971+
} else {
972+
WASM_UNREACHABLE("bad gc type");
973+
}
961974
}
962975

963976
if (possibleDefiningGlobal.is()) {

‎src/wasm/literal.cpp‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ Literal::Literal(Type type) : type(type) {
7373

7474
if (type.isRef() && type.getHeapType().isMaybeShared(HeapType::waitqueue)) {
7575
assert(type.isNonNullable());
76+
new (&gcData) std::shared_ptr<GCData>(std::make_shared<GCData>(Literals{}));
7677
return;
7778
}
7879

@@ -217,7 +218,8 @@ Literal::~Literal() {
217218
return;
218219
}
219220
if (isNull() || isData() || type.getHeapType().isMaybeShared(HeapType::any) ||
220-
type.getHeapType().isMaybeShared(HeapType::ext)) {
221+
type.getHeapType().isMaybeShared(HeapType::ext) ||
222+
type.getHeapType().isMaybeShared(HeapType::waitqueue)) {
221223
gcData.~shared_ptr();
222224
} else if (isFunction()) {
223225
funcData.~shared_ptr();
@@ -501,7 +503,8 @@ bool Literal::operator==(const Literal& other) const {
501503
if (type.isString()) {
502504
return gcData->getLiterals() == other.gcData->getLiterals();
503505
}
504-
if (type.isData()) {
506+
if (type.isData() ||
507+
type.getHeapType().isMaybeShared(HeapType::waitqueue)) {
505508
return gcData == other.gcData;
506509
}
507510
auto heapType = type.getHeapType();
@@ -562,7 +565,8 @@ bool Literal::operator<(const Literal& other) const {
562565
if (type.isFunction()) {
563566
return *funcData < *other.funcData;
564567
}
565-
if (type.isData() || type.isString()) {
568+
if (type.isData() || type.isString() ||
569+
type.getHeapType().isMaybeShared(HeapType::waitqueue)) {
566570
return gcData < other.gcData;
567571
}
568572
auto heapType = type.getHeapType();

‎test/lit/ctor-eval/waitqueue.wast‎

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
2+
;; RUN: wasm-ctor-eval %s --ctors=test --kept-exports=test,other --quiet -all -S -o - | filecheck %s
3+
4+
(module
5+
;; CHECK: (type $struct (shared (struct (field (mut (ref null (shared waitqueue)))))))
6+
(type $struct (shared (struct (field (mut (ref null (shared waitqueue)))))))
7+
8+
;; CHECK: (type $1 (func (result (ref null (shared waitqueue)) (ref null $struct))))
9+
10+
;; CHECK: (type $2 (func (result (ref (shared waitqueue)))))
11+
12+
;; CHECK: (global $ctor-eval$global_6 (ref (shared waitqueue)) (waitqueue.new))
13+
14+
;; CHECK: (global $ctor-eval$global_7 (ref (exact $struct)) (struct.new $struct
15+
;; CHECK-NEXT: (global.get $ctor-eval$global_6)
16+
;; CHECK-NEXT: ))
17+
18+
;; CHECK: (global $global (mut (ref null (shared waitqueue))) (global.get $ctor-eval$global_6))
19+
(global $global (mut (ref null (shared waitqueue))) (ref.null (shared nowaitqueue)))
20+
;; CHECK: (global $struct (mut (ref null $struct)) (global.get $ctor-eval$global_7))
21+
(global $struct (mut (ref null $struct)) (ref.null (shared none)))
22+
23+
(func $test (export "test") (result (ref (shared waitqueue)))
24+
(local $wq (ref (shared waitqueue)))
25+
(local.set $wq
26+
(waitqueue.new)
27+
)
28+
(global.set $global
29+
(local.get $wq)
30+
)
31+
(global.set $struct
32+
(struct.new $struct
33+
(local.get $wq)
34+
)
35+
)
36+
(local.get $wq)
37+
)
38+
39+
;; CHECK: (export "test" (func $test_2))
40+
41+
;; CHECK: (export "other" (func $other))
42+
43+
;; CHECK: (func $other (type $1) (result (ref null (shared waitqueue)) (ref null $struct))
44+
;; CHECK-NEXT: (tuple.make 2
45+
;; CHECK-NEXT: (global.get $global)
46+
;; CHECK-NEXT: (global.get $struct)
47+
;; CHECK-NEXT: )
48+
;; CHECK-NEXT: )
49+
(func $other (export "other") (result (ref null (shared waitqueue)) (ref null $struct))
50+
(tuple.make 2
51+
(global.get $global)
52+
(global.get $struct)
53+
)
54+
)
55+
)
56+
;; CHECK: (func $test_2 (type $2) (result (ref (shared waitqueue)))
57+
;; CHECK-NEXT: (local $wq (ref (shared waitqueue)))
58+
;; CHECK-NEXT: (global.get $ctor-eval$global_6)
59+
;; CHECK-NEXT: )

0 commit comments

Comments
 (0)