Bug 1359027 - Move funcExports and funcImports to tiered Metadata. r=luke
authorLars T Hansen <lhansen@mozilla.com>
Fri, 19 May 2017 10:19:09 +0200
changeset 408084 2bad73fce12b75d5e495409a48377dce07b2f9d3
parent 408083 5187ecd492fc7f98e43d15ef1256946a820e5327
child 408085 22e4abf1e4e7e330fc9eb855f5a2e4ace44774f3
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1359027
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1359027 - Move funcExports and funcImports to tiered Metadata. r=luke
js/src/wasm/WasmCode.cpp
js/src/wasm/WasmCode.h
js/src/wasm/WasmFrameIterator.cpp
js/src/wasm/WasmGenerator.cpp
js/src/wasm/WasmInstance.cpp
js/src/wasm/WasmJS.cpp
js/src/wasm/WasmModule.cpp
--- a/js/src/wasm/WasmCode.cpp
+++ b/js/src/wasm/WasmCode.cpp
@@ -443,103 +443,103 @@ CacheableChars::sizeOfExcludingThis(Mall
     return mallocSizeOf(get());
 }
 
 size_t
 MetadataTier::serializedSize() const
 {
     return SerializedPodVectorSize(memoryAccesses) +
            SerializedPodVectorSize(codeRanges) +
-           SerializedPodVectorSize(callSites);
+           SerializedPodVectorSize(callSites) +
+           SerializedVectorSize(funcImports) +
+           SerializedVectorSize(funcExports);
 }
 
 size_t
 MetadataTier::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
 {
     return memoryAccesses.sizeOfExcludingThis(mallocSizeOf) +
            codeRanges.sizeOfExcludingThis(mallocSizeOf) +
-           callSites.sizeOfExcludingThis(mallocSizeOf);
+           callSites.sizeOfExcludingThis(mallocSizeOf) +
+           SizeOfVectorExcludingThis(funcImports, mallocSizeOf) +
+           SizeOfVectorExcludingThis(funcExports, mallocSizeOf);
 }
 
 uint8_t*
 MetadataTier::serialize(uint8_t* cursor) const
 {
     MOZ_ASSERT(debugTrapFarJumpOffsets.empty() && debugFuncToCodeRange.empty());
     cursor = SerializePodVector(cursor, memoryAccesses);
     cursor = SerializePodVector(cursor, codeRanges);
     cursor = SerializePodVector(cursor, callSites);
+    cursor = SerializeVector(cursor, funcImports);
+    cursor = SerializeVector(cursor, funcExports);
     return cursor;
 }
 
 /* static */ const uint8_t*
 MetadataTier::deserialize(const uint8_t* cursor)
 {
     (cursor = DeserializePodVector(cursor, &memoryAccesses)) &&
     (cursor = DeserializePodVector(cursor, &codeRanges)) &&
-    (cursor = DeserializePodVector(cursor, &callSites));
+    (cursor = DeserializePodVector(cursor, &callSites)) &&
+    (cursor = DeserializeVector(cursor, &funcImports)) &&
+    (cursor = DeserializeVector(cursor, &funcExports));
     debugTrapFarJumpOffsets.clear();
     debugFuncToCodeRange.clear();
     return cursor;
 }
 
 size_t
 Metadata::serializedSize() const
 {
     return sizeof(pod()) +
            tier().serializedSize() +
-           SerializedVectorSize(funcImports) +
-           SerializedVectorSize(funcExports) +
            SerializedVectorSize(sigIds) +
            SerializedPodVectorSize(globals) +
            SerializedPodVectorSize(tables) +
            SerializedPodVectorSize(funcNames) +
            SerializedPodVectorSize(customSections) +
            filename.serializedSize() +
            sizeof(hash);
 }
 
 size_t
 Metadata::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
 {
     return tier().sizeOfExcludingThis(mallocSizeOf) +
-           SizeOfVectorExcludingThis(funcImports, mallocSizeOf) +
-           SizeOfVectorExcludingThis(funcExports, mallocSizeOf) +
            SizeOfVectorExcludingThis(sigIds, mallocSizeOf) +
            globals.sizeOfExcludingThis(mallocSizeOf) +
            tables.sizeOfExcludingThis(mallocSizeOf) +
            funcNames.sizeOfExcludingThis(mallocSizeOf) +
            customSections.sizeOfExcludingThis(mallocSizeOf) +
            filename.sizeOfExcludingThis(mallocSizeOf);
 }
 
 uint8_t*
 Metadata::serialize(uint8_t* cursor) const
 {
     MOZ_ASSERT(!debugEnabled && debugFuncArgTypes.empty() && debugFuncReturnTypes.empty());
     cursor = WriteBytes(cursor, &pod(), sizeof(pod()));
     cursor = tier().serialize(cursor);
-    cursor = SerializeVector(cursor, funcImports);
-    cursor = SerializeVector(cursor, funcExports);
     cursor = SerializeVector(cursor, sigIds);
     cursor = SerializePodVector(cursor, globals);
     cursor = SerializePodVector(cursor, tables);
     cursor = SerializePodVector(cursor, funcNames);
     cursor = SerializePodVector(cursor, customSections);
     cursor = filename.serialize(cursor);
     cursor = WriteBytes(cursor, hash, sizeof(hash));
     return cursor;
 }
 
 /* static */ const uint8_t*
 Metadata::deserialize(const uint8_t* cursor)
 {
     (cursor = ReadBytes(cursor, &pod(), sizeof(pod()))) &&
     (cursor = tier().deserialize(cursor)) &&
-    (cursor = DeserializeVector(cursor, &funcImports)) &&
-    (cursor = DeserializeVector(cursor, &funcExports)) &&
     (cursor = DeserializeVector(cursor, &sigIds)) &&
     (cursor = DeserializePodVector(cursor, &globals)) &&
     (cursor = DeserializePodVector(cursor, &tables)) &&
     (cursor = DeserializePodVector(cursor, &funcNames)) &&
     (cursor = DeserializePodVector(cursor, &customSections)) &&
     (cursor = filename.deserialize(cursor)) &&
     (cursor = ReadBytes(cursor, hash, sizeof(hash)));
     debugEnabled = false;
@@ -558,16 +558,17 @@ struct ProjectFuncIndex
     uint32_t operator[](size_t index) const {
         return funcExports[index].funcIndex();
     }
 };
 
 const FuncExport&
 Metadata::lookupFuncExport(uint32_t funcIndex) const
 {
+    const FuncExportVector& funcExports = tier().funcExports;
     size_t match;
     if (!BinarySearch(ProjectFuncIndex(funcExports), 0, funcExports.length(), funcIndex, &match))
         MOZ_CRASH("missing function export");
 
     return funcExports[match];
 }
 
 bool
--- a/js/src/wasm/WasmCode.h
+++ b/js/src/wasm/WasmCode.h
@@ -153,17 +153,17 @@ class CodeSegment
 // function definition index.
 
 class FuncExport
 {
     Sig sig_;
     MOZ_INIT_OUTSIDE_CTOR struct CacheablePod {
         uint32_t funcIndex_;
         uint32_t codeRangeIndex_;
-        uint32_t entryOffset_;
+        uint32_t entryOffset_;      // Machine code offset
     } pod;
 
   public:
     FuncExport() = default;
     explicit FuncExport(Sig&& sig,
                         uint32_t funcIndex,
                         uint32_t codeRangeIndex)
       : sig_(Move(sig))
@@ -202,18 +202,18 @@ typedef Vector<FuncExport, 0, SystemAllo
 // offsets of these stubs are stored so that function-import callsites can be
 // dynamically patched at runtime.
 
 class FuncImport
 {
     Sig sig_;
     struct CacheablePod {
         uint32_t tlsDataOffset_;
-        uint32_t interpExitCodeOffset_;
-        uint32_t jitExitCodeOffset_;
+        uint32_t interpExitCodeOffset_; // Machine code offset
+        uint32_t jitExitCodeOffset_;    // Machine code offset
     } pod;
 
   public:
     FuncImport() {
         memset(&pod, 0, sizeof(CacheablePod));
     }
 
     FuncImport(Sig&& sig, uint32_t tlsDataOffset)
@@ -334,16 +334,18 @@ struct MetadataCacheablePod
 
 typedef uint8_t ModuleHash[8];
 
 struct MetadataTier
 {
     MemoryAccessVector    memoryAccesses;
     CodeRangeVector       codeRanges;
     CallSiteVector        callSites;
+    FuncImportVector      funcImports;
+    FuncExportVector      funcExports;
 
     // Debug information, not serialized.
     Uint32Vector          debugTrapFarJumpOffsets;
     Uint32Vector          debugFuncToCodeRange;
 
     WASM_DECLARE_SERIALIZABLE(MetadataTier);
 };
 
@@ -362,18 +364,16 @@ struct Metadata : ShareableBase<Metadata
       : MetadataCacheablePod(kind),
         tier_(Move(tier))
     {}
     virtual ~Metadata() {}
 
     MetadataCacheablePod& pod() { return *this; }
     const MetadataCacheablePod& pod() const { return *this; }
 
-    FuncImportVector      funcImports;
-    FuncExportVector      funcExports;
     SigWithIdVector       sigIds;
     GlobalDescVector      globals;
     TableDescVector       tables;
     NameInBytecodeVector  funcNames;
     CustomSectionVector   customSections;
     CacheableChars        filename;
     ModuleHash            hash;
 
--- a/js/src/wasm/WasmFrameIterator.cpp
+++ b/js/src/wasm/WasmFrameIterator.cpp
@@ -209,17 +209,17 @@ FrameIterator::unwoundAddressOfReturnAdd
 
 bool
 FrameIterator::debugEnabled() const
 {
     MOZ_ASSERT(!done());
 
     // Only non-imported functions can have debug frames.
     return code_->metadata().debugEnabled &&
-           codeRange_->funcIndex() >= code_->metadata().funcImports.length();
+           codeRange_->funcIndex() >= code_->metadataTier().funcImports.length();
 }
 
 DebugFrame*
 FrameIterator::debugFrame() const
 {
     MOZ_ASSERT(!done());
     MOZ_ASSERT(debugEnabled());
     return reinterpret_cast<DebugFrame*>((uint8_t*)fp_ - DebugFrame::offsetOfFrame());
--- a/js/src/wasm/WasmGenerator.cpp
+++ b/js/src/wasm/WasmGenerator.cpp
@@ -509,42 +509,42 @@ ModuleGenerator::finishFuncExports()
     if (!sorted.reserve(exportedFuncs_.count()))
         return false;
 
     for (Uint32Set::Range r = exportedFuncs_.all(); !r.empty(); r.popFront())
         sorted.infallibleAppend(r.front());
 
     std::sort(sorted.begin(), sorted.end());
 
-    MOZ_ASSERT(metadata_->funcExports.empty());
-    if (!metadata_->funcExports.reserve(sorted.length()))
+    MOZ_ASSERT(metadataTier_->funcExports.empty());
+    if (!metadataTier_->funcExports.reserve(sorted.length()))
         return false;
 
     for (uint32_t funcIndex : sorted) {
         Sig sig;
         if (!sig.clone(funcSig(funcIndex)))
             return false;
 
         uint32_t codeRangeIndex = funcToCodeRange_[funcIndex];
-        metadata_->funcExports.infallibleEmplaceBack(Move(sig), funcIndex, codeRangeIndex);
+        metadataTier_->funcExports.infallibleEmplaceBack(Move(sig), funcIndex, codeRangeIndex);
     }
 
     return true;
 }
 
 typedef Vector<Offsets, 0, SystemAllocPolicy> OffsetVector;
 typedef Vector<CallableOffsets, 0, SystemAllocPolicy> CallableOffsetVector;
 
 bool
 ModuleGenerator::finishCodegen()
 {
     masm_.haltingAlign(CodeAlignment);
     uint32_t offsetInWhole = masm_.size();
 
-    uint32_t numFuncExports = metadata_->funcExports.length();
+    uint32_t numFuncExports = metadataTier_->funcExports.length();
     MOZ_ASSERT(numFuncExports == exportedFuncs_.count());
 
     // Generate stubs in a separate MacroAssembler since, otherwise, for modules
     // larger than the JumpImmediateRange, even local uses of Label will fail
     // due to the large absolute offsets temporarily stored by Label::bind().
 
     OffsetVector entries;
     CallableOffsetVector interpExits;
@@ -559,25 +559,25 @@ ModuleGenerator::finishCodegen()
     {
         TempAllocator alloc(&lifo_);
         MacroAssembler masm(MacroAssembler::WasmToken(), alloc);
         Label throwLabel;
 
         if (!entries.resize(numFuncExports))
             return false;
         for (uint32_t i = 0; i < numFuncExports; i++)
-            entries[i] = GenerateEntry(masm, metadata_->funcExports[i]);
+            entries[i] = GenerateEntry(masm, metadataTier_->funcExports[i]);
 
         if (!interpExits.resize(numFuncImports()))
             return false;
         if (!jitExits.resize(numFuncImports()))
             return false;
         for (uint32_t i = 0; i < numFuncImports(); i++) {
-            interpExits[i] = GenerateImportInterpExit(masm, metadata_->funcImports[i], i, &throwLabel);
-            jitExits[i] = GenerateImportJitExit(masm, metadata_->funcImports[i], &throwLabel);
+            interpExits[i] = GenerateImportInterpExit(masm, metadataTier_->funcImports[i], i, &throwLabel);
+            jitExits[i] = GenerateImportJitExit(masm, metadataTier_->funcImports[i], &throwLabel);
         }
 
         for (Trap trap : MakeEnumeratedRange(Trap::Limit))
             trapExits[trap] = GenerateTrapExit(masm, trap, &throwLabel);
 
         outOfBoundsExit = GenerateOutOfBoundsExit(masm, &throwLabel);
         unalignedAccessExit = GenerateUnalignedExit(masm, &throwLabel);
         interruptExit = GenerateInterruptExit(masm, &throwLabel);
@@ -588,29 +588,29 @@ ModuleGenerator::finishCodegen()
             return false;
     }
 
     // Adjust each of the resulting Offsets (to account for being merged into
     // masm_) and then create code ranges for all the stubs.
 
     for (uint32_t i = 0; i < numFuncExports; i++) {
         entries[i].offsetBy(offsetInWhole);
-        metadata_->funcExports[i].initEntryOffset(entries[i].begin);
+        metadataTier_->funcExports[i].initEntryOffset(entries[i].begin);
         if (!metadataTier_->codeRanges.emplaceBack(CodeRange::Entry, entries[i]))
             return false;
     }
 
     for (uint32_t i = 0; i < numFuncImports(); i++) {
         interpExits[i].offsetBy(offsetInWhole);
-        metadata_->funcImports[i].initInterpExitOffset(interpExits[i].begin);
+        metadataTier_->funcImports[i].initInterpExitOffset(interpExits[i].begin);
         if (!metadataTier_->codeRanges.emplaceBack(CodeRange::ImportInterpExit, interpExits[i]))
             return false;
 
         jitExits[i].offsetBy(offsetInWhole);
-        metadata_->funcImports[i].initJitExitOffset(jitExits[i].begin);
+        metadataTier_->funcImports[i].initJitExitOffset(jitExits[i].begin);
         if (!metadataTier_->codeRanges.emplaceBack(CodeRange::ImportJitExit, jitExits[i]))
             return false;
     }
 
     for (Trap trap : MakeEnumeratedRange(Trap::Limit)) {
         trapExits[trap].offsetBy(offsetInWhole);
         if (!metadataTier_->codeRanges.emplaceBack(CodeRange::TrapExit, trapExits[trap]))
             return false;
@@ -693,17 +693,17 @@ bool
 ModuleGenerator::addFuncImport(const Sig& sig, uint32_t globalDataOffset)
 {
     MOZ_ASSERT(!finishedFuncDefs_);
 
     Sig copy;
     if (!copy.clone(sig))
         return false;
 
-    return metadata_->funcImports.emplaceBack(Move(copy), globalDataOffset);
+    return metadataTier_->funcImports.emplaceBack(Move(copy), globalDataOffset);
 }
 
 bool
 ModuleGenerator::allocateGlobalBytes(uint32_t bytes, uint32_t align, uint32_t* globalDataOffset)
 {
     CheckedInt<uint32_t> newGlobalDataLength(linkData_.globalDataLength);
 
     newGlobalDataLength += ComputeByteAlignment(newGlobalDataLength.value(), align);
@@ -830,27 +830,27 @@ ModuleGenerator::initImport(uint32_t fun
 
     uint32_t globalDataOffset;
     if (!allocateGlobalBytes(sizeof(FuncImportTls), sizeof(void*), &globalDataOffset))
         return false;
 
     MOZ_ASSERT(!env_->funcImportGlobalDataOffsets[funcIndex]);
     env_->funcImportGlobalDataOffsets[funcIndex] = globalDataOffset;
 
-    MOZ_ASSERT(funcIndex == metadata_->funcImports.length());
+    MOZ_ASSERT(funcIndex == metadataTier_->funcImports.length());
     return addFuncImport(sig(sigIndex), globalDataOffset);
 }
 
 uint32_t
 ModuleGenerator::numFuncImports() const
 {
     // Until all functions have been validated, asm.js doesn't know the total
     // number of imports.
     MOZ_ASSERT_IF(isAsmJS(), finishedFuncDefs_);
-    return metadata_->funcImports.length();
+    return metadataTier_->funcImports.length();
 }
 
 const SigWithId&
 ModuleGenerator::funcSig(uint32_t funcIndex) const
 {
     MOZ_ASSERT(env_->funcSigs[funcIndex]);
     return *env_->funcSigs[funcIndex];
 }
@@ -1011,17 +1011,17 @@ ModuleGenerator::finishFuncDefs()
     finishedFuncDefs_ = true;
 
     // Generate wrapper functions for every import. These wrappers turn imports
     // into plain functions so they can be put into tables and re-exported.
     // asm.js cannot do either and so no wrappers are generated.
 
     if (!isAsmJS()) {
         for (size_t funcIndex = 0; funcIndex < numFuncImports(); funcIndex++) {
-            const FuncImport& funcImport = metadata_->funcImports[funcIndex];
+            const FuncImport& funcImport = metadataTier_->funcImports[funcIndex];
             const SigWithId& sig = funcSig(funcIndex);
 
             FuncOffsets offsets = GenerateImportFunction(masm_, funcImport, sig.id);
             if (masm_.oom())
                 return false;
 
             uint32_t codeRangeIndex = metadataTier_->codeRanges.length();
             if (!metadataTier_->codeRanges.emplaceBack(funcIndex, /* bytecodeOffset = */ 0, offsets))
--- a/js/src/wasm/WasmInstance.cpp
+++ b/js/src/wasm/WasmInstance.cpp
@@ -122,17 +122,17 @@ Instance::tableTls(const TableDesc& td) 
 {
     return *(TableTls*)(globalSegment().globalData() + td.globalDataOffset);
 }
 
 bool
 Instance::callImport(JSContext* cx, uint32_t funcImportIndex, unsigned argc, const uint64_t* argv,
                      MutableHandleValue rval)
 {
-    const FuncImport& fi = metadata().funcImports[funcImportIndex];
+    const FuncImport& fi = metadataTier().funcImports[funcImportIndex];
 
     InvokeArgs args(cx);
     if (!args.init(cx, argc))
         return false;
 
     bool hasI64Arg = false;
     MOZ_ASSERT(fi.sig().args().length() == argc);
     for (size_t i = 0; i < argc; i++) {
@@ -330,31 +330,31 @@ Instance::Instance(JSContext* cx,
     object_(object),
     code_(code),
     debug_(Move(debug)),
     globals_(Move(globals)),
     memory_(memory),
     tables_(Move(tables)),
     enterFrameTrapsEnabled_(false)
 {
-    MOZ_ASSERT(funcImports.length() == metadata().funcImports.length());
+    MOZ_ASSERT(funcImports.length() == metadataTier().funcImports.length());
     MOZ_ASSERT(tables_.length() == metadata().tables.length());
 
     tlsData()->cx = cx;
     tlsData()->instance = this;
     tlsData()->globalData = globals_->globalData();
     tlsData()->memoryBase = memory ? memory->buffer().dataPointerEither().unwrap() : nullptr;
 #ifndef WASM_HUGE_MEMORY
     tlsData()->boundsCheckLimit = memory ? memory->buffer().wasmBoundsCheckLimit() : 0;
 #endif
     tlsData()->stackLimit = *(void**)cx->stackLimitAddressForJitCode(JS::StackForUntrustedScript);
 
-    for (size_t i = 0; i < metadata().funcImports.length(); i++) {
+    for (size_t i = 0; i < metadataTier().funcImports.length(); i++) {
         HandleFunction f = funcImports[i];
-        const FuncImport& fi = metadata().funcImports[i];
+        const FuncImport& fi = metadataTier().funcImports[i];
         FuncImportTls& import = funcImportTls(fi);
         if (!isAsmJS() && IsExportedWasmFunction(f)) {
             WasmInstanceObject* calleeInstanceObj = ExportedFunctionToInstanceObject(f);
             const CodeRange& codeRange = calleeInstanceObj->getExportedFunctionCodeRange(f);
             Instance& calleeInstance = calleeInstanceObj->instance();
             import.tls = calleeInstance.tlsData();
             import.code = calleeInstance.codeSegment().base() + codeRange.funcNormalEntry();
             import.baselineScript = nullptr;
@@ -442,18 +442,18 @@ Instance::init(JSContext* cx)
 
     return true;
 }
 
 Instance::~Instance()
 {
     compartment_->wasm.unregisterInstance(*this);
 
-    for (unsigned i = 0; i < metadata().funcImports.length(); i++) {
-        FuncImportTls& import = funcImportTls(metadata().funcImports[i]);
+    for (unsigned i = 0; i < metadataTier().funcImports.length(); i++) {
+        FuncImportTls& import = funcImportTls(metadataTier().funcImports[i]);
         if (import.baselineScript)
             import.baselineScript->removeDependentWasmImport(*this, i);
     }
 
     if (!metadata().sigIds.empty()) {
         ExclusiveData<SigIdSet>::Guard lockedSigIdSet = sigIdSet->lock();
 
         for (const SigWithId& sig : metadata().sigIds) {
@@ -490,17 +490,17 @@ Instance::tracePrivate(JSTracer* trc)
 {
     // This method is only called from WasmInstanceObject so the only reason why
     // TraceEdge is called is so that the pointer can be updated during a moving
     // GC. TraceWeakEdge may sound better, but it is less efficient given that
     // we know object_ is already marked.
     MOZ_ASSERT(!gc::IsAboutToBeFinalized(&object_));
     TraceEdge(trc, &object_, "wasm instance object");
 
-    for (const FuncImport& fi : metadata().funcImports)
+    for (const FuncImport& fi : metadataTier().funcImports)
         TraceNullableEdge(trc, &funcImportTls(fi).obj, "wasm import");
 
     for (const SharedTable& table : tables_)
         table->trace(trc);
 
     TraceNullableEdge(trc, &memory_, "wasm buffer");
 }
 
@@ -799,17 +799,17 @@ Instance::onMovingGrowTable()
     TableTls& table = tableTls(metadata().tables[0]);
     table.length = tables_[0]->length();
     table.base = tables_[0]->base();
 }
 
 void
 Instance::deoptimizeImportExit(uint32_t funcImportIndex)
 {
-    const FuncImport& fi = metadata().funcImports[funcImportIndex];
+    const FuncImport& fi = metadataTier().funcImports[funcImportIndex];
     FuncImportTls& import = funcImportTls(fi);
     import.code = codeBase() + fi.interpExitCodeOffset();
     import.baselineScript = nullptr;
 }
 
 void
 Instance::ensureEnterFrameTrapsState(JSContext* cx, bool enabled)
 {
--- a/js/src/wasm/WasmJS.cpp
+++ b/js/src/wasm/WasmJS.cpp
@@ -670,17 +670,17 @@ WasmModuleObject::imports(JSContext* cx,
         props.infallibleAppend(IdValuePair(NameToId(cx->names().name), StringValue(nameStr)));
 
         JSString* kindStr = KindToString(cx, names, import.kind);
         if (!kindStr)
             return false;
         props.infallibleAppend(IdValuePair(NameToId(names.kind), StringValue(kindStr)));
 
         if (JitOptions.wasmTestMode && import.kind == DefinitionKind::Function) {
-            JSString* sigStr = SigToString(cx, module->metadata().funcImports[numFuncImport++].sig());
+            JSString* sigStr = SigToString(cx, module->metadataTier().funcImports[numFuncImport++].sig());
             if (!sigStr)
                 return false;
             if (!props.append(IdValuePair(NameToId(names.signature), StringValue(sigStr))))
                 return false;
         }
 
         JSObject* obj = ObjectGroup::newPlainObject(cx, props.begin(), props.length(), GenericObject);
         if (!obj)
@@ -726,17 +726,17 @@ WasmModuleObject::exports(JSContext* cx,
         props.infallibleAppend(IdValuePair(NameToId(cx->names().name), StringValue(nameStr)));
 
         JSString* kindStr = KindToString(cx, names, exp.kind());
         if (!kindStr)
             return false;
         props.infallibleAppend(IdValuePair(NameToId(names.kind), StringValue(kindStr)));
 
         if (JitOptions.wasmTestMode && exp.kind() == DefinitionKind::Function) {
-            JSString* sigStr = SigToString(cx, module->metadata().funcExports[numFuncExport++].sig());
+            JSString* sigStr = SigToString(cx, module->metadataTier().funcExports[numFuncExport++].sig());
             if (!sigStr)
                 return false;
             if (!props.append(IdValuePair(NameToId(names.signature), StringValue(sigStr))))
                 return false;
         }
 
         JSObject* obj = ObjectGroup::newPlainObject(cx, props.begin(), props.length(), GenericObject);
         if (!obj)
--- a/js/src/wasm/WasmModule.cpp
+++ b/js/src/wasm/WasmModule.cpp
@@ -558,31 +558,31 @@ FindImportForFuncImport(const ImportVect
         funcImportIndex--;
     }
     MOZ_CRASH("ran out of imports");
 }
 
 bool
 Module::instantiateFunctions(JSContext* cx, Handle<FunctionVector> funcImports) const
 {
-    MOZ_ASSERT(funcImports.length() == metadata().funcImports.length());
+    MOZ_ASSERT(funcImports.length() == metadataTier().funcImports.length());
 
     if (metadata().isAsmJS())
         return true;
 
-    for (size_t i = 0; i < metadata().funcImports.length(); i++) {
+    for (size_t i = 0; i < metadataTier().funcImports.length(); i++) {
         HandleFunction f = funcImports[i];
         if (!IsExportedFunction(f) || ExportedFunctionToInstance(f).isAsmJS())
             continue;
 
         uint32_t funcIndex = ExportedFunctionToFuncIndex(f);
         Instance& instance = ExportedFunctionToInstance(f);
         const FuncExport& funcExport = instance.metadata().lookupFuncExport(funcIndex);
 
-        if (funcExport.sig() != metadata().funcImports[i].sig()) {
+        if (funcExport.sig() != metadataTier().funcImports[i].sig()) {
             const Import& import = FindImportForFuncImport(imports_, i);
             JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_IMPORT_SIG,
                                       import.module.get(), import.field.get());
             return false;
         }
     }
 
     return true;