Bug 1591209 - Add JSFunction::baseScript() accessor. r=jandem

Add a baseScript() accessor to use in cases where to accessor properties
through a JSFunction that are defined for both lazy and non-lazy
scripts.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ted Campbell 2019-10-25 13:08:09 +00:00
Родитель cc2ee58041
Коммит cfd6179906
12 изменённых файлов: 74 добавлений и 108 удалений

Просмотреть файл

@ -36,9 +36,7 @@ FunctionEmitter::FunctionEmitter(BytecodeEmitter* bce, FunctionBox* funbox,
fun_(bce_->cx, funbox_->function()),
name_(bce_->cx, fun_->explicitName()),
syntaxKind_(syntaxKind),
isHoisted_(isHoisted) {
MOZ_ASSERT_IF(fun_->isInterpretedLazy(), fun_->lazyScript());
}
isHoisted_(isHoisted) {}
bool FunctionEmitter::interpretedCommon() {
// Mark as singletons any function which will only be executed once, or
@ -116,7 +114,7 @@ bool FunctionEmitter::emitLazy() {
if (bce_->emittingRunOnceLambda) {
// NOTE: The 'funbox' is only partially initialized so we defer checking
// the shouldSuppressRunOnce condition until delazification.
fun_->lazyScript()->setTreatAsRunOnce();
fun_->baseScript()->setTreatAsRunOnce();
}
if (!emitFunction()) {

Просмотреть файл

@ -516,7 +516,7 @@ bool ParseContext::declareFunctionThis(const UsedNameTracker& usedNames,
bool declareThis;
if (canSkipLazyClosedOverBindings) {
declareThis = funbox->function()->lazyScript()->hasThisBinding();
declareThis = funbox->function()->baseScript()->hasThisBinding();
} else {
declareThis =
hasUsedFunctionSpecialName(usedNames, dotThis) ||
@ -551,7 +551,7 @@ bool ParseContext::declareFunctionArgumentsObject(
bool tryDeclareArguments;
if (canSkipLazyClosedOverBindings) {
tryDeclareArguments =
funbox->function()->lazyScript()->shouldDeclareArguments();
funbox->function()->baseScript()->shouldDeclareArguments();
} else {
tryDeclareArguments = hasUsedFunctionSpecialName(usedNames, argumentsName);
}

Просмотреть файл

@ -2623,14 +2623,14 @@ bool Parser<FullParseHandler, Unit>::skipLazyInnerFunction(
return false;
}
LazyScript* lazy = fun->lazyScript();
if (lazy->needsHomeObject()) {
BaseScript* base = fun->baseScript();
if (base->needsHomeObject()) {
funbox->setNeedsHomeObject();
}
PropagateTransitiveParseFlags(lazy, pc_->sc());
PropagateTransitiveParseFlags(base, pc_->sc());
if (!tokenStream.advance(fun->lazyScript()->sourceEnd())) {
if (!tokenStream.advance(base->sourceEnd())) {
return false;
}
@ -7212,11 +7212,15 @@ bool GeneralParser<ParseHandler, Unit>::finishClassConstructor(
// Set the same information, but on the lazyScript.
if (ctorbox->isInterpretedLazy()) {
ctorbox->function()->lazyScript()->setToStringEnd(classEndOffset);
ctorbox->function()->baseScript()->setToStringEnd(classEndOffset);
if (numFields > 0) {
ctorbox->function()->lazyScript()->setHasThisBinding();
ctorbox->function()->baseScript()->setHasThisBinding();
}
} else {
// There should not be any non-lazy script yet.
MOZ_ASSERT_IF(ctorbox->hasObject(),
ctorbox->function()->hasUncompletedScript());
}
if (numFields == 0) {

Просмотреть файл

@ -203,14 +203,15 @@ FunctionBox::FunctionBox(JSContext* cx, TraceListNode* traceListHead,
}
void FunctionBox::initFromLazyFunction(JSFunction* fun) {
if (fun->lazyScript()->isDerivedClassConstructor()) {
LazyScript* lazy = fun->lazyScript();
if (lazy->isDerivedClassConstructor()) {
setDerivedClassConstructor();
}
if (fun->lazyScript()->needsHomeObject()) {
if (lazy->needsHomeObject()) {
setNeedsHomeObject();
}
if (fun->lazyScript()->hasEnclosingScope()) {
enclosingScope_ = fun->lazyScript()->enclosingScope();
if (lazy->hasEnclosingScope()) {
enclosingScope_ = lazy->enclosingScope();
} else {
enclosingScope_ = nullptr;
}

Просмотреть файл

@ -6744,8 +6744,7 @@ struct LambdaFunctionInfo {
: fun_(fun),
flags(fun->flags().toRaw()),
nargs(fun->nargs()),
scriptOrLazyScript(fun->hasScript() ? (gc::Cell*)fun->nonLazyScript()
: (gc::Cell*)fun->lazyScript()),
scriptOrLazyScript(fun->baseScript()),
singletonType(fun->isSingleton()),
useSingletonForClone(ObjectGroup::useSingletonForClone(fun)) {
// If this assert fails, make sure CodeGenerator::visitLambda does the

Просмотреть файл

@ -793,12 +793,9 @@ static JSFunction* MaybeConstructorFromType(TypeSet::Type ty) {
static void InterpretedFunctionFilenameAndLineNumber(JSFunction* fun,
const char** filename,
Maybe<unsigned>* lineno) {
if (fun->hasScript()) {
*filename = fun->nonLazyScript()->maybeForwardedScriptSource()->filename();
*lineno = Some((unsigned)fun->nonLazyScript()->lineno());
} else if (fun->hasLazyScript()) {
*filename = fun->lazyScript()->maybeForwardedScriptSource()->filename();
*lineno = Some((unsigned)fun->lazyScript()->lineno());
if (fun->hasBaseScript()) {
*filename = fun->baseScript()->maybeForwardedScriptSource()->filename();
*lineno = Some((unsigned)fun->baseScript()->lineno());
} else {
*filename = "(self-hosted builtin)";
*lineno = Nothing();

Просмотреть файл

@ -32,22 +32,18 @@ inline bool CanReuseFunctionForClone(JSContext* cx, HandleFunction fun) {
if (!fun->isSingleton()) {
return false;
}
if (fun->isInterpretedLazy()) {
LazyScript* lazy = fun->lazyScript();
if (lazy->hasBeenCloned()) {
return false;
}
lazy->setHasBeenCloned();
} else {
JSScript* script = fun->nonLazyScript();
if (script->hasBeenCloned()) {
return false;
}
script->setHasBeenCloned();
if (LazyScript* lazy = script->maybeLazyScript()) {
if (fun->baseScript()->hasBeenCloned()) {
return false;
}
fun->baseScript()->setHasBeenCloned();
if (fun->hasScript()) {
if (LazyScript* lazy = fun->nonLazyScript()->maybeLazyScript()) {
lazy->setHasBeenCloned();
}
}
return true;
}

Просмотреть файл

@ -1216,22 +1216,19 @@ const JSClass* const js::FunctionClassPtr = &JSFunction::class_;
bool JSFunction::isDerivedClassConstructor() {
bool derived;
if (isInterpretedLazy()) {
if (hasSelfHostedLazyScript()) {
// There is only one plausible lazy self-hosted derived
// constructor.
if (isSelfHostedBuiltin()) {
JSAtom* name = GetClonedSelfHostedFunctionName(this);
JSAtom* name = GetClonedSelfHostedFunctionName(this);
// This function is called from places without access to a
// JSContext. Trace some plumbing to get what we want.
derived = name == compartment()
->runtimeFromAnyThread()
->commonNames->DefaultDerivedClassConstructor;
} else {
derived = lazyScript()->isDerivedClassConstructor();
}
} else {
derived = nonLazyScript()->isDerivedClassConstructor();
// This function is called from places without access to a
// JSContext. Trace some plumbing to get what we want.
derived = name == compartment()
->runtimeFromAnyThread()
->commonNames->DefaultDerivedClassConstructor;
}
if (hasBaseScript()) {
derived = baseScript()->isDerivedClassConstructor();
}
MOZ_ASSERT_IF(derived, isClassConstructor());
return derived;
@ -2164,8 +2161,7 @@ bool js::CanReuseScriptForClone(JS::Realm* realm, HandleFunction fun,
// We need to clone the script if we're not already marked as having a
// non-syntactic scope.
return fun->hasScript() ? fun->nonLazyScript()->hasNonSyntacticScope()
: fun->lazyScript()->hasNonSyntacticScope();
return fun->baseScript()->hasNonSyntacticScope();
}
static inline JSFunction* NewFunctionClone(JSContext* cx, HandleFunction fun,

Просмотреть файл

@ -470,6 +470,7 @@ class JSFunction : public js::NativeObject {
bool hasSelfHostedLazyScript() const {
return flags_.hasSelfHostedLazyScript();
}
bool hasBaseScript() const { return hasScript() || hasLazyScript(); }
// Arrow functions store their lexical new.target in the first extended slot.
bool isArrow() const { return flags_.isArrow(); }
@ -514,11 +515,7 @@ class JSFunction : public js::NativeObject {
bool needsPrototypeProperty();
/* Returns the strictness of this function, which must be interpreted. */
bool strict() const {
MOZ_ASSERT(isInterpreted());
return isInterpretedLazy() ? lazyScript()->strict()
: nonLazyScript()->strict();
}
bool strict() const { return baseScript()->strict(); }
void setFlags(uint16_t flags) { flags_ = FunctionFlags(flags); }
void setFlags(FunctionFlags flags) { flags_ = flags; }
@ -767,17 +764,20 @@ class JSFunction : public js::NativeObject {
return u.scripted.s.selfHostedLazy_;
}
js::GeneratorKind generatorKind() const {
if (!isInterpreted()) {
return js::GeneratorKind::NotGenerator;
}
// Access fields defined on both lazy and non-lazy scripts. This should
// optimize away the branch since the union arms are compatible.
js::BaseScript* baseScript() const {
if (hasScript()) {
return nonLazyScript()->generatorKind();
return nonLazyScript();
}
if (hasLazyScript()) {
return lazyScript()->generatorKind();
MOZ_ASSERT(hasLazyScript());
return lazyScript();
}
js::GeneratorKind generatorKind() const {
if (hasBaseScript()) {
return baseScript()->generatorKind();
}
MOZ_ASSERT(isSelfHostedBuiltin());
return js::GeneratorKind::NotGenerator;
}
@ -786,16 +786,9 @@ class JSFunction : public js::NativeObject {
}
js::FunctionAsyncKind asyncKind() const {
if (!isInterpreted()) {
return js::FunctionAsyncKind::SyncFunction;
if (hasBaseScript()) {
return baseScript()->asyncKind();
}
if (hasScript()) {
return nonLazyScript()->asyncKind();
}
if (hasLazyScript()) {
return lazyScript()->asyncKind();
}
MOZ_ASSERT(isSelfHostedBuiltin());
return js::FunctionAsyncKind::SyncFunction;
}

Просмотреть файл

@ -1656,6 +1656,12 @@ class BaseScript : public gc::TenuredCell {
uint32_t toStringStart() const { return toStringStart_; }
uint32_t toStringEnd() const { return toStringEnd_; }
void setToStringEnd(uint32_t toStringEnd) {
MOZ_ASSERT(toStringStart_ <= toStringEnd);
MOZ_ASSERT(toStringEnd_ >= sourceEnd_);
toStringEnd_ = toStringEnd;
}
uint32_t lineno() const { return lineno_; }
uint32_t column() const { return column_; }
@ -3412,12 +3418,6 @@ class LazyScript : public BaseScript {
return lazyData_->fieldInitializers_;
}
void setToStringEnd(uint32_t toStringEnd) {
MOZ_ASSERT(toStringStart_ <= toStringEnd);
MOZ_ASSERT(toStringEnd_ >= sourceEnd_);
toStringEnd_ = toStringEnd;
}
// Returns true if the enclosing script has ever been compiled.
// Once the enclosing script is compiled, the scope chain is created.
// This LazyScript is delazify-able as long as it has the enclosing scope,

Просмотреть файл

@ -173,20 +173,11 @@ bool ObjectGroup::useSingletonForClone(JSFunction* fun) {
* instance a singleton type and clone the underlying script.
*/
uint32_t begin, end;
if (fun->hasScript()) {
if (!fun->nonLazyScript()->isLikelyConstructorWrapper()) {
return false;
}
begin = fun->nonLazyScript()->sourceStart();
end = fun->nonLazyScript()->sourceEnd();
} else {
if (!fun->lazyScript()->isLikelyConstructorWrapper()) {
return false;
}
begin = fun->lazyScript()->sourceStart();
end = fun->lazyScript()->sourceEnd();
if (!fun->baseScript()->isLikelyConstructorWrapper()) {
return false;
}
uint32_t begin = fun->baseScript()->sourceStart();
uint32_t end = fun->baseScript()->sourceEnd();
return end - begin <= 100;
}

Просмотреть файл

@ -354,21 +354,12 @@ AutoXDRTree::Key XDRIncrementalEncoder::getTopLevelTreeKey() const {
}
AutoXDRTree::Key XDRIncrementalEncoder::getTreeKey(JSFunction* fun) const {
if (fun->isInterpretedLazy()) {
static_assert(
sizeof(fun->lazyScript()->sourceStart()) == 4 ||
sizeof(fun->lazyScript()->sourceEnd()) == 4,
"AutoXDRTree key requires LazyScripts positions to be uint32");
return uint64_t(fun->lazyScript()->sourceStart()) << 32 |
fun->lazyScript()->sourceEnd();
}
if (fun->isInterpreted()) {
static_assert(sizeof(fun->nonLazyScript()->sourceStart()) == 4 ||
sizeof(fun->nonLazyScript()->sourceEnd()) == 4,
"AutoXDRTree key requires JSScripts positions to be uint32");
return uint64_t(fun->nonLazyScript()->sourceStart()) << 32 |
fun->nonLazyScript()->sourceEnd();
if (fun->hasBaseScript()) {
static_assert(sizeof(fun->baseScript()->sourceStart()) == 4 &&
sizeof(fun->baseScript()->sourceEnd()) == 4,
"AutoXDRTree key requires BaseScript positions to be uint32");
return uint64_t(fun->baseScript()->sourceStart()) << 32 |
fun->baseScript()->sourceEnd();
}
return AutoXDRTree::noKey;