Bug 1843030 - Part 4: Add PreallocatedCompilationGCOutput. r=nbp
Differential Revision: https://phabricator.services.mozilla.com/D183462
This commit is contained in:
@@ -95,9 +95,9 @@ nsresult JSExecutionContext::JoinOffThread(
|
|||||||
|
|
||||||
MOZ_ASSERT(!mWantsReturnValue);
|
MOZ_ASSERT(!mWantsReturnValue);
|
||||||
|
|
||||||
JS::Rooted<JS::InstantiationStorage> storage(mCx);
|
JS::InstantiationStorage storage;
|
||||||
RefPtr<JS::Stencil> stencil =
|
RefPtr<JS::Stencil> stencil =
|
||||||
JS::FinishOffThreadStencil(mCx, *aOffThreadToken, storage.address());
|
JS::FinishOffThreadStencil(mCx, *aOffThreadToken, &storage);
|
||||||
*aOffThreadToken = nullptr; // Mark the token as having been finished.
|
*aOffThreadToken = nullptr; // Mark the token as having been finished.
|
||||||
if (!stencil) {
|
if (!stencil) {
|
||||||
mSkip = true;
|
mSkip = true;
|
||||||
@@ -105,7 +105,7 @@ nsresult JSExecutionContext::JoinOffThread(
|
|||||||
return mRv;
|
return mRv;
|
||||||
}
|
}
|
||||||
|
|
||||||
return InstantiateStencil(std::move(stencil), storage.address());
|
return InstantiateStencil(std::move(stencil), &storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Unit>
|
template <typename Unit>
|
||||||
|
|||||||
@@ -149,10 +149,9 @@ nsresult ModuleLoader::CompileFetchedModule(
|
|||||||
JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::CompileOptions& aOptions,
|
JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::CompileOptions& aOptions,
|
||||||
ModuleLoadRequest* aRequest, JS::MutableHandle<JSObject*> aModuleOut) {
|
ModuleLoadRequest* aRequest, JS::MutableHandle<JSObject*> aModuleOut) {
|
||||||
if (aRequest->GetScriptLoadContext()->mWasCompiledOMT) {
|
if (aRequest->GetScriptLoadContext()->mWasCompiledOMT) {
|
||||||
JS::Rooted<JS::InstantiationStorage> storage(aCx);
|
JS::InstantiationStorage storage;
|
||||||
RefPtr<JS::Stencil> stencil = JS::FinishOffThreadStencil(
|
RefPtr<JS::Stencil> stencil = JS::FinishOffThreadStencil(
|
||||||
aCx, aRequest->GetScriptLoadContext()->mOffThreadToken,
|
aCx, aRequest->GetScriptLoadContext()->mOffThreadToken, &storage);
|
||||||
storage.address());
|
|
||||||
|
|
||||||
aRequest->GetScriptLoadContext()->mOffThreadToken = nullptr;
|
aRequest->GetScriptLoadContext()->mOffThreadToken = nullptr;
|
||||||
|
|
||||||
@@ -162,7 +161,7 @@ nsresult ModuleLoader::CompileFetchedModule(
|
|||||||
|
|
||||||
JS::InstantiateOptions instantiateOptions(aOptions);
|
JS::InstantiateOptions instantiateOptions(aOptions);
|
||||||
aModuleOut.set(JS::InstantiateModuleStencil(aCx, instantiateOptions,
|
aModuleOut.set(JS::InstantiateModuleStencil(aCx, instantiateOptions,
|
||||||
stencil, storage.address()));
|
stencil, &storage));
|
||||||
if (!aModuleOut) {
|
if (!aModuleOut) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ namespace frontend {
|
|||||||
struct CompilationStencil;
|
struct CompilationStencil;
|
||||||
struct CompilationGCOutput;
|
struct CompilationGCOutput;
|
||||||
struct CompilationInput;
|
struct CompilationInput;
|
||||||
|
struct PreallocatedCompilationGCOutput;
|
||||||
} // namespace frontend
|
} // namespace frontend
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
@@ -61,9 +62,9 @@ struct InstantiationStorage {
|
|||||||
private:
|
private:
|
||||||
// Owned CompilationGCOutput.
|
// Owned CompilationGCOutput.
|
||||||
//
|
//
|
||||||
// This uses raw pointer instead of UniquePtr because CompilationGCOutput
|
// This uses raw pointer instead of UniquePtr because
|
||||||
// is opaque.
|
// PreallocatedCompilationGCOutput is opaque.
|
||||||
js::frontend::CompilationGCOutput* gcOutput_ = nullptr;
|
js::frontend::PreallocatedCompilationGCOutput* gcOutput_ = nullptr;
|
||||||
|
|
||||||
friend JS_PUBLIC_API JSScript* InstantiateGlobalStencil(
|
friend JS_PUBLIC_API JSScript* InstantiateGlobalStencil(
|
||||||
JSContext* cx, const InstantiateOptions& options, Stencil* stencil,
|
JSContext* cx, const InstantiateOptions& options, Stencil* stencil,
|
||||||
@@ -94,8 +95,6 @@ struct InstantiationStorage {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
bool isValid() const { return !!gcOutput_; }
|
bool isValid() const { return !!gcOutput_; }
|
||||||
|
|
||||||
void trace(JSTracer* trc);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace JS
|
} // namespace JS
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ namespace frontend {
|
|||||||
struct CompilationInput;
|
struct CompilationInput;
|
||||||
struct CompilationStencil;
|
struct CompilationStencil;
|
||||||
struct CompilationGCOutput;
|
struct CompilationGCOutput;
|
||||||
|
struct PreallocatedCompilationGCOutput;
|
||||||
class ScriptStencilIterable;
|
class ScriptStencilIterable;
|
||||||
struct InputName;
|
struct InputName;
|
||||||
class ScopeBindingCache;
|
class ScopeBindingCache;
|
||||||
@@ -1213,6 +1214,10 @@ struct CompilationStencil {
|
|||||||
[[nodiscard]] static bool prepareForInstantiate(
|
[[nodiscard]] static bool prepareForInstantiate(
|
||||||
FrontendContext* fc, CompilationAtomCache& atomCache,
|
FrontendContext* fc, CompilationAtomCache& atomCache,
|
||||||
const CompilationStencil& stencil, CompilationGCOutput& gcOutput);
|
const CompilationStencil& stencil, CompilationGCOutput& gcOutput);
|
||||||
|
[[nodiscard]] static bool prepareForInstantiate(
|
||||||
|
FrontendContext* fc, CompilationAtomCache& atomCache,
|
||||||
|
const CompilationStencil& stencil,
|
||||||
|
PreallocatedCompilationGCOutput& gcOutput);
|
||||||
|
|
||||||
[[nodiscard]] static bool instantiateStencils(
|
[[nodiscard]] static bool instantiateStencils(
|
||||||
JSContext* cx, CompilationInput& input, const CompilationStencil& stencil,
|
JSContext* cx, CompilationInput& input, const CompilationStencil& stencil,
|
||||||
@@ -1661,6 +1666,38 @@ struct PreAllocateableGCArray {
|
|||||||
void trace(JSTracer* trc);
|
void trace(JSTracer* trc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CompilationGCOutput;
|
||||||
|
|
||||||
|
// Pre-allocated storage for CompilationGCOutput.
|
||||||
|
struct PreallocatedCompilationGCOutput {
|
||||||
|
private:
|
||||||
|
PreAllocateableGCArray<JSFunction*>::Preallocated functions;
|
||||||
|
PreAllocateableGCArray<js::Scope*>::Preallocated scopes;
|
||||||
|
|
||||||
|
friend struct CompilationGCOutput;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PreallocatedCompilationGCOutput() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] bool allocate(FrontendContext* fc, size_t scriptDataLength,
|
||||||
|
size_t scopeDataLength) {
|
||||||
|
if (!functions.allocate(scriptDataLength)) {
|
||||||
|
ReportOutOfMemory(fc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!scopes.allocate(scopeDataLength)) {
|
||||||
|
ReportOutOfMemory(fc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
|
||||||
|
return functions.sizeOfExcludingThis(mallocSizeOf) +
|
||||||
|
scopes.sizeOfExcludingThis(mallocSizeOf);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// The output of GC allocation from stencil.
|
// The output of GC allocation from stencil.
|
||||||
struct CompilationGCOutput {
|
struct CompilationGCOutput {
|
||||||
// The resulting outermost script for the compilation powered
|
// The resulting outermost script for the compilation powered
|
||||||
@@ -1722,9 +1759,7 @@ struct CompilationGCOutput {
|
|||||||
return scopes[index];
|
return scopes[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate output arrays. This may be called before instantiate to do
|
// Allocate output arrays.
|
||||||
// allocations ahead of time (off thread). The stencil instantiation code will
|
|
||||||
// also run this to ensure the arrays are ready.
|
|
||||||
[[nodiscard]] bool ensureAllocated(FrontendContext* fc,
|
[[nodiscard]] bool ensureAllocated(FrontendContext* fc,
|
||||||
size_t scriptDataLength,
|
size_t scriptDataLength,
|
||||||
size_t scopeDataLength) {
|
size_t scopeDataLength) {
|
||||||
@@ -1743,6 +1778,12 @@ struct CompilationGCOutput {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Steal output arrays' buffer.
|
||||||
|
void steal(PreallocatedCompilationGCOutput&& pre) {
|
||||||
|
functions.steal(std::move(pre.functions));
|
||||||
|
scopes.steal(std::move(pre.scopes));
|
||||||
|
}
|
||||||
|
|
||||||
// A variant of `ensureAllocated` that sets a base index for the function and
|
// A variant of `ensureAllocated` that sets a base index for the function and
|
||||||
// scope arrays. This is used when instantiating only a subset of the stencil.
|
// scope arrays. This is used when instantiating only a subset of the stencil.
|
||||||
// Currently this only applies to self-hosted delazification. The ranges
|
// Currently this only applies to self-hosted delazification. The ranges
|
||||||
|
|||||||
@@ -213,7 +213,8 @@ bool JS::PrepareForInstantiate(JS::FrontendContext* fc,
|
|||||||
MOZ_ASSERT(isGCSafe(compileStorage.getInput()));
|
MOZ_ASSERT(isGCSafe(compileStorage.getInput()));
|
||||||
if (!storage.gcOutput_) {
|
if (!storage.gcOutput_) {
|
||||||
storage.gcOutput_ =
|
storage.gcOutput_ =
|
||||||
fc->getAllocator()->new_<js::frontend::CompilationGCOutput>();
|
fc->getAllocator()
|
||||||
|
->new_<js::frontend::PreallocatedCompilationGCOutput>();
|
||||||
if (!storage.gcOutput_) {
|
if (!storage.gcOutput_) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1814,12 +1814,6 @@ void CompilationGCOutput::trace(JSTracer* trc) {
|
|||||||
scopes.trace(trc);
|
scopes.trace(trc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JS::InstantiationStorage::trace(JSTracer* trc) {
|
|
||||||
if (gcOutput_) {
|
|
||||||
gcOutput_->trace(trc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RegExpObject* RegExpStencil::createRegExp(
|
RegExpObject* RegExpStencil::createRegExp(
|
||||||
JSContext* cx, const CompilationAtomCache& atomCache) const {
|
JSContext* cx, const CompilationAtomCache& atomCache) const {
|
||||||
Rooted<JSAtom*> atom(cx, atomCache.getExistingAtomAt(cx, atom_));
|
Rooted<JSAtom*> atom(cx, atomCache.getExistingAtomAt(cx, atom_));
|
||||||
@@ -2892,6 +2886,19 @@ bool CompilationStencil::prepareForInstantiate(
|
|||||||
return atomCache.allocate(fc, stencil.parserAtomData.size());
|
return atomCache.allocate(fc, stencil.parserAtomData.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
bool CompilationStencil::prepareForInstantiate(
|
||||||
|
FrontendContext* fc, CompilationAtomCache& atomCache,
|
||||||
|
const CompilationStencil& stencil,
|
||||||
|
PreallocatedCompilationGCOutput& gcOutput) {
|
||||||
|
if (!gcOutput.allocate(fc, stencil.scriptData.size(),
|
||||||
|
stencil.scopeData.size())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return atomCache.allocate(fc, stencil.parserAtomData.size());
|
||||||
|
}
|
||||||
|
|
||||||
bool CompilationStencil::serializeStencils(JSContext* cx,
|
bool CompilationStencil::serializeStencils(JSContext* cx,
|
||||||
CompilationInput& input,
|
CompilationInput& input,
|
||||||
JS::TranscodeBuffer& buf,
|
JS::TranscodeBuffer& buf,
|
||||||
@@ -5467,12 +5474,14 @@ JS_PUBLIC_API JSScript* JS::InstantiateGlobalStencil(
|
|||||||
options.copyTo(compileOptions);
|
options.copyTo(compileOptions);
|
||||||
Rooted<CompilationInput> input(cx, CompilationInput(compileOptions));
|
Rooted<CompilationInput> input(cx, CompilationInput(compileOptions));
|
||||||
Rooted<CompilationGCOutput> gcOutput(cx);
|
Rooted<CompilationGCOutput> gcOutput(cx);
|
||||||
CompilationGCOutput& output = storage ? *storage->gcOutput_ : gcOutput.get();
|
if (storage) {
|
||||||
|
gcOutput.get().steal(std::move(*storage->gcOutput_));
|
||||||
|
}
|
||||||
|
|
||||||
if (!InstantiateStencils(cx, input.get(), *stencil, output)) {
|
if (!InstantiateStencils(cx, input.get(), *stencil, gcOutput.get())) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return output.script;
|
return gcOutput.get().script;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API bool JS::StencilIsBorrowed(Stencil* stencil) {
|
JS_PUBLIC_API bool JS::StencilIsBorrowed(Stencil* stencil) {
|
||||||
@@ -5489,12 +5498,14 @@ JS_PUBLIC_API JSObject* JS::InstantiateModuleStencil(
|
|||||||
compileOptions.setModule();
|
compileOptions.setModule();
|
||||||
Rooted<CompilationInput> input(cx, CompilationInput(compileOptions));
|
Rooted<CompilationInput> input(cx, CompilationInput(compileOptions));
|
||||||
Rooted<CompilationGCOutput> gcOutput(cx);
|
Rooted<CompilationGCOutput> gcOutput(cx);
|
||||||
CompilationGCOutput& output = storage ? *storage->gcOutput_ : gcOutput.get();
|
if (storage) {
|
||||||
|
gcOutput.get().steal(std::move(*storage->gcOutput_));
|
||||||
|
}
|
||||||
|
|
||||||
if (!InstantiateStencils(cx, input.get(), *stencil, output)) {
|
if (!InstantiateStencils(cx, input.get(), *stencil, gcOutput.get())) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return output.module;
|
return gcOutput.get().module;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS::TranscodeResult JS::EncodeStencil(JSContext* cx, JS::Stencil* stencil,
|
JS::TranscodeResult JS::EncodeStencil(JSContext* cx, JS::Stencil* stencil,
|
||||||
|
|||||||
@@ -411,15 +411,13 @@ BEGIN_TEST(testStencil_OffThreadWithInstantiationStorage) {
|
|||||||
lock.wait();
|
lock.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
JS::Rooted<JS::InstantiationStorage> storage(cx);
|
JS::InstantiationStorage storage;
|
||||||
RefPtr<JS::Stencil> stencil =
|
RefPtr<JS::Stencil> stencil = JS::FinishOffThreadStencil(cx, token, &storage);
|
||||||
JS::FinishOffThreadStencil(cx, token, storage.address());
|
|
||||||
CHECK(stencil);
|
CHECK(stencil);
|
||||||
|
|
||||||
JS::InstantiateOptions instantiateOptions(options);
|
JS::InstantiateOptions instantiateOptions(options);
|
||||||
JS::RootedScript script(
|
JS::RootedScript script(cx, JS::InstantiateGlobalStencil(
|
||||||
cx, JS::InstantiateGlobalStencil(cx, instantiateOptions, stencil,
|
cx, instantiateOptions, stencil, &storage));
|
||||||
storage.address()));
|
|
||||||
CHECK(script);
|
CHECK(script);
|
||||||
|
|
||||||
JS::RootedValue rval(cx);
|
JS::RootedValue rval(cx);
|
||||||
@@ -514,15 +512,14 @@ BEGIN_TEST(testStencil_OffThreadModuleWithInstantiationStorage) {
|
|||||||
lock.wait();
|
lock.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
JS::Rooted<JS::InstantiationStorage> storage(cx);
|
JS::InstantiationStorage storage;
|
||||||
RefPtr<JS::Stencil> stencil =
|
RefPtr<JS::Stencil> stencil = JS::FinishOffThreadStencil(cx, token, &storage);
|
||||||
JS::FinishOffThreadStencil(cx, token, storage.address());
|
|
||||||
CHECK(stencil);
|
CHECK(stencil);
|
||||||
|
|
||||||
JS::InstantiateOptions instantiateOptions(options);
|
JS::InstantiateOptions instantiateOptions(options);
|
||||||
JS::RootedObject moduleObject(
|
JS::RootedObject moduleObject(
|
||||||
cx, JS::InstantiateModuleStencil(cx, instantiateOptions, stencil,
|
cx,
|
||||||
storage.address()));
|
JS::InstantiateModuleStencil(cx, instantiateOptions, stencil, &storage));
|
||||||
CHECK(moduleObject);
|
CHECK(moduleObject);
|
||||||
|
|
||||||
JS::RootedValue rval(cx);
|
JS::RootedValue rval(cx);
|
||||||
@@ -677,17 +674,15 @@ BEGIN_TEST(testStencil_OffThreadDecodeWithInstantiationStorage) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JS::Rooted<JS::InstantiationStorage> storage(cx);
|
JS::InstantiationStorage storage;
|
||||||
RefPtr<JS::Stencil> stencil =
|
RefPtr<JS::Stencil> stencil = JS::FinishOffThreadStencil(cx, token, &storage);
|
||||||
JS::FinishOffThreadStencil(cx, token, storage.address());
|
|
||||||
CHECK(stencil);
|
CHECK(stencil);
|
||||||
|
|
||||||
CHECK(!JS::StencilIsBorrowed(stencil));
|
CHECK(!JS::StencilIsBorrowed(stencil));
|
||||||
|
|
||||||
JS::InstantiateOptions instantiateOptions;
|
JS::InstantiateOptions instantiateOptions;
|
||||||
JS::RootedScript script(
|
JS::RootedScript script(cx, JS::InstantiateGlobalStencil(
|
||||||
cx, JS::InstantiateGlobalStencil(cx, instantiateOptions, stencil,
|
cx, instantiateOptions, stencil, &storage));
|
||||||
storage.address()));
|
|
||||||
CHECK(script);
|
CHECK(script);
|
||||||
|
|
||||||
JS::RootedValue rval(cx);
|
JS::RootedValue rval(cx);
|
||||||
|
|||||||
@@ -561,7 +561,6 @@ void ParseTask::trace(JSTracer* trc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileStorage_.trace(trc);
|
compileStorage_.trace(trc);
|
||||||
instantiationStorage_.trace(trc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ParseTask::sizeOfExcludingThis(
|
size_t ParseTask::sizeOfExcludingThis(
|
||||||
|
|||||||
Reference in New Issue
Block a user