Bug 1845436 - wasm: Always use the first occuring type index when there is a canonical type. r=yury

Module serialization needs a map from type def pointer to type index. When we have
structurally identical type definitions, we have multiple options of what to use
in the map. Right now we used the last occuring type index in the module. This
caused us to encode type indices while serializing that point to types we haven't
decoded yet, running into errors. This commit changes us to keep the first type
index that we had for the canonical type, to avoid this.

Differential Revision: https://phabricator.services.mozilla.com/D185202
This commit is contained in:
Ryan Hunt 2023-08-08 20:20:35 +00:00
parent 0e950091a9
commit 561fb781ba
2 changed files with 22 additions and 3 deletions

View File

@ -0,0 +1,10 @@
// |jit-test| skip-if: !wasmGcEnabled(); --wasm-test-serialization
// Test that serialization doesn't create a forward reference to the third
// struct when serializing the reference to the first struct, which is
// structurally identical to the first struct.
wasmEvalText(`(module
(type (;0;) (struct))
(type (;2;) (struct (field (ref 0))))
(type (;3;) (struct))
)`);

View File

@ -1186,10 +1186,19 @@ class TypeContext : public AtomicRefCounted<TypeContext> {
groupTypeIndex++) {
uint32_t typeIndex = length() - recGroup->numTypes() + groupTypeIndex;
const TypeDef* oldTypeDef = types_[typeIndex];
const TypeDef* newTypeDef = &canonicalRecGroup->type(groupTypeIndex);
types_[typeIndex] = newTypeDef;
const TypeDef* canonTypeDef = &canonicalRecGroup->type(groupTypeIndex);
types_[typeIndex] = canonTypeDef;
moduleIndices_.remove(oldTypeDef);
if (!moduleIndices_.put(newTypeDef, typeIndex)) {
// Ensure there is an module index entry pointing to the canonical type
// definition. Don't overwrite it if it already exists, serialization
// relies on the module index map pointing to the first occurrence of a
// type definition to avoid creating forward references that didn't exist
// in the original module.
auto canonTypeIndexEntry = moduleIndices_.lookupForAdd(canonTypeDef);
if (!canonTypeIndexEntry &&
!moduleIndices_.add(canonTypeIndexEntry, canonTypeDef, typeIndex)) {
return false;
}
}