From 81636eb525a015e6dd28932f348de1d4d3253845 Mon Sep 17 00:00:00 2001 From: Butkovits Atila Date: Tue, 9 Mar 2021 02:43:20 +0200 Subject: [PATCH] Backed out 14 changesets (bug 1693184, bug 1693611, bug 1693625) for causing failures on test_script_loader_js_cache.html. Backed out changeset 6f384df0be5c (bug 1693184) Backed out changeset 5353d36c4846 (bug 1693625) Backed out changeset 0069d43ee2c4 (bug 1693611) Backed out changeset 8fd50eba1621 (bug 1693611) Backed out changeset 4928193b996f (bug 1693611) Backed out changeset 7bf683fab589 (bug 1693611) Backed out changeset a4ff4b030aaa (bug 1693611) Backed out changeset 565bee5296ac (bug 1693611) Backed out changeset faacbf1943b6 (bug 1693611) Backed out changeset 72fc08b6245d (bug 1693611) Backed out changeset 6f06ff0ebbc3 (bug 1693611) Backed out changeset fb2c167165b8 (bug 1693611) Backed out changeset 0d66ecd8acd4 (bug 1693611) Backed out changeset 0e435a571803 (bug 1693611) --- js/src/frontend/ParserAtom.cpp | 36 +++- js/src/frontend/Stencil.cpp | 4 +- js/src/frontend/StencilXdr.cpp | 322 +++++++++++---------------------- js/src/frontend/StencilXdr.h | 53 +----- js/src/jsapi.cpp | 2 +- js/src/vm/HelperThreads.cpp | 2 +- js/src/vm/JSScript.cpp | 10 +- js/src/vm/Xdr.cpp | 162 ++++++++++++----- js/src/vm/Xdr.h | 91 +++++++--- 9 files changed, 344 insertions(+), 338 deletions(-) diff --git a/js/src/frontend/ParserAtom.cpp b/js/src/frontend/ParserAtom.cpp index c4c6e4d94ccb..2848c712e7df 100644 --- a/js/src/frontend/ParserAtom.cpp +++ b/js/src/frontend/ParserAtom.cpp @@ -16,8 +16,9 @@ #include "frontend/BytecodeCompiler.h" // IsIdentifier #include "frontend/CompilationStencil.h" #include "frontend/NameCollections.h" -#include "util/StringBuffer.h" // StringBuffer -#include "util/Text.h" // AsciiDigitToNumber +#include "frontend/StencilXdr.h" // CanCopyDataToDisk +#include "util/StringBuffer.h" // StringBuffer +#include "util/Text.h" // AsciiDigitToNumber #include "util/Unicode.h" #include "vm/JSContext.h" #include "vm/Printer.h" // Sprinter, QuoteString @@ -973,6 +974,37 @@ bool WellKnownParserAtoms::init(JSContext* cx) { } /* namespace frontend */ } /* namespace js */ +// XDR code. +namespace js { + +template +XDRResult XDRParserAtom(XDRState* xdr, ParserAtom** atomp) { + static_assert(CanCopyDataToDisk::value, + "ParserAtom cannot be bulk-copied to disk."); + + MOZ_TRY(xdr->align32()); + + const ParserAtom* header; + if (mode == XDR_ENCODE) { + header = *atomp; + } else { + MOZ_TRY(xdr->peekData(&header)); + } + + const uint32_t CharSize = + header->hasLatin1Chars() ? sizeof(JS::Latin1Char) : sizeof(char16_t); + uint32_t totalLength = sizeof(ParserAtom) + (CharSize * header->length()); + + MOZ_TRY(xdr->borrowedData(atomp, totalLength)); + + return Ok(); +} + +template XDRResult XDRParserAtom(XDRState* xdr, ParserAtom** atomp); +template XDRResult XDRParserAtom(XDRState* xdr, ParserAtom** atomp); + +} /* namespace js */ + bool JSRuntime::initializeParserAtoms(JSContext* cx) { MOZ_ASSERT(!commonParserNames); diff --git a/js/src/frontend/Stencil.cpp b/js/src/frontend/Stencil.cpp index 1bb50fb273ed..daba97b7a679 100644 --- a/js/src/frontend/Stencil.cpp +++ b/js/src/frontend/Stencil.cpp @@ -1387,7 +1387,7 @@ bool CompilationStencil::deserializeStencils(JSContext* cx, *succeededOut = false; } MOZ_ASSERT(parserAtomData.empty()); - XDRStencilDecoder decoder(cx, range); + XDRStencilDecoder decoder(cx, &input.options, range); XDRResult res = decoder.codeStencil(input, *this); if (res.isErr()) { @@ -3502,7 +3502,7 @@ JS::TranscodeResult JS::DecodeStencil(JSContext* cx, if (!stencil) { return TranscodeResult::Throw; } - XDRStencilDecoder decoder(cx, range); + XDRStencilDecoder decoder(cx, &options, range); XDRResult res = decoder.codeStencil(input.get(), *stencil); if (res.isErr()) { return res.unwrapErr(); diff --git a/js/src/frontend/StencilXdr.cpp b/js/src/frontend/StencilXdr.cpp index 842a02c9c651..54c52199c6fa 100644 --- a/js/src/frontend/StencilXdr.cpp +++ b/js/src/frontend/StencilXdr.cpp @@ -14,7 +14,6 @@ #include // std::has_unique_object_representations #include // std::forward -#include "ds/LifoAlloc.h" // LifoAlloc #include "frontend/CompilationStencil.h" // CompilationStencil #include "frontend/ScriptIndex.h" // ScriptIndex #include "vm/JSScript.h" // js::CheckCompileOptionsMatch @@ -99,14 +98,14 @@ static XDRResult XDRVectorContent(XDRState* xdr, Vector& vec) { } template -static XDRResult XDRSpanInitialized(XDRState* xdr, LifoAlloc& alloc, - mozilla::Span& span, uint32_t size) { +static XDRResult XDRSpanInitialized(XDRState* xdr, mozilla::Span& span, + uint32_t size) { MOZ_ASSERT_IF(mode == XDR_ENCODE, size == span.size()); if (mode == XDR_DECODE) { MOZ_ASSERT(span.empty()); if (size > 0) { - auto* p = alloc.template newArrayUninitialized(size); + auto* p = xdr->stencilAlloc().template newArrayUninitialized(size); if (!p) { js::ReportOutOfMemory(xdr->cx()); return xdr->fail(JS::TranscodeResult::Throw); @@ -159,34 +158,28 @@ static XDRResult XDRSpanContent(XDRState* xdr, mozilla::Span& span) { } template -/* static */ XDRResult StencilXDR::codeBigInt(XDRState* xdr, - BigIntStencil& stencil) { - uint32_t size; +static XDRResult XDRStencilModuleMetadata(XDRState* xdr, + StencilModuleMetadata& stencil) { + MOZ_TRY(XDRVectorContent(xdr, stencil.requestedModules)); + MOZ_TRY(XDRVectorContent(xdr, stencil.importEntries)); + MOZ_TRY(XDRVectorContent(xdr, stencil.localExportEntries)); + MOZ_TRY(XDRVectorContent(xdr, stencil.indirectExportEntries)); + MOZ_TRY(XDRVectorContent(xdr, stencil.starExportEntries)); + MOZ_TRY(XDRVectorContent(xdr, stencil.functionDecls)); + + uint8_t isAsync = 0; if (mode == XDR_ENCODE) { - size = stencil.source_.size(); + if (stencil.isAsync) { + isAsync = stencil.isAsync ? 1 : 0; + } } - MOZ_TRY(xdr->codeUint32(&size)); - return XDRSpanContent(xdr, stencil.source_, size); -} + MOZ_TRY(xdr->codeUint8(&isAsync)); -template -/* static */ XDRResult StencilXDR::codeObjLiteral(XDRState* xdr, - ObjLiteralStencil& stencil) { - uint8_t flags = 0; - - if (mode == XDR_ENCODE) { - flags = stencil.flags_.serialize(); - } - MOZ_TRY(xdr->codeUint8(&flags)); if (mode == XDR_DECODE) { - stencil.flags_.deserialize(flags); + stencil.isAsync = isAsync == 1; } - MOZ_TRY(xdr->codeUint32(&stencil.propertyCount_)); - - MOZ_TRY(XDRSpanContent(xdr, stencil.code_)); - return Ok(); } @@ -200,7 +193,7 @@ template } template -/* static */ XDRResult StencilXDR::codeScopeData( +/* static */ XDRResult StencilXDR::ScopeData( XDRState* xdr, ScopeStencil& stencil, BaseParserScopeData*& baseScopeData) { // WasmInstanceScope & WasmFunctionScope should not appear in stencils. @@ -238,10 +231,42 @@ template return Ok(); } +template +/* static */ XDRResult StencilXDR::ObjLiteral(XDRState* xdr, + ObjLiteralStencil& stencil) { + uint8_t flags = 0; + + if (mode == XDR_ENCODE) { + flags = stencil.flags_.serialize(); + } + MOZ_TRY(xdr->codeUint8(&flags)); + if (mode == XDR_DECODE) { + stencil.flags_.deserialize(flags); + } + + MOZ_TRY(xdr->codeUint32(&stencil.propertyCount_)); + + MOZ_TRY(XDRSpanContent(xdr, stencil.code_)); + + return Ok(); +} + +template +/* static */ XDRResult StencilXDR::BigInt(XDRState* xdr, + BigIntStencil& stencil) { + uint32_t size; + if (mode == XDR_ENCODE) { + size = stencil.source_.size(); + } + MOZ_TRY(xdr->codeUint32(&size)); + + return XDRSpanContent(xdr, stencil.source_, size); +} + template /* static */ -XDRResult StencilXDR::codeSharedData(XDRState* xdr, - RefPtr& sisd) { +XDRResult StencilXDR::SharedData(XDRState* xdr, + RefPtr& sisd) { if (mode == XDR_ENCODE) { MOZ_TRY(XDRImmutableScriptData(xdr, sisd->isd_)); } else { @@ -258,18 +283,26 @@ XDRResult StencilXDR::codeSharedData(XDRState* xdr, return Ok(); } -// Called from js::XDRScript. -template /* static */ XDRResult StencilXDR::codeSharedData( - XDRState* xdr, RefPtr& sisd); -template /* static */ XDRResult StencilXDR::codeSharedData( - XDRState* xdr, RefPtr& sisd); +template + /* static */ + XDRResult + StencilXDR::SharedData(XDRState* xdr, + RefPtr& sisd); + +template + /* static */ + XDRResult + StencilXDR::SharedData(XDRState* xdr, + RefPtr& sisd); + +namespace js { template -/* static */ XDRResult StencilXDR::codeSharedDataContainer( - XDRState* xdr, SharedDataContainer& sharedData) { +XDRResult XDRSharedDataContainer(XDRState* xdr, + SharedDataContainer& sharedData) { if (mode == XDR_ENCODE) { if (sharedData.isBorrow()) { - return codeSharedDataContainer(xdr, *sharedData.asBorrow()); + return XDRSharedDataContainer(xdr, *sharedData.asBorrow()); } } @@ -298,7 +331,7 @@ template if (mode == XDR_ENCODE) { ref = sharedData.asSingle(); } - MOZ_TRY(codeSharedData(xdr, ref)); + MOZ_TRY(StencilXDR::SharedData(xdr, ref)); if (mode == XDR_DECODE) { sharedData.setSingle(ref.forget()); } @@ -324,7 +357,7 @@ template MOZ_TRY(xdr->codeUint8(&exists)); if (exists) { - MOZ_TRY(codeSharedData(xdr, entry)); + MOZ_TRY(StencilXDR::SharedData(xdr, entry)); } } break; @@ -354,7 +387,7 @@ template uint32_t index = iter.get().key().index; auto& data = iter.get().value(); MOZ_TRY(xdr->codeUint32(&index)); - MOZ_TRY(codeSharedData(xdr, data)); + MOZ_TRY(StencilXDR::SharedData(xdr, data)); } } else { for (uint32_t i = 0; i < count; i++) { @@ -362,7 +395,7 @@ template MOZ_TRY(xdr->codeUint32(&index.index)); RefPtr data; - MOZ_TRY(codeSharedData(xdr, data)); + MOZ_TRY(StencilXDR::SharedData(xdr, data)); if (!map.putNew(index, data)) { js::ReportOutOfMemory(xdr->cx()); @@ -378,120 +411,6 @@ template return Ok(); } -template -/* static */ XDRResult StencilXDR::codeParserAtom(XDRState* xdr, - ParserAtom** atomp) { - static_assert(CanCopyDataToDisk::value, - "ParserAtom cannot be bulk-copied to disk."); - - MOZ_TRY(xdr->align32()); - - const ParserAtom* header; - if (mode == XDR_ENCODE) { - header = *atomp; - } else { - MOZ_TRY(xdr->peekData(&header)); - } - - const uint32_t CharSize = - header->hasLatin1Chars() ? sizeof(JS::Latin1Char) : sizeof(char16_t); - uint32_t totalLength = sizeof(ParserAtom) + (CharSize * header->length()); - - MOZ_TRY(xdr->borrowedData(atomp, totalLength)); - - return Ok(); -} - -template -static XDRResult XDRAtomCount(XDRState* xdr, uint32_t* atomCount) { - return xdr->codeUint32(atomCount); -} - -template -/* static */ XDRResult StencilXDR::codeParserAtomSpan( - XDRState* xdr, LifoAlloc& alloc, ParserAtomSpan& parserAtomData) { - if (mode == XDR_ENCODE) { - uint32_t atomVectorLength = parserAtomData.size(); - MOZ_TRY(XDRAtomCount(xdr, &atomVectorLength)); - - uint32_t atomCount = 0; - for (const auto& entry : parserAtomData) { - if (!entry) { - continue; - } - if (entry->isUsedByStencil()) { - atomCount++; - } - } - MOZ_TRY(XDRAtomCount(xdr, &atomCount)); - - for (uint32_t i = 0; i < atomVectorLength; i++) { - auto& entry = parserAtomData[i]; - if (!entry) { - continue; - } - if (entry->isUsedByStencil()) { - MOZ_TRY(xdr->codeUint32(&i)); - MOZ_TRY(codeParserAtom(xdr, &entry)); - } - } - - return Ok(); - } - - uint32_t atomVectorLength; - MOZ_TRY(XDRAtomCount(xdr, &atomVectorLength)); - - frontend::ParserAtomSpanBuilder builder(xdr->cx()->runtime(), parserAtomData); - if (!builder.allocate(xdr->cx(), alloc, atomVectorLength)) { - return xdr->fail(JS::TranscodeResult::Throw); - } - - uint32_t atomCount; - MOZ_TRY(XDRAtomCount(xdr, &atomCount)); - - for (uint32_t i = 0; i < atomCount; i++) { - frontend::ParserAtom* entry = nullptr; - uint32_t index; - MOZ_TRY(xdr->codeUint32(&index)); - MOZ_TRY(codeParserAtom(xdr, &entry)); - if (mode == XDR_DECODE) { - if (index >= atomVectorLength) { - return xdr->fail(JS::TranscodeResult::Failure_BadDecode); - } - } - builder.set(frontend::ParserAtomIndex(index), entry); - } - - return Ok(); -} - -template -/* static */ XDRResult StencilXDR::codeModuleMetadata( - XDRState* xdr, StencilModuleMetadata& stencil) { - MOZ_TRY(XDRVectorContent(xdr, stencil.requestedModules)); - MOZ_TRY(XDRVectorContent(xdr, stencil.importEntries)); - MOZ_TRY(XDRVectorContent(xdr, stencil.localExportEntries)); - MOZ_TRY(XDRVectorContent(xdr, stencil.indirectExportEntries)); - MOZ_TRY(XDRVectorContent(xdr, stencil.starExportEntries)); - MOZ_TRY(XDRVectorContent(xdr, stencil.functionDecls)); - - uint8_t isAsync = 0; - if (mode == XDR_ENCODE) { - if (stencil.isAsync) { - isAsync = stencil.isAsync ? 1 : 0; - } - } - - MOZ_TRY(xdr->codeUint8(&isAsync)); - - if (mode == XDR_DECODE) { - stencil.isAsync = isAsync == 1; - } - - return Ok(); -} - template XDRResult XDRCompilationStencilSpanSize( XDRState* xdr, uint32_t* scriptSize, uint32_t* gcThingSize, @@ -573,45 +492,15 @@ XDRResult XDRCompilationStencilSpanSize( return Ok(); } -// Marker between each section inside CompilationStencil. -// -// These values should meet the following requirement: -// * No same value (differ more than single bit flip) -// * Bit pattern that won't frequently appear inside other XDR data -// -// Currently they're randomly chosen prime numbers that doesn't have same -// byte pattern. -enum class SectionMarker : uint32_t { - ParserAtomData = 0xD9C098D3, - ScopeData = 0x892C25EF, - ScopeNames = 0x638C4FB3, - RegExpData = 0xB030C2AF, - BigIntData = 0x4B24F449, - ObjLiteralData = 0x9AFAAE45, - SharedData = 0xAAD52687, - GCThingData = 0x1BD8F533, - ScriptData = 0x840458FF, - ScriptExtra = 0xA90E489D, - ModuleMetadata = 0x94FDCE6D, -}; - template -static XDRResult CodeMarker(XDRState* xdr, SectionMarker marker) { - return xdr->codeMarker(uint32_t(marker)); -} - -template -/* static */ XDRResult StencilXDR::codeCompilationStencil( - XDRState* xdr, CompilationStencil& stencil) { +XDRResult XDRCompilationStencil(XDRState* xdr, + CompilationStencil& stencil) { MOZ_ASSERT(!stencil.asmJS); if (mode == XDR_DECODE) { stencil.hasExternalDependency = true; } - MOZ_TRY(CodeMarker(xdr, SectionMarker::ParserAtomData)); - MOZ_TRY(codeParserAtomSpan(xdr, stencil.alloc, stencil.parserAtomData)); - MOZ_TRY(xdr->codeUint32(&stencil.functionKey)); uint32_t scriptSize, gcThingSize, scopeSize, scriptExtraSize; @@ -635,45 +524,33 @@ template // All of the vector-indexed data elements referenced by the // main script tree must be materialized first. - MOZ_TRY(CodeMarker(xdr, SectionMarker::ScopeData)); MOZ_TRY(XDRSpanContent(xdr, stencil.scopeData, scopeSize)); - - MOZ_TRY(CodeMarker(xdr, SectionMarker::ScopeNames)); - MOZ_TRY( - XDRSpanInitialized(xdr, stencil.alloc, stencil.scopeNames, scopeSize)); + MOZ_TRY(XDRSpanInitialized(xdr, stencil.scopeNames, scopeSize)); MOZ_ASSERT(stencil.scopeData.size() == stencil.scopeNames.size()); for (uint32_t i = 0; i < scopeSize; i++) { - MOZ_TRY(codeScopeData(xdr, stencil.scopeData[i], stencil.scopeNames[i])); + MOZ_TRY(StencilXDR::ScopeData(xdr, stencil.scopeData[i], + stencil.scopeNames[i])); } - MOZ_TRY(CodeMarker(xdr, SectionMarker::RegExpData)); MOZ_TRY(XDRSpanContent(xdr, stencil.regExpData, regExpSize)); - MOZ_TRY(CodeMarker(xdr, SectionMarker::BigIntData)); - MOZ_TRY( - XDRSpanInitialized(xdr, stencil.alloc, stencil.bigIntData, bigIntSize)); + MOZ_TRY(XDRSpanInitialized(xdr, stencil.bigIntData, bigIntSize)); for (auto& entry : stencil.bigIntData) { - MOZ_TRY(codeBigInt(xdr, entry)); + MOZ_TRY(StencilXDR::BigInt(xdr, entry)); } - MOZ_TRY(CodeMarker(xdr, SectionMarker::ObjLiteralData)); - MOZ_TRY(XDRSpanInitialized(xdr, stencil.alloc, stencil.objLiteralData, - objLiteralSize)); + MOZ_TRY(XDRSpanInitialized(xdr, stencil.objLiteralData, objLiteralSize)); for (auto& entry : stencil.objLiteralData) { - MOZ_TRY(codeObjLiteral(xdr, entry)); + MOZ_TRY(StencilXDR::ObjLiteral(xdr, entry)); } - MOZ_TRY(CodeMarker(xdr, SectionMarker::SharedData)); - MOZ_TRY(codeSharedDataContainer(xdr, stencil.sharedData)); + MOZ_TRY(XDRSharedDataContainer(xdr, stencil.sharedData)); - MOZ_TRY(CodeMarker(xdr, SectionMarker::GCThingData)); MOZ_TRY(XDRSpanContent(xdr, stencil.gcThingData, gcThingSize)); // Now serialize the vector of ScriptStencils. - MOZ_TRY(CodeMarker(xdr, SectionMarker::ScriptData)); MOZ_TRY(XDRSpanContent(xdr, stencil.scriptData, scriptSize)); - MOZ_TRY(CodeMarker(xdr, SectionMarker::ScriptExtra)); MOZ_TRY(XDRSpanContent(xdr, stencil.scriptExtra, scriptExtraSize)); // We don't support coding non-initial CompilationStencil. @@ -688,33 +565,42 @@ template } } - MOZ_TRY(CodeMarker(xdr, SectionMarker::ModuleMetadata)); - MOZ_TRY(codeModuleMetadata(xdr, *stencil.moduleMetadata)); + MOZ_TRY(XDRStencilModuleMetadata(xdr, *stencil.moduleMetadata)); } return Ok(); } -template /* static */ XDRResult StencilXDR::codeCompilationStencil( - XDRState* xdr, CompilationStencil& stencil); +template XDRResult XDRCompilationStencil(XDRState* xdr, + CompilationStencil& stencil); -template /* static */ XDRResult StencilXDR::codeCompilationStencil( - XDRState* xdr, CompilationStencil& stencil); +template XDRResult XDRCompilationStencil(XDRState* xdr, + CompilationStencil& stencil); -/* static */ XDRResult StencilXDR::checkCompilationStencil( - XDRStencilEncoder* encoder, const CompilationStencil& stencil) { +template +XDRResult XDRCheckCompilationStencil(XDRState* xdr, + CompilationStencil& stencil) { if (stencil.asmJS) { - return encoder->fail(JS::TranscodeResult::Failure_AsmJSNotSupported); + return xdr->fail(JS::TranscodeResult::Failure_AsmJSNotSupported); } return Ok(); } -/* static */ XDRResult StencilXDR::checkCompilationStencil( - const ExtensibleCompilationStencil& stencil) { +template XDRResult XDRCheckCompilationStencil(XDRState* xdr, + CompilationStencil& stencil); + +template +XDRResult XDRCheckCompilationStencil(XDRState* xdr, + ExtensibleCompilationStencil& stencil) { if (stencil.asmJS) { - return mozilla::Err(JS::TranscodeResult::Failure_AsmJSNotSupported); + return xdr->fail(JS::TranscodeResult::Failure_AsmJSNotSupported); } return Ok(); } + +template XDRResult XDRCheckCompilationStencil( + XDRState* xdr, ExtensibleCompilationStencil& stencil); + +} // namespace js diff --git a/js/src/frontend/StencilXdr.h b/js/src/frontend/StencilXdr.h index 8f6c6e59f66f..d23c2bf72a33 100644 --- a/js/src/frontend/StencilXdr.h +++ b/js/src/frontend/StencilXdr.h @@ -7,19 +7,12 @@ #ifndef frontend_StencilXdr_h #define frontend_StencilXdr_h -#include "mozilla/RefPtr.h" // RefPtr - -#include "frontend/CompilationStencil.h" // SharedDataContainer -#include "frontend/ObjLiteral.h" // ObjLiteralStencil -#include "frontend/ParserAtom.h" // ParserAtom, ParserAtomSpan -#include "frontend/Stencil.h" // BitIntStencil, ScopeStencil, BaseParserScopeData -#include "vm/SharedStencil.h" // SharedImmutableScriptData -#include "vm/Xdr.h" // XDRMode, XDRResult, XDRState +#include "frontend/ObjLiteral.h" // ObjLiteralStencil +#include "frontend/Stencil.h" // *Stencil +#include "vm/Scope.h" // Scope, ScopeKindString +#include "vm/Xdr.h" // XDRMode, XDRResult, XDREncoder namespace js { - -class LifoAlloc; - namespace frontend { // Check that we can copy data to disk and restore it in another instance of @@ -48,44 +41,18 @@ struct CanCopyDataToDisk { class StencilXDR { public: template - static XDRResult codeBigInt(XDRState* xdr, BigIntStencil& stencil); + static XDRResult ScopeData(XDRState* xdr, ScopeStencil& stencil, + BaseParserScopeData*& baseScopeData); template - static XDRResult codeObjLiteral(XDRState* xdr, - ObjLiteralStencil& stencil); + static XDRResult ObjLiteral(XDRState* xdr, ObjLiteralStencil& stencil); template - static XDRResult codeScopeData(XDRState* xdr, ScopeStencil& stencil, - BaseParserScopeData*& baseScopeData); + static XDRResult BigInt(XDRState* xdr, BigIntStencil& stencil); template - static XDRResult codeSharedData(XDRState* xdr, - RefPtr& sisd); - - template - static XDRResult codeSharedDataContainer(XDRState* xdr, - SharedDataContainer& sharedData); - - template - static XDRResult codeParserAtom(XDRState* xdr, ParserAtom** atomp); - - template - static XDRResult codeParserAtomSpan(XDRState* xdr, LifoAlloc& alloc, - ParserAtomSpan& parserAtomData); - - template - static XDRResult codeModuleMetadata(XDRState* xdr, - StencilModuleMetadata& stencil); - - static XDRResult checkCompilationStencil(XDRStencilEncoder* encoder, - const CompilationStencil& stencil); - - static XDRResult checkCompilationStencil( - const ExtensibleCompilationStencil& stencil); - - template - static XDRResult codeCompilationStencil(XDRState* xdr, - CompilationStencil& stencil); + static XDRResult SharedData(js::XDRState* xdr, + RefPtr& sisd); }; } /* namespace frontend */ diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 4d3c590a20e4..d27bf5090c64 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -5726,7 +5726,7 @@ static JS::TranscodeResult DecodeStencil(JSContext* cx, frontend::CompilationInput& input, frontend::CompilationStencil& stencil, size_t cursorIndex) { - XDRStencilDecoder decoder(cx, buffer, cursorIndex); + XDRStencilDecoder decoder(cx, &input.options, buffer, cursorIndex); if (!input.initForGlobal(cx)) { return JS::TranscodeResult::Throw; diff --git a/js/src/vm/HelperThreads.cpp b/js/src/vm/HelperThreads.cpp index d5172bcddefe..67bafa01d456 100644 --- a/js/src/vm/HelperThreads.cpp +++ b/js/src/vm/HelperThreads.cpp @@ -820,7 +820,7 @@ void ScriptDecodeTask::parse(JSContext* cx) { return; } - XDRStencilDecoder decoder(cx, range); + XDRStencilDecoder decoder(cx, &options, range); XDRResult res = decoder.codeStencil(*stencilInput_, *stencil_); if (!res.isOk()) { stencil_.reset(); diff --git a/js/src/vm/JSScript.cpp b/js/src/vm/JSScript.cpp index 48af1ad416f7..f6f9e880a8da 100644 --- a/js/src/vm/JSScript.cpp +++ b/js/src/vm/JSScript.cpp @@ -1206,7 +1206,7 @@ XDRResult js::XDRScript(XDRState* xdr, HandleScope scriptEnclosingScope, // NOTE: The script data is rooted by the script. MOZ_TRY(PrivateScriptData::XDR(xdr, script, sourceObject, scriptEnclosingScope, funOrMod)); - MOZ_TRY(frontend::StencilXDR::codeSharedData(xdr, script->sharedData_)); + MOZ_TRY(frontend::StencilXDR::SharedData(xdr, script->sharedData_)); if (mode == XDR_DECODE) { if (!SharedImmutableScriptData::shareScriptData(cx, script->sharedData_)) { @@ -2699,7 +2699,7 @@ bool ScriptSource::startIncrementalEncoding( // Remove the reference to the source, to avoid the circular reference. initial->source = nullptr; - xdrEncoder_ = js::MakeUnique(); + xdrEncoder_ = js::MakeUnique(cx); if (!xdrEncoder_) { ReportOutOfMemory(cx); return false; @@ -2710,7 +2710,7 @@ bool ScriptSource::startIncrementalEncoding( mozilla::MakeScopeExit([&] { xdrEncoder_.reset(nullptr); }); XDRResult res = xdrEncoder_->setInitial( - cx, options, + options, std::forward>(initial)); if (res.isErr()) { // On encoding failure, let failureCase destroy encoder and return true @@ -2729,7 +2729,7 @@ bool ScriptSource::addDelazificationToIncrementalEncoding( auto failureCase = mozilla::MakeScopeExit([&] { xdrEncoder_.reset(nullptr); }); - XDRResult res = xdrEncoder_->addDelazification(cx, stencil); + XDRResult res = xdrEncoder_->addDelazification(stencil); if (res.isErr()) { // On encoding failure, let failureCase destroy encoder and return true // to avoid failing any currently executing script. @@ -2749,7 +2749,7 @@ bool ScriptSource::xdrFinalizeEncoder(JSContext* cx, auto cleanup = mozilla::MakeScopeExit([&] { xdrEncoder_.reset(nullptr); }); - XDRResult res = xdrEncoder_->linearize(cx, buffer, this); + XDRResult res = xdrEncoder_->linearize(buffer, this); if (res.isErr()) { if (JS::IsTranscodeFailureResult(res.unwrapErr())) { JS_ReportErrorASCII(cx, "XDR encoding failure"); diff --git a/js/src/vm/Xdr.cpp b/js/src/vm/Xdr.cpp index e7f97c509da6..9e92604e64b0 100644 --- a/js/src/vm/Xdr.cpp +++ b/js/src/vm/Xdr.cpp @@ -20,7 +20,7 @@ #include "builtin/ModuleObject.h" #include "debugger/DebugAPI.h" #include "frontend/CompilationStencil.h" // frontend::{CompilationStencil, ExtensibleCompilationStencil, CompilationStencilMerger, BorrowingCompilationStencil} -#include "frontend/StencilXdr.h" // frontend::StencilXDR +#include "frontend/ParserAtom.h" // frontend::ParserAtom #include "js/BuildId.h" // JS::BuildIdCharVector #include "vm/JSContext.h" #include "vm/JSScript.h" @@ -284,6 +284,67 @@ XDRResult XDRState::codeModuleObject(MutableHandleModuleObject modp) { return Ok(); } +template +static XDRResult XDRAtomCount(XDRState* xdr, uint32_t* atomCount) { + return xdr->codeUint32(atomCount); +} + +template +static XDRResult XDRParserAtomTable(XDRState* xdr, + frontend::CompilationStencil& stencil) { + if (mode == XDR_ENCODE) { + uint32_t atomVectorLength = stencil.parserAtomData.size(); + MOZ_TRY(XDRAtomCount(xdr, &atomVectorLength)); + + uint32_t atomCount = 0; + for (const auto& entry : stencil.parserAtomData) { + if (!entry) { + continue; + } + if (entry->isUsedByStencil()) { + atomCount++; + } + } + MOZ_TRY(XDRAtomCount(xdr, &atomCount)); + + for (uint32_t i = 0; i < atomVectorLength; i++) { + auto& entry = stencil.parserAtomData[i]; + if (!entry) { + continue; + } + if (entry->isUsedByStencil()) { + MOZ_TRY(xdr->codeUint32(&i)); + MOZ_TRY(XDRParserAtom(xdr, &entry)); + } + } + + return Ok(); + } + + uint32_t atomVectorLength; + MOZ_TRY(XDRAtomCount(xdr, &atomVectorLength)); + + if (!xdr->frontendAtoms().allocate(xdr->cx(), xdr->stencilAlloc(), + atomVectorLength)) { + return xdr->fail(JS::TranscodeResult::Throw); + } + + uint32_t atomCount; + MOZ_TRY(XDRAtomCount(xdr, &atomCount)); + MOZ_ASSERT(!xdr->hasAtomTable()); + + for (uint32_t i = 0; i < atomCount; i++) { + frontend::ParserAtom* entry = nullptr; + uint32_t index; + MOZ_TRY(xdr->codeUint32(&index)); + MOZ_TRY(XDRParserAtom(xdr, &entry)); + xdr->frontendAtoms().set(frontend::ParserAtomIndex(index), entry); + } + xdr->finishAtomTable(); + + return Ok(); +} + template XDRResult XDRState::codeScript(MutableHandleScript scriptp) { TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx()); @@ -319,6 +380,7 @@ static XDRResult XDRStencilHeader( MOZ_TRY(VersionCheck(xdr, XDRFormatType::Stencil)); MOZ_TRY(ScriptSource::XDR(xdr, maybeOptions, source)); + MOZ_TRY(xdr->align32()); return Ok(); } @@ -336,42 +398,25 @@ static bool IsOptionCompatibleWithEncoding( } XDRResult XDRStencilEncoder::codeStencil( - const JS::ReadOnlyCompileOptions* options, - const RefPtr& source, - const frontend::CompilationStencil& stencil) { + frontend::CompilationInput& input, frontend::CompilationStencil& stencil) { #ifdef DEBUG auto sanityCheck = mozilla::MakeScopeExit( [&] { MOZ_ASSERT(validateResultCode(cx(), resultCode())); }); #endif - if (options) { - if (!IsOptionCompatibleWithEncoding(*options)) { - return fail(JS::TranscodeResult::Failure); - } + if (!IsOptionCompatibleWithEncoding(input.options)) { + return fail(JS::TranscodeResult::Failure); } - MOZ_TRY(frontend::StencilXDR::checkCompilationStencil(this, stencil)); + MOZ_TRY(XDRCheckCompilationStencil(this, stencil)); - MOZ_TRY(XDRStencilHeader(this, options, - const_cast&>(source))); - MOZ_TRY(frontend::StencilXDR::codeCompilationStencil( - this, const_cast(stencil))); + MOZ_TRY(XDRStencilHeader(this, &input.options, stencil.source)); + MOZ_TRY(XDRParserAtomTable(this, stencil)); + MOZ_TRY(XDRCompilationStencil(this, stencil)); return Ok(); } -XDRResult XDRStencilEncoder::codeStencil( - const frontend::CompilationInput& input, - const frontend::CompilationStencil& stencil) { - return codeStencil(&input.options, stencil.source, stencil); -} - -XDRResult XDRStencilEncoder::codeStencil( - const RefPtr& source, - const frontend::CompilationStencil& stencil) { - return codeStencil(nullptr, source, stencil); -} - XDRIncrementalStencilEncoder::~XDRIncrementalStencilEncoder() { if (merger_) { js_delete(merger_); @@ -379,48 +424,77 @@ XDRIncrementalStencilEncoder::~XDRIncrementalStencilEncoder() { } XDRResult XDRIncrementalStencilEncoder::setInitial( - JSContext* cx, const JS::ReadOnlyCompileOptions& options, + const JS::ReadOnlyCompileOptions& options, UniquePtr&& initial) { +#ifdef DEBUG + auto sanityCheck = mozilla::MakeScopeExit( + [&] { MOZ_ASSERT(validateResultCode(cx(), resultCode())); }); +#endif + if (!IsOptionCompatibleWithEncoding(options)) { - return mozilla::Err(JS::TranscodeResult::Failure); + return fail(JS::TranscodeResult::Failure); } - MOZ_TRY(frontend::StencilXDR::checkCompilationStencil(*initial)); + MOZ_TRY(XDRCheckCompilationStencil(this, *initial)); - merger_ = cx->new_(); + merger_ = cx()->new_(); if (!merger_) { - return mozilla::Err(JS::TranscodeResult::Throw); + return fail(JS::TranscodeResult::Throw); } if (!merger_->setInitial( - cx, std::forward>( - initial))) { - return mozilla::Err(JS::TranscodeResult::Throw); + cx(), std::forward>( + initial))) { + return fail(JS::TranscodeResult::Throw); } return Ok(); } XDRResult XDRIncrementalStencilEncoder::addDelazification( - JSContext* cx, const frontend::CompilationStencil& delazification) { - if (!merger_->addDelazification(cx, delazification)) { - return mozilla::Err(JS::TranscodeResult::Throw); + const frontend::CompilationStencil& delazification) { +#ifdef DEBUG + auto sanityCheck = mozilla::MakeScopeExit( + [&] { MOZ_ASSERT(validateResultCode(cx(), resultCode())); }); +#endif + + if (!merger_->addDelazification(cx(), delazification)) { + return fail(JS::TranscodeResult::Throw); } return Ok(); } -XDRResult XDRIncrementalStencilEncoder::linearize(JSContext* cx, - JS::TranscodeBuffer& buffer, +XDRResult XDRIncrementalStencilEncoder::linearize(JS::TranscodeBuffer& buffer, ScriptSource* ss) { - XDRStencilEncoder encoder(cx, buffer); +#ifdef DEBUG + auto sanityCheck = mozilla::MakeScopeExit( + [&] { MOZ_ASSERT(validateResultCode(cx(), resultCode())); }); +#endif + + // NOTE: If buffer is empty, buffer.begin() doesn't point valid buffer. + MOZ_ASSERT_IF(!buffer.empty(), + JS::IsTranscodingBytecodeAligned(buffer.begin())); + MOZ_ASSERT(JS::IsTranscodingBytecodeOffsetAligned(buffer.length())); + + // Use the output buffer directly. The caller may have already have data in + // the buffer so ensure we skip over it. + XDRBuffer outputBuf(cx(), buffer, buffer.length()); + + switchToBuffer(&outputBuf); + RefPtr source(ss); + MOZ_TRY(XDRStencilHeader(this, nullptr, source)); + { frontend::BorrowingCompilationStencil borrowingStencil( merger_->getResult()); - MOZ_TRY(encoder.codeStencil(source, borrowingStencil)); + MOZ_TRY(XDRParserAtomTable(this, borrowingStencil)); + MOZ_TRY(XDRCompilationStencil(this, borrowingStencil)); } + switchToBuffer(&mainBuf); + return Ok(); } @@ -433,8 +507,14 @@ XDRResult XDRStencilDecoder::codeStencil( [&] { MOZ_ASSERT(validateResultCode(cx(), resultCode())); }); #endif + frontend::ParserAtomSpanBuilder parserAtomBuilder(cx()->runtime(), + stencil.parserAtomData); + parserAtomBuilder_ = &parserAtomBuilder; + stencilAlloc_ = &stencil.alloc; + MOZ_TRY(XDRStencilHeader(this, &input.options, stencil.source)); - MOZ_TRY(frontend::StencilXDR::codeCompilationStencil(this, stencil)); + MOZ_TRY(XDRParserAtomTable(this, stencil)); + MOZ_TRY(XDRCompilationStencil(this, stencil)); return Ok(); } diff --git a/js/src/vm/Xdr.h b/js/src/vm/Xdr.h index bc5a3b1419d2..c94e87ffaf64 100644 --- a/js/src/vm/Xdr.h +++ b/js/src/vm/Xdr.h @@ -17,6 +17,7 @@ #include "jsfriendapi.h" #include "NamespaceImports.h" +#include "frontend/ParserAtom.h" #include "js/CompileOptions.h" #include "js/Transcoding.h" #include "js/TypeDecls.h" @@ -238,6 +239,10 @@ class XDRState : public XDRCoderBase { virtual bool hasAtomTable() const { return false; } virtual XDRAtomTable& atomTable() { MOZ_CRASH("does not have atomTable"); } + virtual frontend::ParserAtomSpanBuilder& frontendAtoms() { + MOZ_CRASH("does not have frontendAtoms"); + } + virtual LifoAlloc& stencilAlloc() { MOZ_CRASH("does not have stencilAlloc"); } virtual void finishAtomTable() { MOZ_CRASH("does not have atomTable"); } template @@ -548,33 +553,56 @@ class XDROffThreadDecoder : public XDRDecoder { * b. ScriptSource * d. Alignment padding * 2. Stencil - * a. CompilationStencil + * a. ParseAtomTable + * b. CompilationStencil */ /* - * The stencil decoder accepts `range` as input. + * The stencil decoder accepts `options` and `range` as input, along + * with a freshly initialized `parserAtoms` table. * * The decoded stencils are outputted to the default-initialized - * `stencil` parameter of `codeStencil` method. + * `stencil` parameter of `codeStencil` method, and decoded atoms are + * interned into the `parserAtoms` parameter of the ctor. * * The decoded stencils borrow the input `buffer`/`range`, and the consumer * has to keep the buffer alive while the decoded stencils are alive. */ class XDRStencilDecoder : public XDRDecoderBase { public: - XDRStencilDecoder(JSContext* cx, JS::TranscodeBuffer& buffer, size_t cursor) - : XDRDecoderBase(cx, buffer, cursor) { + XDRStencilDecoder(JSContext* cx, const JS::ReadOnlyCompileOptions* options, + JS::TranscodeBuffer& buffer, size_t cursor) + : XDRDecoderBase(cx, buffer, cursor), options_(options) { MOZ_ASSERT(JS::IsTranscodingBytecodeAligned(buffer.begin())); MOZ_ASSERT(JS::IsTranscodingBytecodeOffsetAligned(cursor)); + MOZ_ASSERT(options_); } - XDRStencilDecoder(JSContext* cx, const JS::TranscodeRange& range) - : XDRDecoderBase(cx, range) { + XDRStencilDecoder(JSContext* cx, const JS::ReadOnlyCompileOptions* options, + const JS::TranscodeRange& range) + : XDRDecoderBase(cx, range), options_(options) { MOZ_ASSERT(JS::IsTranscodingBytecodeAligned(range.begin().get())); + MOZ_ASSERT(options_); } + bool hasAtomTable() const override { return hasFinishedAtomTable_; } + frontend::ParserAtomSpanBuilder& frontendAtoms() override { + return *parserAtomBuilder_; + } + LifoAlloc& stencilAlloc() override { return *stencilAlloc_; } + void finishAtomTable() override { hasFinishedAtomTable_ = true; } + + bool hasOptions() const override { return true; } + const JS::ReadOnlyCompileOptions& options() override { return *options_; } + XDRResult codeStencil(frontend::CompilationInput& input, frontend::CompilationStencil& stencil); + + private: + const JS::ReadOnlyCompileOptions* options_; + bool hasFinishedAtomTable_ = false; + frontend::ParserAtomSpanBuilder* parserAtomBuilder_ = nullptr; + LifoAlloc* stencilAlloc_ = nullptr; }; class XDRStencilEncoder : public XDREncoder { @@ -587,35 +615,33 @@ class XDRStencilEncoder : public XDREncoder { MOZ_ASSERT(JS::IsTranscodingBytecodeOffsetAligned(buffer.length())); } - private: - XDRResult codeStencil(const JS::ReadOnlyCompileOptions* options, - const RefPtr& source, - const frontend::CompilationStencil& stencil); - - public: - XDRResult codeStencil(const frontend::CompilationInput& input, - const frontend::CompilationStencil& stencil); - - XDRResult codeStencil(const RefPtr& source, - const frontend::CompilationStencil& stencil); + XDRResult codeStencil(frontend::CompilationInput& input, + frontend::CompilationStencil& stencil); }; -class XDRIncrementalStencilEncoder { +class XDRIncrementalStencilEncoder : public XDREncoder { + // The target buffer isn't available until linearize. + // Hold dummy buffer to initialize XDREncoder. + JS::TranscodeBuffer dummy_; + frontend::CompilationStencilMerger* merger_ = nullptr; public: - XDRIncrementalStencilEncoder() = default; + explicit XDRIncrementalStencilEncoder(JSContext* cx) + : XDREncoder(cx, dummy_, 0) {} - ~XDRIncrementalStencilEncoder(); + virtual ~XDRIncrementalStencilEncoder(); - XDRResult linearize(JSContext* cx, JS::TranscodeBuffer& buffer, - js::ScriptSource* ss); + XDRResult linearize(JS::TranscodeBuffer& buffer, js::ScriptSource* ss); XDRResult setInitial( - JSContext* cx, const JS::ReadOnlyCompileOptions& options, + const JS::ReadOnlyCompileOptions& options, UniquePtr&& initial); XDRResult addDelazification( - JSContext* cx, const frontend::CompilationStencil& delazification); + const frontend::CompilationStencil& delazification); + + private: + void switchToBuffer(XDRBuffer* target) { buf = target; } }; template @@ -627,6 +653,21 @@ XDRResult XDRAtom(XDRState* xdr, js::MutableHandleAtom atomp); template XDRResult XDRAtomData(XDRState* xdr, js::MutableHandleAtom atomp); +template +XDRResult XDRParserAtom(XDRState* xdr, frontend::ParserAtom** atomp); + +template +XDRResult XDRCompilationStencil(XDRState* xdr, + frontend::CompilationStencil& stencil); + +template +XDRResult XDRCheckCompilationStencil(XDRState* xdr, + frontend::CompilationStencil& stencil); + +template +XDRResult XDRCheckCompilationStencil( + XDRState* xdr, frontend::ExtensibleCompilationStencil& stencil); + } /* namespace js */ #endif /* vm_Xdr_h */