Skip to content

Commit ccc5be0

Browse files
committed
start
1 parent cf756c9 commit ccc5be0

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

src/passes/GlobalStructInference.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ struct GlobalStructInference : public Pass {
7979
// optimizable it will have an entry here, and not if not.
8080
std::unordered_map<HeapType, std::vector<Name>> typeGlobals;
8181

82+
std::unique_ptr<SubTypes> subTypes;
83+
8284
void run(Module* module) override {
8385
if (!module->features.hasGC()) {
8486
return;
@@ -208,6 +210,12 @@ struct GlobalStructInference : public Pass {
208210
return;
209211
}
210212

213+
// When CD is enabled, we can optimize to ref.get_desc, depending on the
214+
// presence of subtypes.
215+
if (module->features.hasCustomDescriptors()) {
216+
subTypes = std::make_unique<SubTypes>(*module);
217+
}
218+
211219
// The above loop on typeGlobalsCopy is on an unsorted data structure, and
212220
// that can lead to nondeterminism in typeGlobals. Sort the vectors there to
213221
// ensure determinism.
@@ -528,6 +536,53 @@ struct GlobalStructInference : public Pass {
528536
right));
529537
}
530538

539+
void visitRefCast(RefCast* curr) {
540+
// When we see (ref.cast $T), and the type has a descriptor, and that
541+
// desceriptor only has a single global, then we can do (ref.cast_desc)
542+
// using the descriptor. Descriptor XXX
543+
// casts are usually more efficient than normal ones (and even more so
544+
// if we get lucky and are in a loop, where the global.get of the
545+
// descriptor can be hoisted).
546+
547+
// Check if we have a descriptor.
548+
auto type = curr->type;
549+
if (type == Type::unreachable) {
550+
return;
551+
}
552+
auto heapType = type.getHeapType();
553+
auto desc = heapType.getDescriptorType();
554+
if (!desc) {
555+
return;
556+
}
557+
558+
// Check if the type has no subtypes, as a ref.cast_desc will find
559+
// precisely that type and nothing else.
560+
if (!parent.subTypes->getStrictSubTypes(heapType).empty()) {
561+
return;
562+
}
563+
564+
// Check if we have a single global for the descriptor.
565+
auto iter = parent.typeGlobals.find(*desc);
566+
if (iter == parent.typeGlobals.end()) {
567+
return;
568+
}
569+
const auto& globals = iter->second;
570+
if (globals.size() != 1) {
571+
return;
572+
}
573+
574+
// We can optimize!
575+
auto global = globals[0];
576+
auto& wasm = *getModule();
577+
Builder builder(wasm);
578+
auto* getGlobal =
579+
builder.makeGlobalGet(global, wasm.getGlobal(global)->type);
580+
auto* castDesc = builder.makeRefCast(curr->ref, getGlobal, curr->type);
581+
replaceCurrent(castDesc);
582+
583+
// TODO nullable cast?
584+
}
585+
531586
void visitFunction(Function* func) {
532587
if (refinalize) {
533588
ReFinalize().walkFunctionInModule(func, getModule());

0 commit comments

Comments
 (0)