зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1615143 - Move JSScript::lazyScript / LazyScript::script_ to BaseScript. r=jandem
This patch creates a union field in BaseScript to hold either form of pointer. An IsLazyScript flag is added to ImmutableFlags to know which union arm to trace. We are also able to use a single trace function for both. IsLazyScript flag to disambiguate the union arms. Note that this field will be removed entirely once the JSScript and LazyScript instances are merged. Differential Revision: https://phabricator.services.mozilla.com/D62680 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
cd00e1a950
Коммит
432b2a7b18
|
@ -937,10 +937,13 @@ static void CheckFlagsOnDelazification(uint32_t lazy, uint32_t nonLazy) {
|
||||||
// These flags are computed for lazy scripts and may have a different
|
// These flags are computed for lazy scripts and may have a different
|
||||||
// definition for non-lazy scripts.
|
// definition for non-lazy scripts.
|
||||||
//
|
//
|
||||||
|
// IsLazyScript: This flag will be removed in Bug 1529456.
|
||||||
|
//
|
||||||
// TreatAsRunOnce: Some conditions depend on parent context and are
|
// TreatAsRunOnce: Some conditions depend on parent context and are
|
||||||
// computed during lazy parsing, while other conditions
|
// computed during lazy parsing, while other conditions
|
||||||
// need to full parse.
|
// need to full parse.
|
||||||
constexpr uint32_t CustomFlagsMask =
|
constexpr uint32_t CustomFlagsMask =
|
||||||
|
uint32_t(BaseScript::ImmutableFlags::IsLazyScript) |
|
||||||
uint32_t(BaseScript::ImmutableFlags::TreatAsRunOnce);
|
uint32_t(BaseScript::ImmutableFlags::TreatAsRunOnce);
|
||||||
|
|
||||||
// These flags are expected to match between lazy and full parsing.
|
// These flags are expected to match between lazy and full parsing.
|
||||||
|
|
|
@ -4918,7 +4918,7 @@ void js::gc::SweepLazyScripts(GCParallelTask* task) {
|
||||||
for (SweepGroupZonesIter zone(task->gc); !zone.done(); zone.next()) {
|
for (SweepGroupZonesIter zone(task->gc); !zone.done(); zone.next()) {
|
||||||
AutoSetThreadIsSweeping threadIsSweeping(zone);
|
AutoSetThreadIsSweeping threadIsSweeping(zone);
|
||||||
for (auto i = zone->cellIter<LazyScript>(); !i.done(); i.next()) {
|
for (auto i = zone->cellIter<LazyScript>(); !i.done(); i.next()) {
|
||||||
WeakHeapPtrScript* edge = &i.unbarrieredGet()->script_;
|
WeakHeapPtrScript* edge = &i.unbarrieredGet()->u.script_;
|
||||||
if (*edge && IsAboutToBeFinalized(edge)) {
|
if (*edge && IsAboutToBeFinalized(edge)) {
|
||||||
*edge = nullptr;
|
*edge = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -750,20 +750,15 @@ struct ImplicitEdgeHolderType {
|
||||||
|
|
||||||
// For now, we only handle JSObject* and JSScript* keys, but the linear time
|
// For now, we only handle JSObject* and JSScript* keys, but the linear time
|
||||||
// algorithm can be easily extended by adding in more types here, then making
|
// algorithm can be easily extended by adding in more types here, then making
|
||||||
// GCMarker::traverse<T> call markPotentialEphemeronKey.
|
// GCMarker::traverse<T> call markImplicitEdges.
|
||||||
template <>
|
template <>
|
||||||
struct ImplicitEdgeHolderType<JSObject*> {
|
struct ImplicitEdgeHolderType<JSObject*> {
|
||||||
typedef JSObject* Type;
|
typedef JSObject* Type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct ImplicitEdgeHolderType<JSScript*> {
|
struct ImplicitEdgeHolderType<BaseScript*> {
|
||||||
typedef JSScript* Type;
|
typedef BaseScript* Type;
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct ImplicitEdgeHolderType<LazyScript*> {
|
|
||||||
typedef LazyScript* Type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void GCMarker::markEphemeronValues(gc::Cell* markedCell,
|
void GCMarker::markEphemeronValues(gc::Cell* markedCell,
|
||||||
|
@ -809,8 +804,7 @@ void GCMarker::markImplicitEdges(T* thing) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template void GCMarker::markImplicitEdges(JSObject*);
|
template void GCMarker::markImplicitEdges(JSObject*);
|
||||||
template void GCMarker::markImplicitEdges(JSScript*);
|
template void GCMarker::markImplicitEdges(BaseScript*);
|
||||||
template void GCMarker::markImplicitEdges(LazyScript*);
|
|
||||||
|
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
|
@ -1135,19 +1129,24 @@ void BaseScript::traceChildren(JSTracer* trc) {
|
||||||
DebugAPI::traceDebugScript(trc, script);
|
DebugAPI::traceDebugScript(trc, script);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void LazyScript::traceChildren(JSTracer* trc) {
|
|
||||||
BaseScript::traceChildren(trc);
|
|
||||||
|
|
||||||
|
// Trace the edge to our twin. Note that it will have the opposite type of
|
||||||
|
// current script.
|
||||||
|
if (isLazyScript()) {
|
||||||
if (trc->traceWeakEdges()) {
|
if (trc->traceWeakEdges()) {
|
||||||
TraceNullableEdge(trc, &script_, "script");
|
TraceNullableEdge(trc, &u.script_, "script");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (u.lazyScript) {
|
||||||
|
TraceManuallyBarrieredEdge(trc, &u.lazyScript, "lazyScript");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trc->isMarkingTracer()) {
|
if (trc->isMarkingTracer()) {
|
||||||
GCMarker::fromTracer(trc)->markImplicitEdges(this);
|
GCMarker::fromTracer(trc)->markImplicitEdges(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void js::GCMarker::eagerlyMarkChildren(LazyScript* thing) {
|
inline void js::GCMarker::eagerlyMarkChildren(LazyScript* thing) {
|
||||||
traverseEdge(thing, static_cast<JSObject*>(thing->functionOrGlobal_));
|
traverseEdge(thing, static_cast<JSObject*>(thing->functionOrGlobal_));
|
||||||
traverseEdge(thing, static_cast<JSObject*>(thing->sourceObject_));
|
traverseEdge(thing, static_cast<JSObject*>(thing->sourceObject_));
|
||||||
|
|
|
@ -5273,18 +5273,6 @@ void ScriptWarmUpData::trace(JSTracer* trc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSScript::traceChildren(JSTracer* trc) {
|
|
||||||
BaseScript::traceChildren(trc);
|
|
||||||
|
|
||||||
if (lazyScript) {
|
|
||||||
TraceManuallyBarrieredEdge(trc, &lazyScript, "lazyScript");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (trc->isMarkingTracer()) {
|
|
||||||
GCMarker::fromTracer(trc)->markImplicitEdges(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t JSScript::calculateLiveFixed(jsbytecode* pc) {
|
size_t JSScript::calculateLiveFixed(jsbytecode* pc) {
|
||||||
size_t nlivefixed = numAlwaysLiveFixedSlots();
|
size_t nlivefixed = numAlwaysLiveFixedSlots();
|
||||||
|
|
||||||
|
@ -5505,8 +5493,8 @@ bool JSScript::formalLivesInArgumentsObject(unsigned argSlot) {
|
||||||
|
|
||||||
void LazyScript::initScript(JSScript* script) {
|
void LazyScript::initScript(JSScript* script) {
|
||||||
MOZ_ASSERT(script);
|
MOZ_ASSERT(script);
|
||||||
MOZ_ASSERT(!script_.unbarrieredGet());
|
MOZ_ASSERT(!u.script_.unbarrieredGet());
|
||||||
script_.set(script);
|
u.script_.set(script);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
|
@ -5536,6 +5524,11 @@ LazyScript* LazyScript::CreateRaw(JSContext* cx, uint32_t ngcthings,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mark this BaseScript as being a LazyScript and construct the appropriate
|
||||||
|
// union arm.
|
||||||
|
lazy->setFlag(ImmutableFlags::IsLazyScript);
|
||||||
|
new (&lazy->u.script_) WeakHeapPtrScript(nullptr);
|
||||||
|
|
||||||
// Allocate a PrivateScriptData if it will not be empty. Lazy class
|
// Allocate a PrivateScriptData if it will not be empty. Lazy class
|
||||||
// constructors also need PrivateScriptData for field lists.
|
// constructors also need PrivateScriptData for field lists.
|
||||||
if (ngcthings || fun->isClassConstructor()) {
|
if (ngcthings || fun->isClassConstructor()) {
|
||||||
|
|
|
@ -2021,6 +2021,25 @@ class BaseScript : public gc::TenuredCell {
|
||||||
|
|
||||||
ScriptWarmUpData warmUpData_ = {};
|
ScriptWarmUpData warmUpData_ = {};
|
||||||
|
|
||||||
|
union TwinPointer {
|
||||||
|
// Information used to re-lazify a lazily-parsed interpreted function.
|
||||||
|
js::LazyScript* lazyScript;
|
||||||
|
|
||||||
|
// If non-nullptr, the script has been compiled and this is a forwarding
|
||||||
|
// pointer to the result. This is a weak pointer: after relazification, we
|
||||||
|
// can collect the script if there are no other pointers to it.
|
||||||
|
WeakHeapPtrScript script_;
|
||||||
|
|
||||||
|
// Default to the lazyScript union arm which is used by JSScripts. This
|
||||||
|
// corresponds to the default IsLazyScript flag being clear. Remember that a
|
||||||
|
// non-lazy script points *to* a LazyScript.
|
||||||
|
TwinPointer() : lazyScript(nullptr) {}
|
||||||
|
|
||||||
|
// The BaseScript uses a finalizer instead of a C++ destructor so this
|
||||||
|
// should never be run. We need to define to appease compiler though.
|
||||||
|
~TwinPointer() { MOZ_CRASH(); }
|
||||||
|
} u;
|
||||||
|
|
||||||
BaseScript(uint8_t* stubEntry, JSObject* functionOrGlobal,
|
BaseScript(uint8_t* stubEntry, JSObject* functionOrGlobal,
|
||||||
ScriptSourceObject* sourceObject, uint32_t sourceStart,
|
ScriptSourceObject* sourceObject, uint32_t sourceStart,
|
||||||
uint32_t sourceEnd, uint32_t toStringStart, uint32_t toStringEnd,
|
uint32_t sourceEnd, uint32_t toStringStart, uint32_t toStringEnd,
|
||||||
|
@ -2131,6 +2150,10 @@ class BaseScript : public gc::TenuredCell {
|
||||||
|
|
||||||
// Whether this script contains a direct eval statement.
|
// Whether this script contains a direct eval statement.
|
||||||
HasDirectEval = 1 << 27,
|
HasDirectEval = 1 << 27,
|
||||||
|
|
||||||
|
// Whether this BaseScript is a LazyScript. This flag will be removed after
|
||||||
|
// LazyScript and JSScript are merged in Bug 1529456.
|
||||||
|
IsLazyScript = 1 << 28,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mutable flags typically store information about runtime or deoptimization
|
// Mutable flags typically store information about runtime or deoptimization
|
||||||
|
@ -2376,6 +2399,7 @@ setterLevel: \
|
||||||
ShouldDeclareArguments)
|
ShouldDeclareArguments)
|
||||||
IMMUTABLE_FLAG_GETTER(isFunction, IsFunction)
|
IMMUTABLE_FLAG_GETTER(isFunction, IsFunction)
|
||||||
IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(hasDirectEval, HasDirectEval)
|
IMMUTABLE_FLAG_GETTER_SETTER_PUBLIC(hasDirectEval, HasDirectEval)
|
||||||
|
IMMUTABLE_FLAG_GETTER(isLazyScript, IsLazyScript)
|
||||||
|
|
||||||
MUTABLE_FLAG_GETTER_SETTER(warnedAboutUndefinedProp, WarnedAboutUndefinedProp)
|
MUTABLE_FLAG_GETTER_SETTER(warnedAboutUndefinedProp, WarnedAboutUndefinedProp)
|
||||||
MUTABLE_FLAG_GETTER_SETTER(hasRunOnce, HasRunOnce)
|
MUTABLE_FLAG_GETTER_SETTER(hasRunOnce, HasRunOnce)
|
||||||
|
@ -2498,10 +2522,11 @@ setterLevel: \
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
void traceChildren(JSTracer* trc);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
friend class GCMarker;
|
||||||
|
friend void js::gc::SweepLazyScripts(GCParallelTask* task);
|
||||||
|
|
||||||
|
void traceChildren(JSTracer* trc);
|
||||||
void finalize(JSFreeOp* fop);
|
void finalize(JSFreeOp* fop);
|
||||||
|
|
||||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
|
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
|
||||||
|
@ -2565,14 +2590,6 @@ struct DeletePolicy<js::PrivateScriptData>
|
||||||
} /* namespace JS */
|
} /* namespace JS */
|
||||||
|
|
||||||
class JSScript : public js::BaseScript {
|
class JSScript : public js::BaseScript {
|
||||||
private:
|
|
||||||
/* Information used to re-lazify a lazily-parsed interpreted function. */
|
|
||||||
js::LazyScript* lazyScript = nullptr;
|
|
||||||
|
|
||||||
//
|
|
||||||
// End of fields. Start methods.
|
|
||||||
//
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <js::XDRMode mode>
|
template <js::XDRMode mode>
|
||||||
friend js::XDRResult js::XDRScript(js::XDRState<mode>* xdr,
|
friend js::XDRResult js::XDRScript(js::XDRState<mode>* xdr,
|
||||||
|
@ -2847,13 +2864,13 @@ class JSScript : public js::BaseScript {
|
||||||
// discard most JIT code before attempting relazification.
|
// discard most JIT code before attempting relazification.
|
||||||
// - Specific subsystems (such as the Debugger) may disable scripts for
|
// - Specific subsystems (such as the Debugger) may disable scripts for
|
||||||
// their own reasons.
|
// their own reasons.
|
||||||
bool lazyAvailable = selfHosted() || lazyScript;
|
bool lazyAvailable = selfHosted() || u.lazyScript;
|
||||||
return isRelazifiable() && lazyAvailable && !hasJitScript() &&
|
return isRelazifiable() && lazyAvailable && !hasJitScript() &&
|
||||||
!doNotRelazify();
|
!doNotRelazify();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLazyScript(js::LazyScript* lazy) { lazyScript = lazy; }
|
void setLazyScript(js::LazyScript* lazy) { u.lazyScript = lazy; }
|
||||||
js::LazyScript* maybeLazyScript() { return lazyScript; }
|
js::LazyScript* maybeLazyScript() { return u.lazyScript; }
|
||||||
|
|
||||||
bool isModule() const {
|
bool isModule() const {
|
||||||
MOZ_ASSERT(hasFlag(ImmutableFlags::IsModule) ==
|
MOZ_ASSERT(hasFlag(ImmutableFlags::IsModule) ==
|
||||||
|
@ -3187,8 +3204,6 @@ class JSScript : public js::BaseScript {
|
||||||
|
|
||||||
static const JS::TraceKind TraceKind = JS::TraceKind::Script;
|
static const JS::TraceKind TraceKind = JS::TraceKind::Script;
|
||||||
|
|
||||||
void traceChildren(JSTracer* trc);
|
|
||||||
|
|
||||||
// A helper class to prevent relazification of the given function's script
|
// A helper class to prevent relazification of the given function's script
|
||||||
// while it's holding on to it. This class automatically roots the script.
|
// while it's holding on to it. This class automatically roots the script.
|
||||||
class AutoDelazify;
|
class AutoDelazify;
|
||||||
|
@ -3231,12 +3246,6 @@ namespace js {
|
||||||
// Information about a script which may be (or has been) lazily compiled to
|
// Information about a script which may be (or has been) lazily compiled to
|
||||||
// bytecode from its source.
|
// bytecode from its source.
|
||||||
class LazyScript : public BaseScript {
|
class LazyScript : public BaseScript {
|
||||||
// If non-nullptr, the script has been compiled and this is a forwarding
|
|
||||||
// pointer to the result. This is a weak pointer: after relazification, we
|
|
||||||
// can collect the script if there are no other pointers to it.
|
|
||||||
WeakHeapPtrScript script_ = nullptr;
|
|
||||||
friend void js::gc::SweepLazyScripts(GCParallelTask* task);
|
|
||||||
|
|
||||||
// The BaseScript::warmUpData_ field is used as follows:
|
// The BaseScript::warmUpData_ field is used as follows:
|
||||||
// * LazyScript in which the script is nested. This case happens if the
|
// * LazyScript in which the script is nested. This case happens if the
|
||||||
// enclosing script is lazily parsed and have never been compiled.
|
// enclosing script is lazily parsed and have never been compiled.
|
||||||
|
@ -3370,11 +3379,11 @@ class LazyScript : public BaseScript {
|
||||||
|
|
||||||
void initScript(JSScript* script);
|
void initScript(JSScript* script);
|
||||||
|
|
||||||
JSScript* maybeScript() { return script_; }
|
JSScript* maybeScript() { return u.script_; }
|
||||||
const JSScript* maybeScriptUnbarriered() const {
|
const JSScript* maybeScriptUnbarriered() const {
|
||||||
return script_.unbarrieredGet();
|
return u.script_.unbarrieredGet();
|
||||||
}
|
}
|
||||||
bool hasScript() const { return bool(script_); }
|
bool hasScript() const { return bool(u.script_); }
|
||||||
|
|
||||||
// Returns true if the enclosing script has ever been compiled.
|
// Returns true if the enclosing script has ever been compiled.
|
||||||
// Once the enclosing script is compiled, the scope chain is created.
|
// Once the enclosing script is compiled, the scope chain is created.
|
||||||
|
@ -3386,9 +3395,6 @@ class LazyScript : public BaseScript {
|
||||||
return warmUpData_.isEnclosingScope();
|
return warmUpData_.isEnclosingScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class GCMarker;
|
|
||||||
void traceChildren(JSTracer* trc);
|
|
||||||
|
|
||||||
static const JS::TraceKind TraceKind = JS::TraceKind::LazyScript;
|
static const JS::TraceKind TraceKind = JS::TraceKind::LazyScript;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче