Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions src/literal.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,11 +266,7 @@ class Literal {
lit.i32 = value | 0x80000000;
return lit;
}
static Literal makeExtern(int32_t payload, Shareability share) {
auto lit = Literal(Type(HeapTypes::ext.getBasic(share), NonNullable));
lit.i32 = (payload << 1) | 1;
return lit;
}
static Literal makeExtern(int32_t payload, Shareability share);
// Wasm has nondeterministic rules for NaN propagation in some operations. For
// example. f32.neg is deterministic and just flips the sign, even of a NaN,
// but f32.add is nondeterministic, and if one or more of the inputs is a NaN,
Expand Down Expand Up @@ -308,14 +304,8 @@ class Literal {
// Cast to unsigned for the left shift to avoid undefined behavior.
return signed_ ? int32_t((uint32_t(i32) << 1)) >> 1 : (i32 & 0x7fffffff);
}
bool hasExternPayload() const {
assert(type.getHeapType().isMaybeShared(HeapType::ext));
return (i32 & 1) == 1;
}
int32_t getExternPayload() const {
assert(hasExternPayload());
return int32_t(uint32_t(i32) >> 1);
}
bool hasExternPayload() const;
int32_t getExternPayload() const;
int64_t geti64() const {
assert(type == Type::i64);
return i64;
Expand Down Expand Up @@ -813,6 +803,19 @@ struct GCData {
: values(std::move(values)), desc(desc) {}
};

inline bool Literal::hasExternPayload() const {
if (isNull()) {
return false;
}
assert(type.getHeapType().isMaybeShared(HeapType::ext));
return gcData->values[0].type == Type::i32;
}

inline int32_t Literal::getExternPayload() const {
assert(hasExternPayload());
return gcData->values[0].geti32();
}

} // namespace wasm

namespace std {
Expand Down Expand Up @@ -857,6 +860,14 @@ template<> struct hash<wasm::Literal> {
wasm::rehash(digest, a.geti31(true));
return digest;
}
if (type.isMaybeShared(wasm::HeapType::ext)) {
if (a.hasExternPayload()) {
wasm::rehash(digest, a.getExternPayload());
return digest;
}
wasm::rehash(digest, (*this)(a.internalize()));
return digest;
}
if (type.isMaybeShared(wasm::HeapType::any)) {
// This may be an extern string that was internalized to |any|. Undo
// that to get the actual value. (Rehash here with the existing digest,
Expand Down
34 changes: 14 additions & 20 deletions src/wasm/literal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ Literal::Literal(Type type) : type(type) {

if (type.isRef() && type.getHeapType().isMaybeShared(HeapType::ext)) {
assert(type.isNonNullable());
i32 = 1;
new (&gcData) std::shared_ptr<GCData>(
std::make_shared<GCData>(Literals{Literal(int32_t(0))}));
return;
}

Expand All @@ -92,6 +93,11 @@ Literal Literal::makeFunc(Name func, Module& wasm) {
return makeFunc(func, wasm.getFunction(func)->type);
}

Literal Literal::makeExtern(int32_t payload, Shareability share) {
auto ext = HeapTypes::ext.getBasic(share);
return Literal(std::make_shared<GCData>(Literals{Literal(payload)}), ext);
}

Literal::Literal(std::shared_ptr<GCData> gcData, HeapType type)
: gcData(gcData), type(type,
gcData ? NonNullable : Nullable,
Expand Down Expand Up @@ -175,17 +181,9 @@ Literal::Literal(const Literal& other) : type(other.type) {
case HeapType::exn:
new (&exnData) std::shared_ptr<ExnData>(other.exnData);
return;
case HeapType::ext: {
if (other.hasExternPayload()) {
i32 = other.i32;
} else {
// Externalized internal reference.
new (&gcData) std::shared_ptr<GCData>(other.gcData);
}
return;
}
case HeapType::ext:
case HeapType::any:
// Internalized external reference or string.
// Externalized or internalized reference/payload.
new (&gcData) std::shared_ptr<GCData>(other.gcData);
return;
case HeapType::none:
Expand All @@ -210,12 +208,8 @@ Literal::~Literal() {
if (type.isBasic()) {
return;
}
if (type.getHeapType().isMaybeShared(HeapType::ext) && !hasExternPayload()) {
// Externalized internal reference.
gcData.~shared_ptr();
return;
}
if (isNull() || isData() || type.getHeapType().isMaybeShared(HeapType::any)) {
if (isNull() || isData() || type.getHeapType().isMaybeShared(HeapType::any) ||
type.getHeapType().isMaybeShared(HeapType::ext)) {
gcData.~shared_ptr();
} else if (isFunction()) {
funcData.~shared_ptr();
Expand Down Expand Up @@ -506,10 +500,10 @@ bool Literal::operator==(const Literal& other) const {
return i32 == other.i32;
}
if (heapType.isMaybeShared(HeapType::ext)) {
if (hasExternPayload() != other.hasExternPayload()) {
return false;
}
if (hasExternPayload()) {
if (!other.hasExternPayload()) {
return false;
}
return getExternPayload() == other.getExternPayload();
}
return internalize() == other.internalize();
Expand Down
Loading