summaryrefslogtreecommitdiff
path: root/src/wasm-interpreter.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm-interpreter.h')
-rw-r--r--src/wasm-interpreter.h95
1 files changed, 75 insertions, 20 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 53d3048b7..4e2d40e08 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -1483,8 +1483,8 @@ public:
// GC data store an RTT in each instance.
assert(cast.originalRef.isData());
auto gcData = cast.originalRef.getGCData();
- Literal seenRtt = gcData->rtt;
if (curr->rtt) {
+ Literal seenRtt = gcData->rtt;
if (!seenRtt.isSubRtt(intendedRtt)) {
cast.outcome = cast.Failure;
return cast;
@@ -1492,7 +1492,7 @@ public:
cast.castRef =
Literal(gcData, Type(intendedRtt.type.getHeapType(), NonNullable));
} else {
- auto seenType = seenRtt.type.getHeapType();
+ auto seenType = gcData->type;
if (!HeapType::isSubType(seenType, curr->intendedType)) {
cast.outcome = cast.Failure;
return cast;
@@ -1628,13 +1628,42 @@ public:
}
return Literal(std::move(newSupers), curr->type);
}
+
+ // Generates GC data for either dynamic (with an RTT) or static (with a type)
+ // typing. Dynamic typing will provide an rtt expression and an rtt flow with
+ // the value, while static typing only provides a heap type directly.
+ template<typename T>
+ std::shared_ptr<GCData>
+ makeGCData(Expression* rttExpr, Flow& rttFlow, HeapType type, T& data) {
+ if (rttExpr) {
+ return std::make_shared<GCData>(rttFlow.getSingleValue(), data);
+ } else {
+ return std::make_shared<GCData>(type, data);
+ }
+ }
+
Flow visitStructNew(StructNew* curr) {
NOTE_ENTER("StructNew");
- auto rtt = this->visit(curr->rtt);
- if (rtt.breaking()) {
- return rtt;
+ Flow rtt;
+ if (curr->rtt) {
+ rtt = this->visit(curr->rtt);
+ if (rtt.breaking()) {
+ return rtt;
+ }
+ }
+ if (curr->type == Type::unreachable) {
+ // We cannot proceed to compute the heap type, as there isn't one. Just
+ // find why we are unreachable, and stop there.
+ for (auto* operand : curr->operands) {
+ auto value = this->visit(operand);
+ if (value.breaking()) {
+ return value;
+ }
+ }
+ WASM_UNREACHABLE("unreachable but no unreachable child");
}
- const auto& fields = curr->rtt->type.getHeapType().getStruct().fields;
+ auto heapType = curr->type.getHeapType();
+ const auto& fields = heapType.getStruct().fields;
Literals data(fields.size());
for (Index i = 0; i < fields.size(); i++) {
if (curr->isWithDefault()) {
@@ -1647,8 +1676,8 @@ public:
data[i] = value.getSingleValue();
}
}
- return Flow(Literal(std::make_shared<GCData>(rtt.getSingleValue(), data),
- curr->type));
+ return Flow(
+ Literal(makeGCData(curr->rtt, rtt, heapType, data), curr->type));
}
Flow visitStructGet(StructGet* curr) {
NOTE_ENTER("StructGet");
@@ -1691,15 +1720,26 @@ public:
Flow visitArrayNew(ArrayNew* curr) {
NOTE_ENTER("ArrayNew");
- auto rtt = this->visit(curr->rtt);
- if (rtt.breaking()) {
- return rtt;
+ Flow rtt;
+ if (curr->rtt) {
+ rtt = this->visit(curr->rtt);
+ if (rtt.breaking()) {
+ return rtt;
+ }
}
auto size = this->visit(curr->size);
if (size.breaking()) {
return size;
}
- const auto& element = curr->rtt->type.getHeapType().getArray().element;
+ if (curr->type == Type::unreachable) {
+ // We cannot proceed to compute the heap type, as there isn't one. Just
+ // visit the unreachable child, and stop there.
+ auto init = this->visit(curr->init);
+ assert(init.breaking());
+ return init;
+ }
+ auto heapType = curr->type.getHeapType();
+ const auto& element = heapType.getArray().element;
Index num = size.getSingleValue().geti32();
if (num >= ArrayLimit) {
hostLimit("allocation failure");
@@ -1720,20 +1760,35 @@ public:
data[i] = value;
}
}
- return Flow(Literal(std::make_shared<GCData>(rtt.getSingleValue(), data),
- curr->type));
+ return Flow(
+ Literal(makeGCData(curr->rtt, rtt, heapType, data), curr->type));
}
Flow visitArrayInit(ArrayInit* curr) {
NOTE_ENTER("ArrayInit");
- auto rtt = this->visit(curr->rtt);
- if (rtt.breaking()) {
- return rtt;
+ Flow rtt;
+ if (curr->rtt) {
+ rtt = this->visit(curr->rtt);
+ if (rtt.breaking()) {
+ return rtt;
+ }
}
Index num = curr->values.size();
if (num >= ArrayLimit) {
hostLimit("allocation failure");
}
- auto field = curr->type.getHeapType().getArray().element;
+ if (curr->type == Type::unreachable) {
+ // We cannot proceed to compute the heap type, as there isn't one. Just
+ // find why we are unreachable, and stop there.
+ for (auto* value : curr->values) {
+ auto result = this->visit(value);
+ if (result.breaking()) {
+ return result;
+ }
+ }
+ WASM_UNREACHABLE("unreachable but no unreachable child");
+ }
+ auto heapType = curr->type.getHeapType();
+ auto field = heapType.getArray().element;
Literals data(num);
for (Index i = 0; i < num; i++) {
auto value = this->visit(curr->values[i]);
@@ -1742,8 +1797,8 @@ public:
}
data[i] = truncateForPacking(value.getSingleValue(), field);
}
- return Flow(Literal(std::make_shared<GCData>(rtt.getSingleValue(), data),
- curr->type));
+ return Flow(
+ Literal(makeGCData(curr->rtt, rtt, heapType, data), curr->type));
}
Flow visitArrayGet(ArrayGet* curr) {
NOTE_ENTER("ArrayGet");