Skip to content

Commit cb2d175

Browse files
Extract out type walker
1 parent c405f26 commit cb2d175

2 files changed

Lines changed: 134 additions & 132 deletions

File tree

src/wasm-type.h

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,139 @@ inline bool HeapType::isBottom() const {
11091109
return false;
11101110
}
11111111

1112+
struct HeapTypeInfo {
1113+
using type_t = HeapType;
1114+
// Used in assertions to ensure that temporary types don't leak into the
1115+
// global store.
1116+
bool isTemp = false;
1117+
bool isOpen = false;
1118+
Shareability share = Unshared;
1119+
// The supertype of this HeapType, if it exists.
1120+
HeapTypeInfo* supertype = nullptr;
1121+
// The descriptor of this HeapType, if it exists.
1122+
HeapTypeInfo* descriptor = nullptr;
1123+
// The HeapType described by this one, if it exists.
1124+
HeapTypeInfo* described = nullptr;
1125+
// The recursion group of this type or null if the recursion group is trivial
1126+
// (i.e. contains only this type).
1127+
std::vector<HeapType>* recGroup = nullptr;
1128+
size_t recGroupIndex = 0;
1129+
HeapTypeKind kind;
1130+
union {
1131+
Signature signature;
1132+
Continuation continuation;
1133+
Struct struct_;
1134+
Array array;
1135+
};
1136+
1137+
HeapTypeInfo(Signature sig) : kind(HeapTypeKind::Func), signature(sig) {}
1138+
HeapTypeInfo(Continuation continuation)
1139+
: kind(HeapTypeKind::Cont), continuation(continuation) {}
1140+
HeapTypeInfo(const Struct& struct_)
1141+
: kind(HeapTypeKind::Struct), struct_(struct_) {}
1142+
HeapTypeInfo(Struct&& struct_)
1143+
: kind(HeapTypeKind::Struct), struct_(std::move(struct_)) {}
1144+
HeapTypeInfo(Array array) : kind(HeapTypeKind::Array), array(array) {}
1145+
~HeapTypeInfo();
1146+
1147+
constexpr bool isSignature() const { return kind == HeapTypeKind::Func; }
1148+
constexpr bool isContinuation() const { return kind == HeapTypeKind::Cont; }
1149+
constexpr bool isStruct() const { return kind == HeapTypeKind::Struct; }
1150+
constexpr bool isArray() const { return kind == HeapTypeKind::Array; }
1151+
constexpr bool isData() const { return isStruct() || isArray(); }
1152+
};
1153+
1154+
template<typename Self> struct TypeGraphWalkerBase {
1155+
void walkRoot(Type* type) {
1156+
assert(taskList.empty());
1157+
taskList.push_back(Task::scan(type));
1158+
doWalk();
1159+
}
1160+
1161+
void walkRoot(HeapType* ht) {
1162+
assert(taskList.empty());
1163+
taskList.push_back(Task::scan(ht));
1164+
doWalk();
1165+
}
1166+
1167+
protected:
1168+
Self& self() { return *static_cast<Self*>(this); }
1169+
1170+
void scanType(Type* type) {
1171+
if (type->isTuple()) {
1172+
auto& types = const_cast<Tuple&>(type->getTuple());
1173+
for (auto it = types.rbegin(); it != types.rend(); ++it) {
1174+
taskList.push_back(Task::scan(&*it));
1175+
}
1176+
}
1177+
}
1178+
1179+
void scanHeapType(HeapType* ht) {
1180+
if (ht->isBasic()) {
1181+
return;
1182+
}
1183+
assert(!ht->isBasic());
1184+
auto* info = reinterpret_cast<HeapTypeInfo*>(ht->getID());
1185+
1186+
switch (info->kind) {
1187+
case HeapTypeKind::Func:
1188+
taskList.push_back(Task::scan(&info->signature.results));
1189+
taskList.push_back(Task::scan(&info->signature.params));
1190+
break;
1191+
case HeapTypeKind::Cont:
1192+
taskList.push_back(Task::scan(&info->continuation.type));
1193+
break;
1194+
case HeapTypeKind::Struct: {
1195+
auto& fields = info->struct_.fields;
1196+
for (auto field = fields.rbegin(); field != fields.rend(); ++field) {
1197+
taskList.push_back(Task::scan(&field->type));
1198+
}
1199+
break;
1200+
}
1201+
case HeapTypeKind::Array:
1202+
taskList.push_back(Task::scan(&info->array.element.type));
1203+
break;
1204+
case HeapTypeKind::Basic:
1205+
WASM_UNREACHABLE("unexpected kind");
1206+
}
1207+
}
1208+
1209+
private:
1210+
struct Task {
1211+
enum Kind {
1212+
ScanType,
1213+
ScanHeapType,
1214+
} kind;
1215+
union {
1216+
Type* type;
1217+
HeapType* heapType;
1218+
};
1219+
static Task scan(Type* type) { return Task(type, ScanType); }
1220+
static Task scan(HeapType* ht) { return Task(ht, ScanHeapType); }
1221+
1222+
private:
1223+
Task(Type* type, Kind kind) : kind(kind), type(type) {}
1224+
Task(HeapType* ht, Kind kind) : kind(kind), heapType(ht) {}
1225+
};
1226+
1227+
std::vector<Task> taskList;
1228+
1229+
void doWalk() {
1230+
while (!taskList.empty()) {
1231+
auto curr = taskList.back();
1232+
taskList.pop_back();
1233+
switch (curr.kind) {
1234+
case Task::ScanType:
1235+
self().scanType(curr.type);
1236+
break;
1237+
case Task::ScanHeapType:
1238+
self().scanHeapType(curr.heapType);
1239+
break;
1240+
}
1241+
}
1242+
}
1243+
};
1244+
11121245
} // namespace wasm
11131246

11141247
namespace std {

src/wasm/wasm-type.cpp

Lines changed: 1 addition & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -38,48 +38,6 @@ namespace {
3838

3939
using RecGroupInfo = std::vector<HeapType>;
4040

41-
struct HeapTypeInfo {
42-
using type_t = HeapType;
43-
// Used in assertions to ensure that temporary types don't leak into the
44-
// global store.
45-
bool isTemp = false;
46-
bool isOpen = false;
47-
Shareability share = Unshared;
48-
// The supertype of this HeapType, if it exists.
49-
HeapTypeInfo* supertype = nullptr;
50-
// The descriptor of this HeapType, if it exists.
51-
HeapTypeInfo* descriptor = nullptr;
52-
// The HeapType described by this one, if it exists.
53-
HeapTypeInfo* described = nullptr;
54-
// The recursion group of this type or null if the recursion group is trivial
55-
// (i.e. contains only this type).
56-
RecGroupInfo* recGroup = nullptr;
57-
size_t recGroupIndex = 0;
58-
HeapTypeKind kind;
59-
union {
60-
Signature signature;
61-
Continuation continuation;
62-
Struct struct_;
63-
Array array;
64-
};
65-
66-
HeapTypeInfo(Signature sig) : kind(HeapTypeKind::Func), signature(sig) {}
67-
HeapTypeInfo(Continuation continuation)
68-
: kind(HeapTypeKind::Cont), continuation(continuation) {}
69-
HeapTypeInfo(const Struct& struct_)
70-
: kind(HeapTypeKind::Struct), struct_(struct_) {}
71-
HeapTypeInfo(Struct&& struct_)
72-
: kind(HeapTypeKind::Struct), struct_(std::move(struct_)) {}
73-
HeapTypeInfo(Array array) : kind(HeapTypeKind::Array), array(array) {}
74-
~HeapTypeInfo();
75-
76-
constexpr bool isSignature() const { return kind == HeapTypeKind::Func; }
77-
constexpr bool isContinuation() const { return kind == HeapTypeKind::Cont; }
78-
constexpr bool isStruct() const { return kind == HeapTypeKind::Struct; }
79-
constexpr bool isArray() const { return kind == HeapTypeKind::Array; }
80-
constexpr bool isData() const { return isStruct() || isArray(); }
81-
};
82-
8341
// Helper for coinductively checking whether a pair of Types or HeapTypes are in
8442
// a subtype relation.
8543
struct SubTyper {
@@ -223,7 +181,7 @@ namespace {
223181

224182
HeapTypeInfo* getHeapTypeInfo(HeapType ht) {
225183
assert(!ht.isBasic());
226-
return (HeapTypeInfo*)ht.getID();
184+
return reinterpret_cast<HeapTypeInfo*>(ht.getID());
227185
}
228186

229187
HeapType asHeapType(std::unique_ptr<HeapTypeInfo>& info) {
@@ -242,95 +200,6 @@ bool isTemp(HeapType type) {
242200
// from reference types to the referenced heap types are not walked, so
243201
// subclasses should handle referenced heap types when their reference types are
244202
// visited.
245-
template<typename Self> struct TypeGraphWalkerBase {
246-
void walkRoot(Type* type) {
247-
assert(taskList.empty());
248-
taskList.push_back(Task::scan(type));
249-
doWalk();
250-
}
251-
252-
void walkRoot(HeapType* ht) {
253-
assert(taskList.empty());
254-
taskList.push_back(Task::scan(ht));
255-
doWalk();
256-
}
257-
258-
protected:
259-
Self& self() { return *static_cast<Self*>(this); }
260-
261-
void scanType(Type* type) {
262-
if (type->isTuple()) {
263-
auto& types = const_cast<Tuple&>(type->getTuple());
264-
for (auto it = types.rbegin(); it != types.rend(); ++it) {
265-
taskList.push_back(Task::scan(&*it));
266-
}
267-
}
268-
}
269-
270-
void scanHeapType(HeapType* ht) {
271-
if (ht->isBasic()) {
272-
return;
273-
}
274-
auto* info = getHeapTypeInfo(*ht);
275-
switch (info->kind) {
276-
case HeapTypeKind::Func:
277-
taskList.push_back(Task::scan(&info->signature.results));
278-
taskList.push_back(Task::scan(&info->signature.params));
279-
break;
280-
case HeapTypeKind::Cont:
281-
taskList.push_back(Task::scan(&info->continuation.type));
282-
break;
283-
case HeapTypeKind::Struct: {
284-
auto& fields = info->struct_.fields;
285-
for (auto field = fields.rbegin(); field != fields.rend(); ++field) {
286-
taskList.push_back(Task::scan(&field->type));
287-
}
288-
break;
289-
}
290-
case HeapTypeKind::Array:
291-
taskList.push_back(Task::scan(&info->array.element.type));
292-
break;
293-
case HeapTypeKind::Basic:
294-
WASM_UNREACHABLE("unexpected kind");
295-
}
296-
}
297-
298-
private:
299-
struct Task {
300-
enum Kind {
301-
ScanType,
302-
ScanHeapType,
303-
} kind;
304-
union {
305-
Type* type;
306-
HeapType* heapType;
307-
};
308-
static Task scan(Type* type) { return Task(type, ScanType); }
309-
static Task scan(HeapType* ht) { return Task(ht, ScanHeapType); }
310-
311-
private:
312-
Task(Type* type, Kind kind) : kind(kind), type(type) {}
313-
Task(HeapType* ht, Kind kind) : kind(kind), heapType(ht) {}
314-
};
315-
316-
std::vector<Task> taskList;
317-
318-
void doWalk() {
319-
while (!taskList.empty()) {
320-
auto curr = taskList.back();
321-
taskList.pop_back();
322-
switch (curr.kind) {
323-
case Task::ScanType:
324-
self().scanType(curr.type);
325-
break;
326-
case Task::ScanHeapType:
327-
self().scanHeapType(curr.heapType);
328-
break;
329-
}
330-
}
331-
}
332-
};
333-
334203
// A type graph walker that scans each each direct HeapType child of the root.
335204
template<typename Self> struct HeapTypeChildWalker : TypeGraphWalkerBase<Self> {
336205
void scanType(Type* type) {

0 commit comments

Comments
 (0)