Skip to content
Merged
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
32 changes: 13 additions & 19 deletions src/passes/Heap2Local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1029,8 +1029,7 @@ struct Array2Struct : PostWalker<Array2Struct> {

// The type of the struct we are changing to (nullable and non-nullable
// variations).
Type nullStruct;
Type nonNullStruct;
HeapType structType;

Array2Struct(Expression* allocation,
EscapeAnalyzer& analyzer,
Expand All @@ -1048,7 +1047,7 @@ struct Array2Struct : PostWalker<Array2Struct> {
for (Index i = 0; i < numFields; i++) {
fields.push_back(element);
}
HeapType structType = Struct(fields);
structType = Struct(fields);

// Generate a StructNew to replace the ArrayNew*.
if (auto* arrayNew = allocation->dynCast<ArrayNew>()) {
Expand Down Expand Up @@ -1097,30 +1096,25 @@ struct Array2Struct : PostWalker<Array2Struct> {
// the array type (which can be the case of an array of arrays). But that is
// fine to do as the array.get is rewritten to a struct.get which is then
// lowered away to locals anyhow.
auto nullArray = Type(arrayType, Nullable);
auto nonNullArray = Type(arrayType, NonNullable);
nullStruct = Type(structType, Nullable);
nonNullStruct = Type(structType, NonNullable);
for (auto& [reached, _] : analyzer.reachedInteractions) {
if (reached->is<RefCast>()) {
// Casts must be handled later: We need to see the old type, and to
// potentially replace the cast based on that, see below.
continue;
}

// We must check subtyping here because the allocation may be upcast as it
// flows around. If we do see such upcasting then we are refining here and
// must refinalize.
if (Type::isSubType(nullArray, reached->type)) {
if (nullArray != reached->type) {
refinalize = true;
}
reached->type = nullStruct;
} else if (Type::isSubType(nonNullArray, reached->type)) {
if (nonNullArray != reached->type) {
if (!reached->type.isRef()) {
continue;
}

// The allocation type may be generalized as it flows around. If we do see
// such generalizing, then we are refining here and must refinalize.
auto reachedHeapType = reached->type.getHeapType();
if (HeapType::isSubType(arrayType, reachedHeapType)) {
if (arrayType != reachedHeapType) {
refinalize = true;
}
reached->type = nonNullStruct;
reached->type = Type(structType, reached->type.getNullability());
}
}

Expand Down Expand Up @@ -1248,7 +1242,7 @@ struct Array2Struct : PostWalker<Array2Struct> {
// type here unconditionally, since we know the allocation flows through
// here, and anyhow we will be removing the reference during Struct2Local,
// later.)
curr->type = nonNullStruct;
curr->type = Type(structType, NonNullable);
}

// Regardless of how we altered the type here, refinalize.
Expand Down
Loading