Skip to content

Commit eac0846

Browse files
authored
Generalize Literal::externalize/internalize for strings and shareability (#6784)
1 parent f938154 commit eac0846

File tree

3 files changed

+47
-18
lines changed

3 files changed

+47
-18
lines changed

src/wasm/literal.cpp

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ Literal::Literal(std::shared_ptr<GCData> gcData, HeapType type)
7474
: gcData(gcData), type(type, gcData ? NonNullable : Nullable) {
7575
// The type must be a proper type for GC data: either a struct, array, or
7676
// string; or an externalized version of the same; or a null.
77-
assert((isData() && gcData) || (type == HeapType::ext && gcData) ||
77+
assert((isData() && gcData) ||
78+
(type.isMaybeShared(HeapType::ext) && gcData) ||
7879
(type.isBottom() && !gcData));
7980
}
8081

@@ -115,7 +116,7 @@ Literal::Literal(const Literal& other) : type(other.type) {
115116
new (&gcData) std::shared_ptr<GCData>();
116117
return;
117118
}
118-
if (other.isData() || other.type.getHeapType() == HeapType::ext) {
119+
if (other.isData() || other.type.getHeapType().isMaybeShared(HeapType::ext)) {
119120
new (&gcData) std::shared_ptr<GCData>(other.gcData);
120121
return;
121122
}
@@ -160,7 +161,7 @@ Literal::~Literal() {
160161
if (type.isBasic()) {
161162
return;
162163
}
163-
if (isNull() || isData() || type.getHeapType() == HeapType::ext) {
164+
if (isNull() || isData() || type.getHeapType().isMaybeShared(HeapType::ext)) {
164165
gcData.~shared_ptr();
165166
}
166167
}
@@ -2684,36 +2685,29 @@ Literal Literal::relaxedFmsF64x2(const Literal& left,
26842685
}
26852686

26862687
Literal Literal::externalize() const {
2687-
assert(Type::isSubType(type, Type(HeapType::any, Nullable)) &&
2688+
assert(type.isRef() && type.getHeapType().getUnsharedTop() == HeapType::any &&
26882689
"can only externalize internal references");
26892690
if (isNull()) {
26902691
return Literal(std::shared_ptr<GCData>{}, HeapType::noext);
26912692
}
26922693
auto heapType = type.getHeapType();
26932694
auto extType = HeapTypes::ext.getBasic(heapType.getShared());
2694-
if (heapType.isBasic()) {
2695-
switch (heapType.getBasic(Unshared)) {
2696-
case HeapType::i31: {
2697-
return Literal(std::make_shared<GCData>(HeapType::i31, Literals{*this}),
2698-
extType);
2699-
}
2700-
case HeapType::string:
2701-
WASM_UNREACHABLE("TODO: string literals");
2702-
default:
2703-
WASM_UNREACHABLE("unexpected type");
2704-
}
2695+
if (heapType.isMaybeShared(HeapType::i31)) {
2696+
return Literal(std::make_shared<GCData>(heapType, Literals{*this}),
2697+
extType);
27052698
}
27062699
return Literal(gcData, extType);
27072700
}
27082701

27092702
Literal Literal::internalize() const {
2710-
assert(Type::isSubType(type, Type(HeapType::ext, Nullable)) &&
2703+
auto extType = HeapTypes::ext.getBasic(type.getHeapType().getShared());
2704+
assert(Type::isSubType(type, Type(extType, Nullable)) &&
27112705
"can only internalize external references");
27122706
if (isNull()) {
27132707
return Literal(std::shared_ptr<GCData>{}, HeapType::none);
27142708
}
2715-
if (gcData->type == HeapType::i31) {
2716-
assert(gcData->values[0].type.getHeapType() == HeapType::i31);
2709+
if (gcData->type.isMaybeShared(HeapType::i31)) {
2710+
assert(gcData->values[0].type.getHeapType().isMaybeShared(HeapType::i31));
27172711
return gcData->values[0];
27182712
}
27192713
return Literal(gcData, gcData->type);

test/lit/ctor-eval/shared-i31.wast

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@
1717
(i32.const 42)
1818
)
1919
)
20+
;; Also externalizing and internalizing works: this code can be precomputed
21+
;; and hence removed.
22+
(drop
23+
(any.convert_extern
24+
(extern.convert_any
25+
(global.get $global)
26+
)
27+
)
28+
)
2029
(global.get $global)
2130
)
2231

test/lit/exec/strings.wast

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,24 @@
476476
(string.const "five!")
477477
)
478478
)
479+
480+
;; CHECK: [fuzz-exec] calling extern
481+
;; CHECK-NEXT: [fuzz-exec] note result: extern => string("string")
482+
(func $extern (export "extern") (result externref)
483+
(extern.convert_any
484+
(string.const "string")
485+
)
486+
)
487+
488+
;; CHECK: [fuzz-exec] calling extern-intern
489+
;; CHECK-NEXT: [fuzz-exec] note result: extern-intern => string("string")
490+
(func $extern-intern (export "extern-intern") (result anyref)
491+
(any.convert_extern
492+
(extern.convert_any
493+
(string.const "string")
494+
)
495+
)
496+
)
479497
)
480498
;; CHECK: [fuzz-exec] calling new_wtf16_array
481499
;; CHECK-NEXT: [fuzz-exec] note result: new_wtf16_array => string("ello")
@@ -604,6 +622,12 @@
604622

605623
;; CHECK: [fuzz-exec] calling string.measure
606624
;; CHECK-NEXT: [fuzz-exec] note result: string.measure => 5
625+
626+
;; CHECK: [fuzz-exec] calling extern
627+
;; CHECK-NEXT: [fuzz-exec] note result: extern => string("string")
628+
629+
;; CHECK: [fuzz-exec] calling extern-intern
630+
;; CHECK-NEXT: [fuzz-exec] note result: extern-intern => string("string")
607631
;; CHECK-NEXT: [fuzz-exec] comparing compare.1
608632
;; CHECK-NEXT: [fuzz-exec] comparing compare.10
609633
;; CHECK-NEXT: [fuzz-exec] comparing compare.2
@@ -624,6 +648,8 @@
624648
;; CHECK-NEXT: [fuzz-exec] comparing eq.3
625649
;; CHECK-NEXT: [fuzz-exec] comparing eq.4
626650
;; CHECK-NEXT: [fuzz-exec] comparing eq.5
651+
;; CHECK-NEXT: [fuzz-exec] comparing extern
652+
;; CHECK-NEXT: [fuzz-exec] comparing extern-intern
627653
;; CHECK-NEXT: [fuzz-exec] comparing get_codeunit
628654
;; CHECK-NEXT: [fuzz-exec] comparing invalid_code_point
629655
;; CHECK-NEXT: [fuzz-exec] comparing isolated_high_code_point

0 commit comments

Comments
 (0)