зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1773319 - Intro API to create/destroy FrontendContext, ParseScript r=arai
Need to fill out jsapi-test for more details and use cases. ParseGlobalScript() has a stackLimit parameter because I don't expect to know what the limit for the TaskController task is, or even that the function is being run by TaskController. Differential Revision: https://phabricator.services.mozilla.com/D167461
This commit is contained in:
Родитель
00196ec53e
Коммит
9dfe84719a
|
@ -0,0 +1,40 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* JavaScript API for compiling scripts to stencil without depending on
|
||||
* JSContext. */
|
||||
|
||||
#ifndef js_experimental_ParseScript_h
|
||||
#define js_experimental_ParseScript_h
|
||||
|
||||
#include "jspubtd.h"
|
||||
#include "js/experimental/JSStencil.h"
|
||||
#include "js/Stack.h"
|
||||
|
||||
namespace js {
|
||||
class FrontendContext;
|
||||
}
|
||||
|
||||
namespace JS {
|
||||
using FrontendContext = js::FrontendContext;
|
||||
|
||||
// Create a new front-end context.
|
||||
JS_PUBLIC_API JS::FrontendContext* NewFrontendContext();
|
||||
|
||||
// Destroy a front-end context allocated with JS_NewFrontendContext.
|
||||
JS_PUBLIC_API void DestroyFrontendContext(JS::FrontendContext* fc);
|
||||
|
||||
extern JS_PUBLIC_API already_AddRefed<JS::Stencil> ParseGlobalScript(
|
||||
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options,
|
||||
JS::NativeStackLimit stackLimit, JS::SourceText<mozilla::Utf8Unit>& srcBuf);
|
||||
|
||||
extern JS_PUBLIC_API already_AddRefed<JS::Stencil> ParseGlobalScript(
|
||||
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options,
|
||||
JS::NativeStackLimit stackLimit, JS::SourceText<char16_t>& srcBuf);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif // js_experimental_ParseScript_h
|
|
@ -312,7 +312,7 @@ template <typename Unit>
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO bug 1773339 maybeCx nullptr could crash here
|
||||
// TODO bug 1773319 maybeCx nullptr could crash here
|
||||
if (input.options.populateDelazificationCache() &&
|
||||
!maybeCx->isHelperThreadContext()) {
|
||||
BorrowingCompilationStencil borrowingStencil(compiler.stencil());
|
||||
|
|
|
@ -190,3 +190,18 @@ JS_PUBLIC_API bool js::CheckWasiRecursionLimit(FrontendContext* fc) {
|
|||
return fc->checkWasiRecursionLimit();
|
||||
}
|
||||
#endif // __wasi__
|
||||
|
||||
FrontendContext* js::NewFrontendContext() {
|
||||
UniquePtr<FrontendContext> fc = MakeUnique<FrontendContext>();
|
||||
if (!fc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!fc->allocateOwnedPool()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return fc.release();
|
||||
}
|
||||
|
||||
void js::DestroyFrontendContext(FrontendContext* fc) { js_delete_poison(fc); }
|
||||
|
|
|
@ -226,6 +226,14 @@ class ManualReportFrontendContext : public FrontendContext {
|
|||
}
|
||||
};
|
||||
|
||||
// Create function for FrontendContext, which is manually allocated and
|
||||
// exclusively owned.
|
||||
extern FrontendContext* NewFrontendContext();
|
||||
|
||||
// Destroy function for FrontendContext, which was allocated with
|
||||
// NewFrontendContext.
|
||||
extern void DestroyFrontendContext(FrontendContext* fc);
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif /* frontend_FrontendContext_h */
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "js/experimental/ParseScript.h"
|
||||
|
||||
#include "frontend/BytecodeCompilation.h" // frontend::CompileGlobalScriptToStencil
|
||||
#include "frontend/CompilationStencil.h" // frontend::{CompilationStencil,CompilationInput}
|
||||
#include "frontend/FrontendContext.h" // frontend::FrontendContext
|
||||
#include "frontend/ScopeBindingCache.h" // frontend::NoScopeBindingCache
|
||||
#include "js/SourceText.h" // JS::SourceText
|
||||
#include "js/Stack.h" // JS::GetNativeStackLimit
|
||||
#include "util/NativeStack.h" // GetNativeStackBase
|
||||
|
||||
using namespace js;
|
||||
|
||||
JS_PUBLIC_API FrontendContext* JS::NewFrontendContext() {
|
||||
MOZ_ASSERT(JS::detail::libraryInitState == JS::detail::InitState::Running,
|
||||
"must call JS_Init prior to creating any FrontendContexts");
|
||||
|
||||
return js::NewFrontendContext();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API void JS::DestroyFrontendContext(FrontendContext* fc) {
|
||||
return js::DestroyFrontendContext(fc);
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
static already_AddRefed<JS::Stencil> ParseGlobalScriptImpl(
|
||||
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options,
|
||||
JS::NativeStackLimit stackLimit, JS::SourceText<CharT>& srcBuf) {
|
||||
ScopeKind scopeKind = ScopeKind::Global;
|
||||
// TODO bug 1773319 nonsyntactic scope
|
||||
|
||||
JS::SourceText<CharT> data(std::move(srcBuf));
|
||||
|
||||
UniquePtr<frontend::CompilationInput> stencilInput_ =
|
||||
fc->getAllocator()->make_unique<frontend::CompilationInput>(options);
|
||||
if (!stencilInput_) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
frontend::NoScopeBindingCache scopeCache;
|
||||
LifoAlloc tempLifoAlloc(JSContext::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
|
||||
RefPtr<frontend::CompilationStencil> stencil_ =
|
||||
frontend::CompileGlobalScriptToStencil(nullptr, fc, stackLimit,
|
||||
tempLifoAlloc, *stencilInput_,
|
||||
&scopeCache, data, scopeKind);
|
||||
return stencil_.forget();
|
||||
}
|
||||
|
||||
// TODO bug 1773319 alloc instantiation storage
|
||||
|
||||
already_AddRefed<JS::Stencil> JS::ParseGlobalScript(
|
||||
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options,
|
||||
JS::NativeStackLimit stackLimit,
|
||||
JS::SourceText<mozilla::Utf8Unit>& srcBuf) {
|
||||
return ParseGlobalScriptImpl(fc, options, stackLimit, srcBuf);
|
||||
}
|
||||
|
||||
already_AddRefed<JS::Stencil> JS::ParseGlobalScript(
|
||||
JS::FrontendContext* fc, const JS::ReadOnlyCompileOptions& options,
|
||||
JS::NativeStackLimit stackLimit, JS::SourceText<char16_t>& srcBuf) {
|
||||
return ParseGlobalScriptImpl(fc, options, stackLimit, srcBuf);
|
||||
}
|
|
@ -64,6 +64,7 @@ UNIFIED_SOURCES += [
|
|||
"ParseNode.cpp",
|
||||
"ParseNodeVerify.cpp",
|
||||
"ParserAtom.cpp",
|
||||
"ParseScript.cpp",
|
||||
"PrivateOpEmitter.cpp",
|
||||
"PropOpEmitter.cpp",
|
||||
"SharedContext.cpp",
|
||||
|
|
|
@ -90,6 +90,7 @@ UNIFIED_SOURCES += [
|
|||
"testOOM.cpp",
|
||||
"testParseJSON.cpp",
|
||||
"testParserAtom.cpp",
|
||||
"testParseScript.cpp",
|
||||
"testPersistentRooted.cpp",
|
||||
"testPreserveJitCode.cpp",
|
||||
"testPrintf.cpp",
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/RefPtr.h" // RefPtr
|
||||
#include "mozilla/ScopeExit.h" // MakeScopeExit
|
||||
#include "mozilla/Utf8.h" // mozilla::Utf8Unit
|
||||
|
||||
#include "frontend/CompilationStencil.h" // JS::Stencil
|
||||
#include "js/CompileOptions.h" // JS::CompileOptions, JS::InstantiateOptions
|
||||
#include "js/experimental/ParseScript.h" // JS::NewFrontendContext
|
||||
#include "js/SourceText.h" // JS::Source{Ownership,Text}
|
||||
#include "jsapi-tests/tests.h"
|
||||
#include "vm/ErrorReporting.h"
|
||||
|
||||
using namespace JS;
|
||||
|
||||
template <typename T>
|
||||
static void dump(const T& data) {
|
||||
js::Fprinter printer(stderr);
|
||||
js::JSONPrinter json(printer, true);
|
||||
|
||||
data->dump(json);
|
||||
printer.put("\n");
|
||||
}
|
||||
|
||||
BEGIN_TEST(testParseScript) {
|
||||
CHECK(testCompile());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool testCompile() {
|
||||
static constexpr std::string_view src = "42\n";
|
||||
static constexpr std::u16string_view src_16 = u"42\n";
|
||||
|
||||
static_assert(src.length() == src_16.length(),
|
||||
"Source buffers must be same length");
|
||||
|
||||
JS::CompileOptions options(cx);
|
||||
|
||||
JS::SourceText<char16_t> buf16;
|
||||
CHECK(buf16.init(cx, src_16.data(), src_16.length(),
|
||||
JS::SourceOwnership::Borrowed));
|
||||
|
||||
JS::SourceText<mozilla::Utf8Unit> buf8;
|
||||
CHECK(buf8.init(cx, src.data(), src.length(), JS::SourceOwnership::Borrowed));
|
||||
|
||||
JS::FrontendContext* fc = JS::NewFrontendContext();
|
||||
CHECK(fc);
|
||||
auto destroyFc =
|
||||
mozilla::MakeScopeExit([fc] { JS::DestroyFrontendContext(fc); });
|
||||
|
||||
RefPtr<JS::Stencil> stencil = ParseGlobalScript(
|
||||
fc, options, cx->stackLimitForCurrentPrincipal(), buf16);
|
||||
CHECK(stencil);
|
||||
CHECK(stencil->scriptExtra.size() == 1);
|
||||
CHECK(stencil->scriptExtra[0].extent.sourceStart == 0);
|
||||
CHECK(stencil->scriptExtra[0].extent.sourceEnd == 3);
|
||||
CHECK(stencil->scriptData.size() == 1);
|
||||
CHECK(stencil->scriptData[0].hasSharedData()); // has generated bytecode
|
||||
CHECK(stencil->scriptData[0].gcThingsLength == 1);
|
||||
|
||||
stencil =
|
||||
ParseGlobalScript(fc, options, cx->stackLimitForCurrentPrincipal(), buf8);
|
||||
CHECK(stencil);
|
||||
|
||||
{
|
||||
JS::SourceText<char16_t> srcBuf;
|
||||
CHECK(srcBuf.init(cx, src_16.data(), src_16.length(),
|
||||
JS::SourceOwnership::Borrowed));
|
||||
|
||||
stencil = ParseGlobalScript(fc, options,
|
||||
cx->stackLimitForCurrentPrincipal(), srcBuf);
|
||||
CHECK(stencil);
|
||||
}
|
||||
|
||||
// TODO bug 1773319 check failure is propagated out
|
||||
|
||||
return true;
|
||||
}
|
||||
END_TEST(testParseScript);
|
|
@ -248,6 +248,7 @@ EXPORTS.js.experimental += [
|
|||
"../public/experimental/Intl.h",
|
||||
"../public/experimental/JitInfo.h",
|
||||
"../public/experimental/JSStencil.h",
|
||||
"../public/experimental/ParseScript.h",
|
||||
"../public/experimental/PCCountProfiling.h",
|
||||
"../public/experimental/SourceHook.h",
|
||||
"../public/experimental/TypedData.h",
|
||||
|
|
Загрузка…
Ссылка в новой задаче