@@ -248,6 +248,30 @@ struct ShapeHash {
248248 size_t operator ()(const HeapType& type) const { return shapeHash (type); }
249249};
250250
251+ // The supertypes of each type in a descriptor chain. Hash and equality-compare
252+ // them using real identity to identify siblings chains that share the same
253+ // supertypes.
254+ using ChainSupers = std::vector<std::optional<HeapType>>;
255+
256+ struct ChainSupersEq {
257+ bool operator ()(const ChainSupers& a, const ChainSupers& b) const {
258+ return a == b;
259+ }
260+ };
261+
262+ struct ChainSupersHash {
263+ size_t operator ()(const ChainSupers& supers) const {
264+ auto digest = wasm::hash (supers.size ());
265+ for (auto & super : supers) {
266+ wasm::rehash (digest, !!super);
267+ if (super) {
268+ wasm::rehash (digest, *super);
269+ }
270+ }
271+ return digest;
272+ }
273+ };
274+
251275void TypeMerging::run (Module* module_) {
252276 module = module_;
253277
@@ -339,8 +363,10 @@ bool TypeMerging::merge(MergeKind kind) {
339363 // that siblings that refine the supertype in the same way can be assigned to
340364 // the same partition and potentially merged.
341365 std::unordered_map<
342- std::optional<HeapType>,
343- std::unordered_map<HeapType, Partitions::iterator, ShapeHash, ShapeEq>>
366+ std::vector<std::optional<HeapType>>,
367+ std::unordered_map<HeapType, Partitions::iterator, ShapeHash, ShapeEq>,
368+ ChainSupersHash,
369+ ChainSupersEq>
344370 shapePartitions;
345371
346372 // Ensure the type has a partition and return a reference to it. Since we
@@ -358,12 +384,16 @@ bool TypeMerging::merge(MergeKind kind) {
358384 // Similar to the above, but look up or create a partition associated with the
359385 // type's supertype and top-level shape rather than its identity.
360386 auto ensureShapePartition = [&](HeapType type) -> Partitions::iterator {
361- auto super = type.getDeclaredSuperType ();
362- if (super) {
363- super = getMerged (*super);
387+ ChainSupers supers;
388+ for (auto t : type.getDescriptorChain ()) {
389+ auto super = t.getDeclaredSuperType ();
390+ if (super) {
391+ super = getMerged (*super);
392+ }
393+ supers.push_back (super);
364394 }
365395 auto [it, inserted] =
366- shapePartitions[super ].insert ({type, partitions.end ()});
396+ shapePartitions[supers ].insert ({type, partitions.end ()});
367397 if (inserted) {
368398 it->second = partitions.insert (partitions.end (), Partition{});
369399 }
0 commit comments