mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-07 09:54:42 +00:00
Bug 1837964 - Part 3: Split nsXULPrototypeScript::Compile into nsXULPrototypeScript::{Compile,CompileMaybeOffThread}. r=smaug
Given the text ownership is different and the behavior is also different, it's better having separate functions. Also this simplifies the later patch that touches off-thread case. Differential Revision: https://phabricator.services.mozilla.com/D181205
This commit is contained in:
parent
dbc77b97e8
commit
af843d8fd0
@ -855,9 +855,8 @@ PrototypeDocumentContentSink::OnStreamComplete(nsIStreamLoader* aLoader,
|
||||
rv = ScriptLoader::ConvertToUTF8(channel, string, stringLen, u""_ns,
|
||||
mDocument, units, unitsLength);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = mCurrentScriptProto->Compile(units.release(), unitsLength,
|
||||
JS::SourceOwnership::TakeOwnership, uri,
|
||||
1, mDocument, this);
|
||||
rv = mCurrentScriptProto->CompileMaybeOffThread(
|
||||
std::move(units), unitsLength, uri, 1, mDocument, this);
|
||||
if (NS_SUCCEEDED(rv) && !mCurrentScriptProto->HasStencil()) {
|
||||
mOffThreadCompiling = true;
|
||||
mDocument->BlockOnload();
|
||||
|
@ -416,8 +416,8 @@ XULContentSinkImpl::HandleEndElement(const char16_t* aName) {
|
||||
|
||||
script->mOutOfLine = false;
|
||||
if (doc) {
|
||||
script->Compile(mText, mTextLength, JS::SourceOwnership::Borrowed,
|
||||
mDocumentURL, script->mLineNo, doc);
|
||||
script->Compile(mText, mTextLength, mDocumentURL, script->mLineNo,
|
||||
doc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1610,11 +1610,20 @@ static nsresult ReadStencil(nsIObjectInputStream* aStream, JSContext* aCx,
|
||||
return rv;
|
||||
}
|
||||
|
||||
void nsXULPrototypeScript::FillCompileOptions(JS::CompileOptions& options) {
|
||||
void nsXULPrototypeScript::FillCompileOptions(JS::CompileOptions& aOptions,
|
||||
const char* aFilename,
|
||||
uint32_t aLineNo) {
|
||||
// NOTE: This method shouldn't change any field which also exists in
|
||||
// JS::InstantiateOptions. If such field is added,
|
||||
// nsXULPrototypeScript::InstantiateScript should also call this method.
|
||||
|
||||
// If the script was inline, tell the JS parser to save source for
|
||||
// Function.prototype.toSource(). If it's out of line, we retrieve the
|
||||
// source from the files on demand.
|
||||
options.setSourceIsLazy(mOutOfLine);
|
||||
aOptions.setSourceIsLazy(mOutOfLine);
|
||||
|
||||
aOptions.setIntroductionType(mOutOfLine ? "srcScript" : "inlineScript")
|
||||
.setFileAndLine(aFilename, mOutOfLine ? 1 : aLineNo);
|
||||
}
|
||||
|
||||
nsresult nsXULPrototypeScript::Serialize(
|
||||
@ -1853,26 +1862,18 @@ static void OffThreadScriptReceiverCallback(JS::OffThreadToken* aToken,
|
||||
NS_DispatchToMainThread(notify);
|
||||
}
|
||||
|
||||
template <typename Unit>
|
||||
nsresult nsXULPrototypeScript::Compile(
|
||||
const Unit* aText, size_t aTextLength, JS::SourceOwnership aOwnership,
|
||||
nsIURI* aURI, uint32_t aLineNo, Document* aDocument,
|
||||
nsIOffThreadScriptReceiver* aOffThreadReceiver /* = nullptr */) {
|
||||
// We'll compile the script in the compilation scope.
|
||||
nsresult nsXULPrototypeScript::Compile(const char16_t* aText,
|
||||
size_t aTextLength, nsIURI* aURI,
|
||||
uint32_t aLineNo, Document* aDocument) {
|
||||
AutoJSAPI jsapi;
|
||||
if (!jsapi.Init(xpc::CompilationScope())) {
|
||||
if (aOwnership == JS::SourceOwnership::TakeOwnership) {
|
||||
// In this early-exit case -- before the |srcBuf.init| call will
|
||||
// own |aText| -- we must relinquish ownership manually.
|
||||
js_free(const_cast<Unit*>(aText));
|
||||
}
|
||||
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
JS::SourceText<Unit> srcBuf;
|
||||
if (NS_WARN_IF(!srcBuf.init(cx, aText, aTextLength, aOwnership))) {
|
||||
JS::SourceText<char16_t> srcBuf;
|
||||
if (NS_WARN_IF(!srcBuf.init(cx, aText, aTextLength,
|
||||
JS::SourceOwnership::Borrowed))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -1882,15 +1883,45 @@ nsresult nsXULPrototypeScript::Compile(
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Ok, compile it to create a prototype script object!
|
||||
JS::CompileOptions options(cx);
|
||||
FillCompileOptions(options);
|
||||
options.setIntroductionType(mOutOfLine ? "srcScript" : "inlineScript")
|
||||
.setFileAndLine(urlspec.get(), mOutOfLine ? 1 : aLineNo);
|
||||
FillCompileOptions(options, urlspec.get(), aLineNo);
|
||||
|
||||
JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
|
||||
RefPtr<JS::Stencil> stencil =
|
||||
JS::CompileGlobalScriptToStencil(cx, options, srcBuf);
|
||||
if (!stencil) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
Set(stencil);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aOffThreadReceiver && JS::CanCompileOffThread(cx, options, aTextLength)) {
|
||||
nsresult nsXULPrototypeScript::CompileMaybeOffThread(
|
||||
mozilla::UniquePtr<mozilla::Utf8Unit[], JS::FreePolicy>&& aText,
|
||||
size_t aTextLength, nsIURI* aURI, uint32_t aLineNo, Document* aDocument,
|
||||
nsIOffThreadScriptReceiver* aOffThreadReceiver) {
|
||||
MOZ_ASSERT(aOffThreadReceiver);
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
if (!jsapi.Init(xpc::CompilationScope())) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
JS::SourceText<mozilla::Utf8Unit> srcBuf;
|
||||
if (NS_WARN_IF(!srcBuf.init(cx, std::move(aText), aTextLength))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsAutoCString urlspec;
|
||||
nsresult rv = aURI->GetSpec(urlspec);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
JS::CompileOptions options(cx);
|
||||
FillCompileOptions(options, urlspec.get(), aLineNo);
|
||||
|
||||
if (JS::CanCompileOffThread(cx, options, aTextLength)) {
|
||||
if (!JS::CompileToStencilOffThread(
|
||||
cx, options, srcBuf, OffThreadScriptReceiverCallback,
|
||||
static_cast<void*>(aOffThreadReceiver))) {
|
||||
@ -1909,21 +1940,11 @@ nsresult nsXULPrototypeScript::Compile(
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
template nsresult nsXULPrototypeScript::Compile<char16_t>(
|
||||
const char16_t* aText, size_t aTextLength, JS::SourceOwnership aOwnership,
|
||||
nsIURI* aURI, uint32_t aLineNo, Document* aDocument,
|
||||
nsIOffThreadScriptReceiver* aOffThreadReceiver);
|
||||
template nsresult nsXULPrototypeScript::Compile<Utf8Unit>(
|
||||
const Utf8Unit* aText, size_t aTextLength, JS::SourceOwnership aOwnership,
|
||||
nsIURI* aURI, uint32_t aLineNo, Document* aDocument,
|
||||
nsIOffThreadScriptReceiver* aOffThreadReceiver);
|
||||
|
||||
nsresult nsXULPrototypeScript::InstantiateScript(
|
||||
JSContext* aCx, JS::MutableHandle<JSScript*> aScript) {
|
||||
MOZ_ASSERT(mStencil);
|
||||
|
||||
JS::CompileOptions options(aCx);
|
||||
FillCompileOptions(options);
|
||||
JS::InstantiateOptions instantiateOptions(options);
|
||||
aScript.set(JS::InstantiateGlobalStencil(aCx, instantiateOptions, mStencil));
|
||||
if (!aScript) {
|
||||
|
@ -20,11 +20,13 @@
|
||||
#include "js/SourceText.h"
|
||||
#include "js/TracingAPI.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/Utility.h" // JS::FreePolicy
|
||||
#include "mozilla/AlreadyAddRefed.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/dom/DOMString.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/FragmentOrElement.h"
|
||||
@ -213,7 +215,8 @@ class nsXULPrototypeScript : public nsXULPrototypeNode {
|
||||
private:
|
||||
virtual ~nsXULPrototypeScript() = default;
|
||||
|
||||
void FillCompileOptions(JS::CompileOptions& options);
|
||||
void FillCompileOptions(JS::CompileOptions& aOptions, const char* aFilename,
|
||||
uint32_t aLineNo);
|
||||
|
||||
public:
|
||||
virtual nsresult Serialize(
|
||||
@ -228,11 +231,31 @@ class nsXULPrototypeScript : public nsXULPrototypeNode {
|
||||
nsresult DeserializeOutOfLine(nsIObjectInputStream* aInput,
|
||||
nsXULPrototypeDocument* aProtoDoc);
|
||||
|
||||
template <typename Unit>
|
||||
nsresult Compile(const Unit* aText, size_t aTextLength,
|
||||
JS::SourceOwnership aOwnership, nsIURI* aURI,
|
||||
uint32_t aLineNo, mozilla::dom::Document* aDocument,
|
||||
nsIOffThreadScriptReceiver* aOffThreadReceiver = nullptr);
|
||||
// Compile given JS source text synchronously.
|
||||
//
|
||||
// This method doesn't take the ownership of aText, but borrows during the
|
||||
// compilation.
|
||||
//
|
||||
// If successfully compiled, `HasStencil()` returns true.
|
||||
nsresult Compile(const char16_t* aText, size_t aTextLength, nsIURI* aURI,
|
||||
uint32_t aLineNo, mozilla::dom::Document* aDocument);
|
||||
|
||||
// Compile given JS source text possibly in off-thread.
|
||||
//
|
||||
// This method takes the ownership of aText.
|
||||
//
|
||||
// If this doesn't use off-thread compilation and successfully compiled,
|
||||
// `HasStencil()` returns true.
|
||||
//
|
||||
// If this uses off-thread compilation, `HasStencil()` returns false, and
|
||||
// once the compilation finishes, aOffThreadReceiver gets notified with the
|
||||
// compiled stencil. The callback is responsible for calling `Set()` with
|
||||
// the stencil.
|
||||
nsresult CompileMaybeOffThread(
|
||||
mozilla::UniquePtr<mozilla::Utf8Unit[], JS::FreePolicy>&& aText,
|
||||
size_t aTextLength, nsIURI* aURI, uint32_t aLineNo,
|
||||
mozilla::dom::Document* aDocument,
|
||||
nsIOffThreadScriptReceiver* aOffThreadReceiver);
|
||||
|
||||
void Set(JS::Stencil* aStencil);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user