Repository navigation
Conversation
In `GlobalStructInference::analyzeClosedWorld`, `unoptimizable` types and `typeGlobals` are propagated from subtypes up to all declared supertypes because a `struct.get` or `ref.get_desc` on a non-exact reference to `$super` might access an instance of any subtype `$sub`. However, `FunctionOptimizer::optimize` also looked up `typeGlobals[heapType]` when the reference operand had an exact type `(ref null? (exact $super))`, which can never hold an instance of a strict subtype `$sub` at runtime. When optimizing `(ref.get_desc $super ref)` on an exact reference of type `(ref (exact $super))`, including globals that initialize a strict subtype `$sub` caused `getReadValue` to produce descriptors of type `(ref (exact $sub.desc))`, which is not a subtype of `(ref (exact $super.desc))`, widening the `select` result type to non-exact `(ref $super.desc)` and failing validation. Save `exactTypeGlobals` after erasing directly unoptimizable types and before propagating unoptimizability and globals from subtypes to supertypes, and consult `exactTypeGlobals` in `FunctionOptimizer::optimize` when `ref->type.isExact()`.
There was a problem hiding this comment.
Code Review
This pull request introduces exactTypeGlobals to the GlobalStructInference pass to optimize reads of exact references, which cannot refer to strict subtypes. This allows exact references to be optimized even when their supertypes or subtypes are unoptimizable. The feedback suggests sorting the vectors in exactTypeGlobals lexicographically to ensure determinism and consistency in the optimization output.
| for (auto type : unoptimizable) { | ||
| typeGlobals.erase(type); | ||
| } | ||
| exactTypeGlobals = typeGlobals; |
There was a problem hiding this comment.
To ensure determinism and consistency, the vectors in exactTypeGlobals should be sorted lexicographically, just like typeGlobals is sorted at the end of analyzeClosedWorld. Since exactTypeGlobals is not modified after this copy, sorting it here guarantees that the optimization output remains independent of the order of globals in the module.
| exactTypeGlobals = typeGlobals; | |
| exactTypeGlobals = typeGlobals; | |
| for (auto& [type, globals] : exactTypeGlobals) { | |
| std::sort(globals.begin(), globals.end()); | |
| } |
In
GlobalStructInference::analyzeClosedWorld,unoptimizabletypes andtypeGlobalsare propagated from subtypes up to all declared supertypes because astruct.getorref.get_descon a non-exact reference to$supermight access an instance of any subtype$sub. However,FunctionOptimizer::optimizealso looked uptypeGlobals[heapType]when the reference operand had an exact type(ref null? (exact $super)), which can never hold an instance of a strict subtype$subat runtime. When optimizing(ref.get_desc $super ref)on an exact reference of type(ref (exact $super)), including globals that initialize a strict subtype$subcausedgetReadValueto produce descriptors of type(ref (exact $sub.desc)), which is not a subtype of(ref (exact $super.desc)), widening theselectresult type to non-exact(ref $super.desc)and failing validation.Save
exactTypeGlobalsafter erasing directly unoptimizable types and before propagating unoptimizability and globals from subtypes to supertypes, and consultexactTypeGlobalsinFunctionOptimizer::optimizewhenref->type.isExact().