Bug 1530412 - Use JSScript::ImmutableFlags in LazyScript r=jandem

Using the same flags as JSScript gives a consistent story of how to
handle flag preservation (in XDR and other cases). This also provides
consistent naming of flags which cover the same concept and will make it
simpler to inherit flags in de-lazification.

The LazyScript::packedFieldsForXDR concept exactly matches immutable
flags behaviour (which is on purpose). As a result of the split we don't
need to manually reset runtime flags in LazyScript::CreateRaw.

Differential Revision: https://phabricator.services.mozilla.com/D23402

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ted Campbell 2019-03-19 15:19:46 +00:00
parent da7ce5d164
commit f318e1c232
2 changed files with 105 additions and 124 deletions

View File

@ -271,7 +271,7 @@ static XDRResult XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun,
JSContext* cx = xdr->cx();
uint64_t packedFields;
uint32_t immutableFlags;
uint32_t numClosedOverBindings;
{
uint32_t sourceStart = script->sourceStart();
@ -283,7 +283,7 @@ static XDRResult XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun,
uint32_t numFieldInitializers;
if (mode == XDR_ENCODE) {
packedFields = lazy->packedFieldsForXDR();
immutableFlags = lazy->immutableFlags();
numClosedOverBindings = lazy->numClosedOverBindings();
MOZ_ASSERT(sourceStart == lazy->sourceStart());
MOZ_ASSERT(sourceEnd == lazy->sourceEnd());
@ -303,7 +303,7 @@ static XDRResult XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun,
}
}
MOZ_TRY(xdr->codeUint64(&packedFields));
MOZ_TRY(xdr->codeUint32(&immutableFlags));
MOZ_TRY(xdr->codeUint32(&numFieldInitializers));
MOZ_TRY(xdr->codeUint32(&numClosedOverBindings));
@ -311,7 +311,7 @@ static XDRResult XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun,
RootedScriptSourceObject sourceObject(cx, script->sourceObject());
lazy.set(LazyScript::CreateForXDR(
cx, numClosedOverBindings, /* numInnerFunctions = */ 0, fun, script,
enclosingScope, sourceObject, packedFields, sourceStart, sourceEnd,
enclosingScope, sourceObject, immutableFlags, sourceStart, sourceEnd,
toStringStart, toStringEnd, lineno, column));
if (!lazy) {
return xdr->fail(JS::TranscodeResult_Throw);
@ -1054,7 +1054,7 @@ XDRResult js::XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope,
uint32_t toStringEnd;
uint32_t lineno;
uint32_t column;
uint64_t packedFields;
uint32_t immutableFlags;
uint32_t numFieldInitializers;
uint32_t numClosedOverBindings;
uint32_t numInnerFunctions;
@ -1072,7 +1072,7 @@ XDRResult js::XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope,
toStringEnd = lazy->toStringEnd();
lineno = lazy->lineno();
column = lazy->column();
packedFields = lazy->packedFieldsForXDR();
immutableFlags = lazy->immutableFlags();
if (fun->kind() == JSFunction::FunctionKind::ClassConstructor) {
numFieldInitializers =
(uint32_t)lazy->getFieldInitializers().numFieldInitializers;
@ -1089,7 +1089,7 @@ XDRResult js::XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope,
MOZ_TRY(xdr->codeUint32(&toStringEnd));
MOZ_TRY(xdr->codeUint32(&lineno));
MOZ_TRY(xdr->codeUint32(&column));
MOZ_TRY(xdr->codeUint64(&packedFields));
MOZ_TRY(xdr->codeUint32(&immutableFlags));
MOZ_TRY(xdr->codeUint32(&numFieldInitializers));
MOZ_TRY(xdr->codeUint32(&numClosedOverBindings));
MOZ_TRY(xdr->codeUint32(&numInnerFunctions));
@ -1097,7 +1097,7 @@ XDRResult js::XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope,
if (mode == XDR_DECODE) {
lazy.set(LazyScript::CreateForXDR(
cx, numClosedOverBindings, numInnerFunctions, fun, nullptr,
enclosingScope, sourceObject, packedFields, sourceStart, sourceEnd,
enclosingScope, sourceObject, immutableFlags, sourceStart, sourceEnd,
toStringStart, toStringEnd, lineno, column));
if (!lazy) {
return xdr->fail(JS::TranscodeResult_Throw);
@ -4821,7 +4821,7 @@ bool JSScript::formalLivesInArgumentsObject(unsigned argSlot) {
LazyScript::LazyScript(uint32_t numClosedOverBindings,
uint32_t numInnerFunctions, JSFunction* fun,
ScriptSourceObject& sourceObject, void* table,
uint64_t packedFields, uint32_t sourceStart,
uint32_t immutableFlags, uint32_t sourceStart,
uint32_t sourceEnd, uint32_t toStringStart,
uint32_t lineno, uint32_t column)
: script_(nullptr),
@ -4830,7 +4830,8 @@ LazyScript::LazyScript(uint32_t numClosedOverBindings,
table_(table),
numClosedOverBindings_(numClosedOverBindings),
numInnerFunctions_(numInnerFunctions),
packedFields_(packedFields),
immutableFlags_(immutableFlags),
mutableFlags_(0),
fieldInitializers_(FieldInitializers::Invalid()),
sourceStart_(sourceStart),
sourceEnd_(sourceEnd),
@ -4887,40 +4888,17 @@ ScriptSource* LazyScript::maybeForwardedScriptSource() const {
.source();
}
uint64_t LazyScript::packedFieldsForXDR() const {
union {
PackedView p;
uint64_t packedFields;
};
packedFields = packedFields_;
// Reset runtime flags
p.hasBeenCloned = false;
return packedFields;
}
/* static */
LazyScript* LazyScript::CreateRaw(JSContext* cx, uint32_t numClosedOverBindings,
uint32_t numInnerFunctions,
HandleFunction fun,
HandleScriptSourceObject sourceObject,
uint64_t packedFields, uint32_t sourceStart,
uint32_t immutableFlags, uint32_t sourceStart,
uint32_t sourceEnd, uint32_t toStringStart,
uint32_t lineno, uint32_t column) {
cx->check(fun);
MOZ_ASSERT(sourceObject);
union {
PackedView p;
uint64_t packed;
};
packed = packedFields;
// Reset runtime flags to obtain a fresh LazyScript.
p.hasBeenCloned = false;
size_t bytes = (numClosedOverBindings * sizeof(JSAtom*)) +
(numInnerFunctions * sizeof(GCPtrFunction));
@ -4942,8 +4920,8 @@ LazyScript* LazyScript::CreateRaw(JSContext* cx, uint32_t numClosedOverBindings,
return new (res)
LazyScript(numClosedOverBindings, numInnerFunctions, fun, *sourceObject,
table.release(), packed, sourceStart, sourceEnd, toStringStart,
lineno, column);
table.release(), immutableFlags, sourceStart, sourceEnd,
toStringStart, lineno, column);
}
/* static */
@ -4954,31 +4932,15 @@ LazyScript* LazyScript::Create(JSContext* cx, HandleFunction fun,
uint32_t sourceStart, uint32_t sourceEnd,
uint32_t toStringStart, uint32_t lineno,
uint32_t column, frontend::ParseGoal parseGoal) {
union {
PackedView p;
uint64_t packedFields;
};
p.shouldDeclareArguments = false;
p.hasThisBinding = false;
p.isAsync = false;
p.hasRest = false;
p.isGenerator = false;
p.strict = false;
p.bindingsAccessedDynamically = false;
p.hasDebuggerStatement = false;
p.hasDirectEval = false;
p.isLikelyConstructorWrapper = false;
p.treatAsRunOnce = false;
p.isDerivedClassConstructor = false;
p.needsHomeObject = false;
p.isBinAST = false;
p.parseGoal = uint32_t(parseGoal);
uint32_t immutableFlags = 0;
if (parseGoal == frontend::ParseGoal::Module) {
immutableFlags |= uint32_t(ImmutableFlags::IsModule);
}
LazyScript* res = LazyScript::CreateRaw(
cx, closedOverBindings.length(), innerFunctions.length(), fun,
sourceObject, packedFields, sourceStart, sourceEnd, toStringStart, lineno,
column);
sourceObject, immutableFlags, sourceStart, sourceEnd, toStringStart,
lineno, column);
if (!res) {
return nullptr;
}
@ -5003,7 +4965,7 @@ LazyScript* LazyScript::Create(JSContext* cx, HandleFunction fun,
LazyScript* LazyScript::CreateForXDR(
JSContext* cx, uint32_t numClosedOverBindings, uint32_t numInnerFunctions,
HandleFunction fun, HandleScript script, HandleScope enclosingScope,
HandleScriptSourceObject sourceObject, uint64_t packedFields,
HandleScriptSourceObject sourceObject, uint32_t immutableFlags,
uint32_t sourceStart, uint32_t sourceEnd, uint32_t toStringStart,
uint32_t toStringEnd, uint32_t lineno, uint32_t column) {
// Dummy atom which is not a valid property name.
@ -5015,7 +4977,7 @@ LazyScript* LazyScript::CreateForXDR(
LazyScript* res = LazyScript::CreateRaw(
cx, numClosedOverBindings, numInnerFunctions, fun, sourceObject,
packedFields, sourceStart, sourceEnd, toStringStart, lineno, column);
immutableFlags, sourceStart, sourceEnd, toStringStart, lineno, column);
if (!res) {
return nullptr;
}

View File

@ -1769,6 +1769,12 @@ class JSScript : public js::gc::TenuredCell {
// Whether this function needs a call object or named lambda environment.
NeedsFunctionEnvironmentObjects = 1 << 24,
// LazyScript flags
ShouldDeclareArguments = 1 << 25,
IsBinAST = 1 << 26,
HasDebuggerStatement = 1 << 27,
HasDirectEval = 1 << 28,
};
private:
@ -2979,35 +2985,23 @@ class LazyScript : public gc::TenuredCell {
uint32_t numClosedOverBindings_;
uint32_t numInnerFunctions_;
struct PackedView {
uint32_t shouldDeclareArguments : 1;
uint32_t hasThisBinding : 1;
uint32_t isAsync : 1;
uint32_t isBinAST : 1;
// See: JSScript::ImmutableFlags / MutableFlags.
// NOTE: Lazy script only defines and uses a subset of these flags.
using ImmutableFlags = JSScript::ImmutableFlags;
using MutableFlags = JSScript::MutableFlags;
// N.B. These are booleans but need to be uint32_t to pack correctly on
// MSVC. If you add another boolean here, make sure to initialize it in
// LazyScript::Create().
uint32_t isGenerator : 1;
uint32_t strict : 1;
uint32_t bindingsAccessedDynamically : 1;
uint32_t hasDebuggerStatement : 1;
uint32_t hasDirectEval : 1;
uint32_t isLikelyConstructorWrapper : 1;
uint32_t treatAsRunOnce : 1;
uint32_t isDerivedClassConstructor : 1;
uint32_t needsHomeObject : 1;
uint32_t hasRest : 1;
uint32_t parseGoal : 1;
uint32_t immutableFlags_;
uint32_t mutableFlags_;
// Runtime flags
uint32_t hasBeenCloned : 1;
};
MOZ_MUST_USE bool hasFlag(MutableFlags flag) const {
return mutableFlags_ & uint32_t(flag);
}
void setFlag(MutableFlags flag) { mutableFlags_ |= uint32_t(flag); }
union {
PackedView p_;
uint64_t packedFields_;
};
MOZ_MUST_USE bool hasFlag(ImmutableFlags flag) const {
return immutableFlags_ & uint32_t(flag);
}
void setFlag(ImmutableFlags flag) { immutableFlags_ |= uint32_t(flag); }
FieldInitializers fieldInitializers_;
@ -3024,7 +3018,7 @@ class LazyScript : public gc::TenuredCell {
LazyScript(uint32_t numClosedOverBindings, uint32_t numInnerFunctions,
JSFunction* fun, ScriptSourceObject& sourceObject, void* table,
uint64_t packedFields, uint32_t sourceStart, uint32_t sourceEnd,
uint32_t immutableFlags, uint32_t sourceStart, uint32_t sourceEnd,
uint32_t toStringStart, uint32_t lineno, uint32_t column);
// Create a LazyScript without initializing the closedOverBindings and the
@ -3033,7 +3027,7 @@ class LazyScript : public gc::TenuredCell {
static LazyScript* CreateRaw(JSContext* cx, uint32_t numClosedOverBindings,
uint32_t numInnerFunctions, HandleFunction fun,
HandleScriptSourceObject sourceObject,
uint64_t packedData, uint32_t sourceStart,
uint32_t immutableFlags, uint32_t sourceStart,
uint32_t sourceEnd, uint32_t toStringStart,
uint32_t lineno, uint32_t column);
@ -3064,7 +3058,7 @@ class LazyScript : public gc::TenuredCell {
static LazyScript* CreateForXDR(
JSContext* cx, uint32_t numClosedOverBindings, uint32_t numInnerFunctions,
HandleFunction fun, HandleScript script, HandleScope enclosingScope,
HandleScriptSourceObject sourceObject, uint64_t packedData,
HandleScriptSourceObject sourceObject, uint32_t immutableFlags,
uint32_t sourceStart, uint32_t sourceEnd, uint32_t toStringStart,
uint32_t toStringEnd, uint32_t lineno, uint32_t column);
@ -3129,8 +3123,8 @@ class LazyScript : public gc::TenuredCell {
}
GeneratorKind generatorKind() const {
return p_.isGenerator ? GeneratorKind::Generator
: GeneratorKind::NotGenerator;
return hasFlag(ImmutableFlags::IsGenerator) ? GeneratorKind::Generator
: GeneratorKind::NotGenerator;
}
bool isGenerator() const {
@ -3141,69 +3135,94 @@ class LazyScript : public gc::TenuredCell {
// A script only gets its generator kind set as part of initialization,
// so it can only transition from NotGenerator.
MOZ_ASSERT(!isGenerator());
p_.isGenerator = kind == GeneratorKind::Generator;
if (kind == GeneratorKind::Generator) {
setFlag(ImmutableFlags::IsGenerator);
}
}
bool isAsync() const { return hasFlag(ImmutableFlags::IsAsync); }
FunctionAsyncKind asyncKind() const {
return p_.isAsync ? FunctionAsyncKind::AsyncFunction
: FunctionAsyncKind::SyncFunction;
return isAsync() ? FunctionAsyncKind::AsyncFunction
: FunctionAsyncKind::SyncFunction;
}
bool isAsync() const { return p_.isAsync; }
void setAsyncKind(FunctionAsyncKind kind) {
p_.isAsync = kind == FunctionAsyncKind::AsyncFunction;
if (kind == FunctionAsyncKind::AsyncFunction) {
setFlag(ImmutableFlags::IsAsync);
}
}
bool hasRest() const { return p_.hasRest; }
void setHasRest() { p_.hasRest = true; }
bool hasRest() const { return hasFlag(ImmutableFlags::HasRest); }
void setHasRest() { setFlag(ImmutableFlags::HasRest); }
frontend::ParseGoal parseGoal() const {
return frontend::ParseGoal(p_.parseGoal);
if (hasFlag(ImmutableFlags::IsModule)) {
return frontend::ParseGoal::Module;
}
return frontend::ParseGoal::Script;
}
bool isBinAST() const { return p_.isBinAST; }
void setIsBinAST() { p_.isBinAST = true; }
bool isBinAST() const { return hasFlag(ImmutableFlags::IsBinAST); }
void setIsBinAST() { setFlag(ImmutableFlags::IsBinAST); }
bool strict() const { return p_.strict; }
void setStrict() { p_.strict = true; }
bool strict() const { return hasFlag(ImmutableFlags::Strict); }
void setStrict() { setFlag(ImmutableFlags::Strict); }
bool bindingsAccessedDynamically() const {
return p_.bindingsAccessedDynamically;
return hasFlag(ImmutableFlags::BindingsAccessedDynamically);
}
void setBindingsAccessedDynamically() {
p_.bindingsAccessedDynamically = true;
setFlag(ImmutableFlags::BindingsAccessedDynamically);
}
bool hasDebuggerStatement() const { return p_.hasDebuggerStatement; }
void setHasDebuggerStatement() { p_.hasDebuggerStatement = true; }
bool hasDebuggerStatement() const {
return hasFlag(ImmutableFlags::HasDebuggerStatement);
}
void setHasDebuggerStatement() {
setFlag(ImmutableFlags::HasDebuggerStatement);
}
bool hasDirectEval() const { return p_.hasDirectEval; }
void setHasDirectEval() { p_.hasDirectEval = true; }
bool hasDirectEval() const { return hasFlag(ImmutableFlags::HasDirectEval); }
void setHasDirectEval() { setFlag(ImmutableFlags::HasDirectEval); }
bool isLikelyConstructorWrapper() const {
return p_.isLikelyConstructorWrapper;
return hasFlag(ImmutableFlags::IsLikelyConstructorWrapper);
}
void setLikelyConstructorWrapper() {
setFlag(ImmutableFlags::IsLikelyConstructorWrapper);
}
void setLikelyConstructorWrapper() { p_.isLikelyConstructorWrapper = true; }
bool hasBeenCloned() const { return p_.hasBeenCloned; }
void setHasBeenCloned() { p_.hasBeenCloned = true; }
bool hasBeenCloned() const { return hasFlag(MutableFlags::HasBeenCloned); }
void setHasBeenCloned() { setFlag(MutableFlags::HasBeenCloned); }
bool treatAsRunOnce() const { return p_.treatAsRunOnce; }
void setTreatAsRunOnce() { p_.treatAsRunOnce = true; }
bool treatAsRunOnce() const {
return hasFlag(ImmutableFlags::TreatAsRunOnce);
}
void setTreatAsRunOnce() { setFlag(ImmutableFlags::TreatAsRunOnce); }
bool isDerivedClassConstructor() const {
return p_.isDerivedClassConstructor;
return hasFlag(ImmutableFlags::IsDerivedClassConstructor);
}
void setIsDerivedClassConstructor() {
setFlag(ImmutableFlags::IsDerivedClassConstructor);
}
void setIsDerivedClassConstructor() { p_.isDerivedClassConstructor = true; }
bool needsHomeObject() const { return p_.needsHomeObject; }
void setNeedsHomeObject() { p_.needsHomeObject = true; }
bool needsHomeObject() const {
return hasFlag(ImmutableFlags::NeedsHomeObject);
}
void setNeedsHomeObject() { setFlag(ImmutableFlags::NeedsHomeObject); }
bool shouldDeclareArguments() const { return p_.shouldDeclareArguments; }
void setShouldDeclareArguments() { p_.shouldDeclareArguments = true; }
bool shouldDeclareArguments() const {
return hasFlag(ImmutableFlags::ShouldDeclareArguments);
}
void setShouldDeclareArguments() {
setFlag(ImmutableFlags::ShouldDeclareArguments);
}
bool hasThisBinding() const { return p_.hasThisBinding; }
void setHasThisBinding() { p_.hasThisBinding = true; }
bool hasThisBinding() const {
return hasFlag(ImmutableFlags::FunctionHasThisBinding);
}
void setHasThisBinding() { setFlag(ImmutableFlags::FunctionHasThisBinding); }
void setFieldInitializers(FieldInitializers fieldInitializers) {
fieldInitializers_ = fieldInitializers;
@ -3246,7 +3265,7 @@ class LazyScript : public gc::TenuredCell {
return mallocSizeOf(table_);
}
uint64_t packedFieldsForXDR() const;
uint32_t immutableFlags() const { return immutableFlags_; }
};
/* If this fails, add/remove padding within LazyScript. */