зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1600439 - Replace LazyScriptData with PrivateScriptData. r=jandem
It it straight-foward for users of LazyScriptData to support a single array for closedOverBindings and innerFunctions. As a result, we can use PrivateScriptData as the implementation and eliminate the LazyScriptData type altogether. Depends on D55035 Differential Revision: https://phabricator.services.mozilla.com/D55360 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
6ea700f0c1
Коммит
8ec1a14c33
|
@ -532,6 +532,28 @@ static bool PushFunctionScript(JSContext* cx, Debugger* dbg, HandleFunction fun,
|
|||
return wrapped && NewbornArrayPush(cx, array, ObjectValue(*wrapped));
|
||||
}
|
||||
|
||||
static bool PushInnerFunctions(JSContext* cx, Debugger* dbg, HandleObject array,
|
||||
mozilla::Span<const JS::GCCellPtr> gcThings) {
|
||||
RootedFunction fun(cx);
|
||||
|
||||
for (JS::GCCellPtr gcThing : gcThings) {
|
||||
if (!gcThing.is<JSObject>()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JSObject* obj = &gcThing.as<JSObject>();
|
||||
if (obj->is<JSFunction>()) {
|
||||
fun = &obj->as<JSFunction>();
|
||||
|
||||
if (!PushFunctionScript(cx, dbg, fun, array)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DebuggerScript::CallData::getChildScripts() {
|
||||
if (!ensureScriptMaybeLazy()) {
|
||||
return false;
|
||||
|
@ -543,31 +565,15 @@ bool DebuggerScript::CallData::getChildScripts() {
|
|||
return false;
|
||||
}
|
||||
|
||||
RootedFunction fun(cx);
|
||||
if (obj->getReferent().is<JSScript*>()) {
|
||||
RootedScript script(cx, obj->getReferent().as<JSScript*>());
|
||||
for (JS::GCCellPtr gcThing : script->gcthings()) {
|
||||
if (!gcThing.is<JSObject>()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JSObject* obj = &gcThing.as<JSObject>();
|
||||
if (obj->is<JSFunction>()) {
|
||||
fun = &obj->as<JSFunction>();
|
||||
|
||||
if (!PushFunctionScript(cx, dbg, fun, result)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!PushInnerFunctions(cx, dbg, result, script->gcthings())) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
Rooted<LazyScript*> lazy(cx, obj->getReferent().as<LazyScript*>());
|
||||
|
||||
for (const GCPtrFunction& innerFun : lazy->innerFunctions()) {
|
||||
fun = innerFun;
|
||||
if (!PushFunctionScript(cx, dbg, fun, result)) {
|
||||
return false;
|
||||
}
|
||||
if (!PushInnerFunctions(cx, dbg, result, lazy->gcthings())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,22 @@ class FullParseHandler {
|
|||
lazyOuterFunction_(cx, lazyOuterFunction),
|
||||
lazyInnerFunctionIndex(0),
|
||||
lazyClosedOverBindingIndex(0),
|
||||
sourceKind_(kind) {}
|
||||
sourceKind_(kind) {
|
||||
// The LazyScript::gcthings() array contains the inner function list
|
||||
// followed by the closed-over bindings data. Advance the index for
|
||||
// closed-over bindings to the end of the inner functions. The
|
||||
// nextLazyInnerFunction / nextLazyClosedOverBinding accessors confirm we
|
||||
// have the expected types. See also: LazyScript::Create.
|
||||
if (lazyOuterFunction) {
|
||||
for (JS::GCCellPtr gcThing : lazyOuterFunction->gcthings()) {
|
||||
if (gcThing.is<JSObject>()) {
|
||||
lazyClosedOverBindingIndex++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static NullNode null() { return NullNode(); }
|
||||
|
||||
|
@ -1036,15 +1051,17 @@ class FullParseHandler {
|
|||
bool canSkipLazyInnerFunctions() { return !!lazyOuterFunction_; }
|
||||
bool canSkipLazyClosedOverBindings() { return !!lazyOuterFunction_; }
|
||||
JSFunction* nextLazyInnerFunction() {
|
||||
MOZ_ASSERT(lazyInnerFunctionIndex <
|
||||
lazyOuterFunction_->numInnerFunctions());
|
||||
return lazyOuterFunction_->innerFunctions()[lazyInnerFunctionIndex++];
|
||||
return &lazyOuterFunction_->gcthings()[lazyInnerFunctionIndex++]
|
||||
.as<JSObject>()
|
||||
.as<JSFunction>();
|
||||
}
|
||||
JSAtom* nextLazyClosedOverBinding() {
|
||||
MOZ_ASSERT(lazyClosedOverBindingIndex <
|
||||
lazyOuterFunction_->numClosedOverBindings());
|
||||
return lazyOuterFunction_
|
||||
->closedOverBindings()[lazyClosedOverBindingIndex++];
|
||||
// These entries are either JSAtom* or nullptr, so use the 'asCell()'
|
||||
// accessor which is faster.
|
||||
gc::Cell* cell =
|
||||
lazyOuterFunction_->gcthings()[lazyClosedOverBindingIndex++].asCell();
|
||||
MOZ_ASSERT_IF(cell, cell->is<JSAtom>());
|
||||
return static_cast<JSAtom*>(cell);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -977,17 +977,8 @@ void LazyScript::traceChildren(JSTracer* trc) {
|
|||
TraceNullableEdge(trc, &script_, "script");
|
||||
}
|
||||
|
||||
// We rely on the fact that atoms are always tenured.
|
||||
for (GCPtrAtom& closedOverBinding : closedOverBindings()) {
|
||||
if (closedOverBinding) {
|
||||
TraceEdge(trc, &closedOverBinding, "closedOverBinding");
|
||||
}
|
||||
}
|
||||
|
||||
for (GCPtrFunction& innerFunction : innerFunctions()) {
|
||||
if (innerFunction) {
|
||||
TraceEdge(trc, &innerFunction, "lazyScriptInnerFunction");
|
||||
}
|
||||
if (data_) {
|
||||
data_->trace(trc);
|
||||
}
|
||||
|
||||
if (trc->isMarkingTracer()) {
|
||||
|
@ -1005,16 +996,16 @@ inline void js::GCMarker::eagerlyMarkChildren(LazyScript* thing) {
|
|||
|
||||
// script_ is weak so is not traced here.
|
||||
|
||||
// We rely on the fact that atoms are always tenured.
|
||||
for (GCPtrAtom& closedOverBinding : thing->closedOverBindings()) {
|
||||
if (closedOverBinding) {
|
||||
traverseEdge(thing, static_cast<JSString*>(closedOverBinding));
|
||||
}
|
||||
}
|
||||
|
||||
for (GCPtrFunction& innerFunction : thing->innerFunctions()) {
|
||||
if (innerFunction) {
|
||||
traverseEdge(thing, static_cast<JSObject*>(innerFunction));
|
||||
if (thing->data_) {
|
||||
// Traverse the PrivateScriptData::gcthings() array.
|
||||
for (JS::GCCellPtr& elem : thing->data_->gcthings()) {
|
||||
if (elem.is<JSObject>()) {
|
||||
traverseEdge(thing, &elem.as<JSObject>());
|
||||
} else if (elem.is<JSString>()) {
|
||||
traverseEdge(thing, &elem.as<JSString>());
|
||||
} else {
|
||||
MOZ_ASSERT(!elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -86,11 +86,12 @@ static void TraverseInnerLazyScriptsForLazyScript(
|
|||
JSContext* cx, void* data, LazyScript* enclosingLazyScript,
|
||||
IterateLazyScriptCallback lazyScriptCallback,
|
||||
const JS::AutoRequireNoGC& nogc) {
|
||||
for (JSFunction* fun : enclosingLazyScript->innerFunctions()) {
|
||||
// LazyScript::CreateForXDR temporarily initializes innerFunctions with
|
||||
// its own function, but it should be overwritten with correct
|
||||
// inner functions before getting inserted into parent's innerFunctions.
|
||||
MOZ_ASSERT(fun != enclosingLazyScript->function());
|
||||
for (JS::GCCellPtr gcThing : enclosingLazyScript->gcthings()) {
|
||||
if (!gcThing.is<JSObject>()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JSFunction* fun = &gcThing.as<JSObject>().as<JSFunction>();
|
||||
|
||||
if (!fun->isInterpretedLazy()) {
|
||||
return;
|
||||
|
|
|
@ -241,27 +241,59 @@ template XDRResult js::XDRScriptConst(XDRState<XDR_DECODE>*,
|
|||
|
||||
// Code LazyScript's closed over bindings.
|
||||
template <XDRMode mode>
|
||||
static XDRResult XDRLazyClosedOverBindings(XDRState<mode>* xdr,
|
||||
MutableHandle<LazyScript*> lazy) {
|
||||
/* static */
|
||||
XDRResult LazyScript::XDRScriptData(XDRState<mode>* xdr,
|
||||
HandleScriptSourceObject sourceObject,
|
||||
Handle<LazyScript*> lazy) {
|
||||
JSContext* cx = xdr->cx();
|
||||
|
||||
RootedAtom atom(cx);
|
||||
for (GCPtrAtom& elem : lazy->closedOverBindings()) {
|
||||
uint8_t endOfScopeSentinel;
|
||||
if (mode == XDR_ENCODE) {
|
||||
atom = elem.get();
|
||||
endOfScopeSentinel = !atom;
|
||||
}
|
||||
RootedFunction func(cx);
|
||||
|
||||
MOZ_TRY(xdr->codeUint8(&endOfScopeSentinel));
|
||||
for (JS::GCCellPtr& elem : lazy->data_->gcthings()) {
|
||||
JS::TraceKind kind = elem.kind();
|
||||
|
||||
if (endOfScopeSentinel) {
|
||||
atom = nullptr;
|
||||
} else {
|
||||
MOZ_TRY(XDRAtom(xdr, &atom));
|
||||
}
|
||||
MOZ_TRY(xdr->codeEnum32(&kind));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
elem.init(atom);
|
||||
switch (kind) {
|
||||
case JS::TraceKind::Object: {
|
||||
if (mode == XDR_ENCODE) {
|
||||
func = &elem.as<JSObject>().as<JSFunction>();
|
||||
}
|
||||
MOZ_TRY(XDRInterpretedFunction(xdr, nullptr, sourceObject, &func));
|
||||
if (mode == XDR_DECODE) {
|
||||
MOZ_ASSERT(func->isInterpretedLazy());
|
||||
func->setEnclosingLazyScript(lazy);
|
||||
|
||||
elem = JS::GCCellPtr(func);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JS::TraceKind::String: {
|
||||
if (mode == XDR_ENCODE) {
|
||||
gc::Cell* cell = elem.asCell();
|
||||
MOZ_ASSERT_IF(cell, cell->is<JSAtom>());
|
||||
atom = static_cast<JSAtom*>(cell);
|
||||
}
|
||||
MOZ_TRY(XDRAtom(xdr, &atom));
|
||||
if (mode == XDR_DECODE) {
|
||||
elem = JS::GCCellPtr(static_cast<JSString*>(atom));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JS::TraceKind::Null: {
|
||||
// This is default so nothing to do.
|
||||
MOZ_ASSERT(!elem);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
// Fail in debug, but only soft-fail in release
|
||||
MOZ_ASSERT(false, "Bad XDR class kind");
|
||||
return xdr->fail(JS::TranscodeResult_Failure_BadDecode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -279,8 +311,10 @@ static XDRResult XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun,
|
|||
|
||||
JSContext* cx = xdr->cx();
|
||||
|
||||
RootedScriptSourceObject sourceObject(cx, script->sourceObject());
|
||||
|
||||
uint32_t immutableFlags;
|
||||
uint32_t numClosedOverBindings;
|
||||
uint32_t ngcthings;
|
||||
{
|
||||
uint32_t sourceStart = script->sourceStart();
|
||||
uint32_t sourceEnd = script->sourceEnd();
|
||||
|
@ -292,17 +326,13 @@ static XDRResult XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun,
|
|||
|
||||
if (mode == XDR_ENCODE) {
|
||||
immutableFlags = lazy->immutableFlags();
|
||||
numClosedOverBindings = lazy->numClosedOverBindings();
|
||||
ngcthings = lazy->gcthings().size();
|
||||
MOZ_ASSERT(sourceStart == lazy->sourceStart());
|
||||
MOZ_ASSERT(sourceEnd == lazy->sourceEnd());
|
||||
MOZ_ASSERT(toStringStart == lazy->toStringStart());
|
||||
MOZ_ASSERT(toStringEnd == lazy->toStringEnd());
|
||||
MOZ_ASSERT(lineno == lazy->lineno());
|
||||
MOZ_ASSERT(column == lazy->column());
|
||||
// We can assert we have no inner functions because we don't
|
||||
// relazify scripts with inner functions. See
|
||||
// JSFunction::delazifyLazilyInterpretedFunction.
|
||||
MOZ_ASSERT(!lazy->hasInnerFunctions());
|
||||
if (fun->kind() == FunctionFlags::FunctionKind::ClassConstructor) {
|
||||
numFieldInitializers =
|
||||
(uint32_t)lazy->getFieldInitializers().numFieldInitializers;
|
||||
|
@ -313,14 +343,13 @@ static XDRResult XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun,
|
|||
|
||||
MOZ_TRY(xdr->codeUint32(&immutableFlags));
|
||||
MOZ_TRY(xdr->codeUint32(&numFieldInitializers));
|
||||
MOZ_TRY(xdr->codeUint32(&numClosedOverBindings));
|
||||
MOZ_TRY(xdr->codeUint32(&ngcthings));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
RootedScriptSourceObject sourceObject(cx, script->sourceObject());
|
||||
lazy.set(LazyScript::CreateForXDR(
|
||||
cx, numClosedOverBindings, /* numInnerFunctions = */ 0, fun, script,
|
||||
enclosingScope, sourceObject, immutableFlags, sourceStart, sourceEnd,
|
||||
toStringStart, toStringEnd, lineno, column));
|
||||
cx, ngcthings, fun, script, enclosingScope, sourceObject,
|
||||
immutableFlags, sourceStart, sourceEnd, toStringStart, toStringEnd,
|
||||
lineno, column));
|
||||
if (!lazy) {
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
@ -332,11 +361,11 @@ static XDRResult XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun,
|
|||
}
|
||||
}
|
||||
|
||||
// Code binding names.
|
||||
MOZ_TRY(XDRLazyClosedOverBindings(xdr, lazy));
|
||||
// We can assert we have no inner functions because we don't relazify scripts
|
||||
// with inner functions. See JSFunction::delazifyLazilyInterpretedFunction.
|
||||
MOZ_ASSERT(!lazy->hasInnerFunctions());
|
||||
|
||||
// No need to do anything with inner functions, since we asserted we don't
|
||||
// have any.
|
||||
MOZ_TRY(LazyScript::XDRScriptData(xdr, sourceObject, lazy));
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
@ -1249,8 +1278,7 @@ XDRResult js::XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope,
|
|||
uint32_t column;
|
||||
uint32_t immutableFlags;
|
||||
uint32_t numFieldInitializers;
|
||||
uint32_t numClosedOverBindings;
|
||||
uint32_t numInnerFunctions;
|
||||
uint32_t ngcthings;
|
||||
|
||||
if (mode == XDR_ENCODE) {
|
||||
// Note: it's possible the LazyScript has a non-null script_ pointer
|
||||
|
@ -1272,8 +1300,7 @@ XDRResult js::XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope,
|
|||
} else {
|
||||
numFieldInitializers = UINT32_MAX;
|
||||
}
|
||||
numClosedOverBindings = lazy->numClosedOverBindings();
|
||||
numInnerFunctions = lazy->numInnerFunctions();
|
||||
ngcthings = lazy->gcthings().size();
|
||||
}
|
||||
|
||||
MOZ_TRY(xdr->codeUint32(&sourceStart));
|
||||
|
@ -1284,14 +1311,13 @@ XDRResult js::XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope,
|
|||
MOZ_TRY(xdr->codeUint32(&column));
|
||||
MOZ_TRY(xdr->codeUint32(&immutableFlags));
|
||||
MOZ_TRY(xdr->codeUint32(&numFieldInitializers));
|
||||
MOZ_TRY(xdr->codeUint32(&numClosedOverBindings));
|
||||
MOZ_TRY(xdr->codeUint32(&numInnerFunctions));
|
||||
MOZ_TRY(xdr->codeUint32(&ngcthings));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
lazy.set(LazyScript::CreateForXDR(
|
||||
cx, numClosedOverBindings, numInnerFunctions, fun, nullptr,
|
||||
enclosingScope, sourceObject, immutableFlags, sourceStart, sourceEnd,
|
||||
toStringStart, toStringEnd, lineno, column));
|
||||
cx, ngcthings, fun, nullptr, enclosingScope, sourceObject,
|
||||
immutableFlags, sourceStart, sourceEnd, toStringStart, toStringEnd,
|
||||
lineno, column));
|
||||
if (!lazy) {
|
||||
return xdr->fail(JS::TranscodeResult_Throw);
|
||||
}
|
||||
|
@ -1305,27 +1331,7 @@ XDRResult js::XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope,
|
|||
}
|
||||
}
|
||||
|
||||
// Code closed-over bindings.
|
||||
MOZ_TRY(XDRLazyClosedOverBindings(xdr, lazy));
|
||||
|
||||
// Code inner functions.
|
||||
{
|
||||
RootedFunction func(cx);
|
||||
for (GCPtrFunction& elem : lazy->innerFunctions()) {
|
||||
if (mode == XDR_ENCODE) {
|
||||
func = elem.get();
|
||||
}
|
||||
|
||||
MOZ_TRY(XDRInterpretedFunction(xdr, nullptr, sourceObject, &func));
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
elem.init(func);
|
||||
if (elem->isInterpretedLazy()) {
|
||||
elem->setEnclosingLazyScript(lazy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MOZ_TRY(LazyScript::XDRScriptData(xdr, sourceObject, lazy));
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
@ -5332,9 +5338,8 @@ void JSScript::traceChildren(JSTracer* trc) {
|
|||
}
|
||||
|
||||
void LazyScript::finalize(JSFreeOp* fop) {
|
||||
if (lazyData_) {
|
||||
fop->free_(this, lazyData_, lazyData_->allocationSize(),
|
||||
MemoryUse::LazyScriptData);
|
||||
if (data_) {
|
||||
fop->free_(this, data_, data_->allocationSize(), MemoryUse::LazyScriptData);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5556,103 +5561,16 @@ bool JSScript::formalLivesInArgumentsObject(unsigned argSlot) {
|
|||
return argsObjAliasesFormals() && !formalIsAliased(argSlot);
|
||||
}
|
||||
|
||||
/* static */ size_t LazyScriptData::AllocationSize(
|
||||
uint32_t numClosedOverBindings, uint32_t numInnerFunctions) {
|
||||
size_t size = sizeof(LazyScriptData);
|
||||
|
||||
size += numClosedOverBindings * sizeof(GCPtrAtom);
|
||||
size += numInnerFunctions * sizeof(GCPtrFunction);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
inline size_t LazyScriptData::allocationSize() const {
|
||||
return AllocationSize(numClosedOverBindings_, numInnerFunctions_);
|
||||
}
|
||||
|
||||
// Placement-new elements of an array. This should optimize away for types with
|
||||
// trivial default initiation.
|
||||
template <typename T>
|
||||
void LazyScriptData::initElements(size_t offset, size_t length) {
|
||||
void* raw = offsetToPointer<void>(offset);
|
||||
DefaultInitializeElements<T>(raw, length);
|
||||
}
|
||||
|
||||
LazyScriptData::LazyScriptData(uint32_t numClosedOverBindings,
|
||||
uint32_t numInnerFunctions)
|
||||
: numClosedOverBindings_(numClosedOverBindings),
|
||||
numInnerFunctions_(numInnerFunctions) {
|
||||
// Variable-length data begins immediately after LazyScriptData itself.
|
||||
size_t cursor = sizeof(*this);
|
||||
|
||||
// Default-initialize trailing arrays.
|
||||
|
||||
static_assert(alignof(LazyScriptData) >= alignof(GCPtrAtom),
|
||||
"Incompatible alignment");
|
||||
initElements<GCPtrAtom>(cursor, numClosedOverBindings);
|
||||
cursor += numClosedOverBindings * sizeof(GCPtrAtom);
|
||||
|
||||
static_assert(alignof(GCPtrAtom) >= alignof(GCPtrFunction),
|
||||
"Incompatible alignment");
|
||||
initElements<GCPtrFunction>(cursor, numInnerFunctions);
|
||||
cursor += numInnerFunctions * sizeof(GCPtrFunction);
|
||||
|
||||
// Sanity check
|
||||
MOZ_ASSERT(AllocationSize(numClosedOverBindings, numInnerFunctions) ==
|
||||
cursor);
|
||||
}
|
||||
|
||||
/* static */ LazyScriptData* LazyScriptData::new_(
|
||||
JSContext* cx, uint32_t numClosedOverBindings, uint32_t numInnerFunctions) {
|
||||
// Compute size including trailing arrays
|
||||
size_t size = AllocationSize(numClosedOverBindings, numInnerFunctions);
|
||||
|
||||
// Allocate contiguous raw buffer
|
||||
void* raw = cx->pod_malloc<uint8_t>(size);
|
||||
MOZ_ASSERT(uintptr_t(raw) % alignof(LazyScriptData) == 0);
|
||||
if (!raw) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Constuct the LazyScriptData. Trailing arrays are uninitialized but
|
||||
// GCPtrs are put into a safe state.
|
||||
return new (raw) LazyScriptData(numClosedOverBindings, numInnerFunctions);
|
||||
}
|
||||
|
||||
mozilla::Span<GCPtrAtom> LazyScriptData::closedOverBindings() {
|
||||
size_t offset = sizeof(LazyScriptData);
|
||||
return mozilla::MakeSpan(offsetToPointer<GCPtrAtom>(offset),
|
||||
numClosedOverBindings_);
|
||||
}
|
||||
|
||||
mozilla::Span<GCPtrFunction> LazyScriptData::innerFunctions() {
|
||||
size_t offset =
|
||||
sizeof(LazyScriptData) + sizeof(GCPtrAtom) * numClosedOverBindings_;
|
||||
return mozilla::MakeSpan(offsetToPointer<GCPtrFunction>(offset),
|
||||
numInnerFunctions_);
|
||||
}
|
||||
|
||||
void LazyScriptData::trace(JSTracer* trc) {
|
||||
if (numClosedOverBindings_) {
|
||||
auto array = closedOverBindings();
|
||||
TraceRange(trc, array.size(), array.data(), "closedOverBindings");
|
||||
}
|
||||
|
||||
if (numInnerFunctions_) {
|
||||
auto array = innerFunctions();
|
||||
TraceRange(trc, array.size(), array.data(), "innerFunctions");
|
||||
}
|
||||
}
|
||||
|
||||
LazyScript::LazyScript(JSFunction* fun, uint8_t* stubEntry,
|
||||
ScriptSourceObject& sourceObject, LazyScriptData* data,
|
||||
uint32_t immutableFlags, uint32_t sourceStart,
|
||||
uint32_t sourceEnd, uint32_t toStringStart,
|
||||
uint32_t toStringEnd, uint32_t lineno, uint32_t column)
|
||||
ScriptSourceObject& sourceObject,
|
||||
PrivateScriptData* data, uint32_t immutableFlags,
|
||||
uint32_t sourceStart, uint32_t sourceEnd,
|
||||
uint32_t toStringStart, uint32_t toStringEnd,
|
||||
uint32_t lineno, uint32_t column)
|
||||
: BaseScript(stubEntry, fun, &sourceObject, sourceStart, sourceEnd,
|
||||
toStringStart, toStringEnd),
|
||||
script_(nullptr),
|
||||
lazyData_(data) {
|
||||
data_(data) {
|
||||
lineno_ = lineno;
|
||||
column_ = column;
|
||||
|
||||
|
@ -5694,8 +5612,7 @@ void LazyScript::setEnclosingScope(Scope* enclosingScope) {
|
|||
}
|
||||
|
||||
/* static */
|
||||
LazyScript* LazyScript::CreateRaw(JSContext* cx, uint32_t numClosedOverBindings,
|
||||
uint32_t numInnerFunctions,
|
||||
LazyScript* LazyScript::CreateRaw(JSContext* cx, uint32_t ngcthings,
|
||||
HandleFunction fun,
|
||||
HandleScriptSourceObject sourceObject,
|
||||
uint32_t immutableFlags, uint32_t sourceStart,
|
||||
|
@ -5706,12 +5623,11 @@ LazyScript* LazyScript::CreateRaw(JSContext* cx, uint32_t numClosedOverBindings,
|
|||
|
||||
MOZ_ASSERT(sourceObject);
|
||||
|
||||
// Allocate a LazyScriptData if it will not be empty. Lazy class constructors
|
||||
// also need LazyScriptData for field lists.
|
||||
Rooted<UniquePtr<LazyScriptData>> data(cx);
|
||||
if (numClosedOverBindings || numInnerFunctions || fun->isClassConstructor()) {
|
||||
data.reset(
|
||||
LazyScriptData::new_(cx, numClosedOverBindings, numInnerFunctions));
|
||||
// Allocate a PrivateScriptData if it will not be empty. Lazy class
|
||||
// constructors also need PrivateScriptData for field lists.
|
||||
Rooted<UniquePtr<PrivateScriptData>> data(cx);
|
||||
if (ngcthings || fun->isClassConstructor()) {
|
||||
data.reset(PrivateScriptData::new_(cx, ngcthings));
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -5750,41 +5666,52 @@ LazyScript* LazyScript::Create(
|
|||
immutableFlags |= uint32_t(ImmutableFlags::HasInnerFunctions);
|
||||
}
|
||||
|
||||
uint32_t ngcthings =
|
||||
innerFunctionBoxes.length() + closedOverBindings.length();
|
||||
|
||||
LazyScript* res = LazyScript::CreateRaw(
|
||||
cx, closedOverBindings.length(), innerFunctionBoxes.length(), fun,
|
||||
sourceObject, immutableFlags, sourceStart, sourceEnd, toStringStart,
|
||||
toStringEnd, lineno, column);
|
||||
cx, ngcthings, fun, sourceObject, immutableFlags, sourceStart, sourceEnd,
|
||||
toStringStart, toStringEnd, lineno, column);
|
||||
if (!res) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mozilla::Span<GCPtrAtom> resClosedOverBindings = res->closedOverBindings();
|
||||
for (size_t i = 0; i < res->numClosedOverBindings(); i++) {
|
||||
resClosedOverBindings[i].init(closedOverBindings[i]);
|
||||
// Fill in gcthing data with inner functions followed by binding data.
|
||||
mozilla::Span<JS::GCCellPtr> gcThings =
|
||||
res->data_ ? res->data_->gcthings() : mozilla::Span<JS::GCCellPtr>();
|
||||
auto iter = gcThings.begin();
|
||||
|
||||
for (const frontend::FunctionBox* funbox : innerFunctionBoxes) {
|
||||
JSFunction* fun = funbox->function();
|
||||
*iter++ = JS::GCCellPtr(fun);
|
||||
|
||||
MOZ_ASSERT(fun->isInterpretedLazy());
|
||||
fun->setEnclosingLazyScript(res);
|
||||
}
|
||||
|
||||
mozilla::Span<GCPtrFunction> resInnerFunctions = res->innerFunctions();
|
||||
for (size_t i = 0; i < res->numInnerFunctions(); i++) {
|
||||
resInnerFunctions[i].init(innerFunctionBoxes[i]->function());
|
||||
if (resInnerFunctions[i]->isInterpretedLazy()) {
|
||||
resInnerFunctions[i]->setEnclosingLazyScript(res);
|
||||
for (JSAtom* binding : closedOverBindings) {
|
||||
if (binding) {
|
||||
*iter++ = JS::GCCellPtr(binding);
|
||||
} else {
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(iter == gcThings.end());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* static */
|
||||
LazyScript* LazyScript::CreateForXDR(
|
||||
JSContext* cx, uint32_t numClosedOverBindings, uint32_t numInnerFunctions,
|
||||
HandleFunction fun, HandleScript script, HandleScope enclosingScope,
|
||||
HandleScriptSourceObject sourceObject, uint32_t immutableFlags,
|
||||
uint32_t sourceStart, uint32_t sourceEnd, uint32_t toStringStart,
|
||||
uint32_t toStringEnd, uint32_t lineno, uint32_t column) {
|
||||
JSContext* cx, uint32_t ngcthings, HandleFunction fun, HandleScript script,
|
||||
HandleScope enclosingScope, HandleScriptSourceObject sourceObject,
|
||||
uint32_t immutableFlags, uint32_t sourceStart, uint32_t sourceEnd,
|
||||
uint32_t toStringStart, uint32_t toStringEnd, uint32_t lineno,
|
||||
uint32_t column) {
|
||||
LazyScript* res = LazyScript::CreateRaw(
|
||||
cx, numClosedOverBindings, numInnerFunctions, fun, sourceObject,
|
||||
immutableFlags, sourceStart, sourceEnd, toStringStart, toStringEnd,
|
||||
lineno, column);
|
||||
cx, ngcthings, fun, sourceObject, immutableFlags, sourceStart, sourceEnd,
|
||||
toStringStart, toStringEnd, lineno, column);
|
||||
if (!res) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -3223,48 +3223,6 @@ static_assert(
|
|||
|
||||
namespace js {
|
||||
|
||||
// Variable-length data for LazyScripts. Contains vector of inner functions and
|
||||
// vector of captured property ids.
|
||||
class alignas(uintptr_t) LazyScriptData final {
|
||||
private:
|
||||
uint32_t numClosedOverBindings_ = 0;
|
||||
uint32_t numInnerFunctions_ = 0;
|
||||
|
||||
FieldInitializers fieldInitializers_ = FieldInitializers::Invalid();
|
||||
|
||||
// Size to allocate
|
||||
static size_t AllocationSize(uint32_t numClosedOverBindings,
|
||||
uint32_t numInnerFunctions);
|
||||
size_t allocationSize() const;
|
||||
|
||||
// Translate an offset into a concrete pointer.
|
||||
template <typename T>
|
||||
T* offsetToPointer(size_t offset) {
|
||||
uintptr_t base = reinterpret_cast<uintptr_t>(this);
|
||||
return reinterpret_cast<T*>(base + offset);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void initElements(size_t offset, size_t length);
|
||||
|
||||
LazyScriptData(uint32_t numClosedOverBindings, uint32_t numInnerFunctions);
|
||||
|
||||
public:
|
||||
static LazyScriptData* new_(JSContext* cx, uint32_t numClosedOverBindings,
|
||||
uint32_t numInnerFunctions);
|
||||
|
||||
friend class LazyScript;
|
||||
|
||||
mozilla::Span<GCPtrAtom> closedOverBindings();
|
||||
mozilla::Span<GCPtrFunction> innerFunctions();
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
|
||||
// LazyScriptData has trailing data so isn't copyable or movable.
|
||||
LazyScriptData(const LazyScriptData&) = delete;
|
||||
LazyScriptData& operator=(const LazyScriptData&) = delete;
|
||||
};
|
||||
|
||||
// Information about a script which may be (or has been) lazily compiled to
|
||||
// bytecode from its source.
|
||||
class LazyScript : public BaseScript {
|
||||
|
@ -3353,14 +3311,14 @@ class LazyScript : public BaseScript {
|
|||
// +-----------------+
|
||||
|
||||
// Heap allocated table with any free variables, inner functions, or class
|
||||
// fields. This will be nullptr if none exist.
|
||||
LazyScriptData* lazyData_;
|
||||
// fields. This will be nullptr if none exists.
|
||||
PrivateScriptData* data_ = nullptr;
|
||||
|
||||
static const uint32_t NumClosedOverBindingsBits = 20;
|
||||
static const uint32_t NumInnerFunctionsBits = 20;
|
||||
|
||||
LazyScript(JSFunction* fun, uint8_t* stubEntry,
|
||||
ScriptSourceObject& sourceObject, LazyScriptData* data,
|
||||
ScriptSourceObject& sourceObject, PrivateScriptData* data,
|
||||
uint32_t immutableFlags, uint32_t sourceStart, uint32_t sourceEnd,
|
||||
uint32_t toStringStart, uint32_t toStringEnd, uint32_t lineno,
|
||||
uint32_t column);
|
||||
|
@ -3368,8 +3326,8 @@ class LazyScript : public BaseScript {
|
|||
// Create a LazyScript without initializing the closedOverBindings and the
|
||||
// innerFunctions. To be GC-safe, the caller must initialize both vectors
|
||||
// with valid atoms and functions.
|
||||
static LazyScript* CreateRaw(JSContext* cx, uint32_t numClosedOverBindings,
|
||||
uint32_t numInnerFunctions, HandleFunction fun,
|
||||
static LazyScript* CreateRaw(JSContext* cx, uint32_t ngcthings,
|
||||
HandleFunction fun,
|
||||
HandleScriptSourceObject sourceObject,
|
||||
uint32_t immutableFlags, uint32_t sourceStart,
|
||||
uint32_t sourceEnd, uint32_t toStringStart,
|
||||
|
@ -3400,12 +3358,19 @@ class LazyScript : public BaseScript {
|
|||
//
|
||||
// The sourceObject and enclosingScope arguments may be null if the
|
||||
// enclosing function is also lazy.
|
||||
static LazyScript* CreateForXDR(
|
||||
JSContext* cx, uint32_t numClosedOverBindings, uint32_t numInnerFunctions,
|
||||
HandleFunction fun, HandleScript script, HandleScope enclosingScope,
|
||||
HandleScriptSourceObject sourceObject, uint32_t immutableFlags,
|
||||
uint32_t sourceStart, uint32_t sourceEnd, uint32_t toStringStart,
|
||||
uint32_t toStringEnd, uint32_t lineno, uint32_t column);
|
||||
static LazyScript* CreateForXDR(JSContext* cx, uint32_t ngcthings,
|
||||
HandleFunction fun, HandleScript script,
|
||||
HandleScope enclosingScope,
|
||||
HandleScriptSourceObject sourceObject,
|
||||
uint32_t immutableFlags, uint32_t sourceStart,
|
||||
uint32_t sourceEnd, uint32_t toStringStart,
|
||||
uint32_t toStringEnd, uint32_t lineno,
|
||||
uint32_t column);
|
||||
|
||||
template <XDRMode mode>
|
||||
static XDRResult XDRScriptData(XDRState<mode>* xdr,
|
||||
HandleScriptSourceObject sourceObject,
|
||||
Handle<LazyScript*> lazy);
|
||||
|
||||
bool canRelazify() const {
|
||||
// Only functions without inner functions or direct eval are re-lazified.
|
||||
|
@ -3441,20 +3406,8 @@ class LazyScript : public BaseScript {
|
|||
return enclosingScope()->hasOnChain(ScopeKind::NonSyntactic);
|
||||
}
|
||||
|
||||
mozilla::Span<GCPtrAtom> closedOverBindings() {
|
||||
return lazyData_ ? lazyData_->closedOverBindings()
|
||||
: mozilla::Span<GCPtrAtom>();
|
||||
}
|
||||
uint32_t numClosedOverBindings() const {
|
||||
return lazyData_ ? lazyData_->closedOverBindings().size() : 0;
|
||||
};
|
||||
|
||||
mozilla::Span<GCPtrFunction> innerFunctions() {
|
||||
return lazyData_ ? lazyData_->innerFunctions()
|
||||
: mozilla::Span<GCPtrFunction>();
|
||||
}
|
||||
uint32_t numInnerFunctions() const {
|
||||
return lazyData_ ? lazyData_->innerFunctions().size() : 0;
|
||||
mozilla::Span<JS::GCCellPtr> gcthings() {
|
||||
return data_ ? data_->gcthings() : mozilla::Span<JS::GCCellPtr>();
|
||||
}
|
||||
|
||||
frontend::ParseGoal parseGoal() const {
|
||||
|
@ -3472,13 +3425,13 @@ class LazyScript : public BaseScript {
|
|||
void setWrappedByDebugger() { setFlag(MutableFlags::WrappedByDebugger); }
|
||||
|
||||
void setFieldInitializers(FieldInitializers fieldInitializers) {
|
||||
MOZ_ASSERT(lazyData_);
|
||||
lazyData_->fieldInitializers_ = fieldInitializers;
|
||||
MOZ_ASSERT(data_);
|
||||
data_->setFieldInitializers(fieldInitializers);
|
||||
}
|
||||
|
||||
const FieldInitializers& getFieldInitializers() const {
|
||||
MOZ_ASSERT(lazyData_);
|
||||
return lazyData_->fieldInitializers_;
|
||||
MOZ_ASSERT(data_);
|
||||
return data_->getFieldInitializers();
|
||||
}
|
||||
|
||||
// Returns true if the enclosing script has ever been compiled.
|
||||
|
@ -3498,7 +3451,7 @@ class LazyScript : public BaseScript {
|
|||
static const JS::TraceKind TraceKind = JS::TraceKind::LazyScript;
|
||||
|
||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
|
||||
return mallocSizeOf(lazyData_);
|
||||
return mallocSizeOf(data_);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче