Backed out changeset ce39fc80bb5b (bug 1591209) due to perf/memory regressions at tcampbell request.

This commit is contained in:
Oana Pop Rus 2019-10-29 01:15:12 +02:00
parent b3407dccf1
commit 9523825524
12 changed files with 109 additions and 75 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -32,18 +32,22 @@ inline bool CanReuseFunctionForClone(JSContext* cx, HandleFunction fun) {
if (!fun->isSingleton()) {
return false;
}
if (fun->baseScript()->hasBeenCloned()) {
return false;
}
fun->baseScript()->setHasBeenCloned();
if (fun->hasScript()) {
if (LazyScript* lazy = fun->nonLazyScript()->maybeLazyScript()) {
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()) {
lazy->setHasBeenCloned();
}
}
return true;
}

View File

@ -1216,19 +1216,22 @@ const JSClass* const js::FunctionClassPtr = &JSFunction::class_;
bool JSFunction::isDerivedClassConstructor() {
bool derived;
if (hasSelfHostedLazyScript()) {
if (isInterpretedLazy()) {
// There is only one plausible lazy self-hosted derived
// constructor.
JSAtom* name = GetClonedSelfHostedFunctionName(this);
if (isSelfHostedBuiltin()) {
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;
}
if (hasBaseScript()) {
derived = baseScript()->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;
} else {
derived = lazyScript()->isDerivedClassConstructor();
}
} else {
derived = nonLazyScript()->isDerivedClassConstructor();
}
MOZ_ASSERT_IF(derived, isClassConstructor());
return derived;
@ -2161,7 +2164,8 @@ 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->baseScript()->hasNonSyntacticScope();
return fun->hasScript() ? fun->nonLazyScript()->hasNonSyntacticScope()
: fun->lazyScript()->hasNonSyntacticScope();
}
static inline JSFunction* NewFunctionClone(JSContext* cx, HandleFunction fun,

View File

@ -470,7 +470,6 @@ 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(); }
@ -515,7 +514,11 @@ class JSFunction : public js::NativeObject {
bool needsPrototypeProperty();
/* Returns the strictness of this function, which must be interpreted. */
bool strict() const { return baseScript()->strict(); }
bool strict() const {
MOZ_ASSERT(isInterpreted());
return isInterpretedLazy() ? lazyScript()->strict()
: nonLazyScript()->strict();
}
void setFlags(uint16_t flags) { flags_ = FunctionFlags(flags); }
void setFlags(FunctionFlags flags) { flags_ = flags; }
@ -764,20 +767,17 @@ class JSFunction : public js::NativeObject {
return u.scripted.s.selfHostedLazy_;
}
// 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();
}
MOZ_ASSERT(hasLazyScript());
return lazyScript();
}
js::GeneratorKind generatorKind() const {
if (hasBaseScript()) {
return baseScript()->generatorKind();
if (!isInterpreted()) {
return js::GeneratorKind::NotGenerator;
}
if (hasScript()) {
return nonLazyScript()->generatorKind();
}
if (hasLazyScript()) {
return lazyScript()->generatorKind();
}
MOZ_ASSERT(isSelfHostedBuiltin());
return js::GeneratorKind::NotGenerator;
}
@ -786,9 +786,16 @@ class JSFunction : public js::NativeObject {
}
js::FunctionAsyncKind asyncKind() const {
if (hasBaseScript()) {
return baseScript()->asyncKind();
if (!isInterpreted()) {
return js::FunctionAsyncKind::SyncFunction;
}
if (hasScript()) {
return nonLazyScript()->asyncKind();
}
if (hasLazyScript()) {
return lazyScript()->asyncKind();
}
MOZ_ASSERT(isSelfHostedBuiltin());
return js::FunctionAsyncKind::SyncFunction;
}

View File

@ -1656,12 +1656,6 @@ 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_; }
@ -3418,6 +3412,12 @@ 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,

View File

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

View File

@ -354,12 +354,21 @@ AutoXDRTree::Key XDRIncrementalEncoder::getTopLevelTreeKey() const {
}
AutoXDRTree::Key XDRIncrementalEncoder::getTreeKey(JSFunction* fun) const {
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();
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();
}
return AutoXDRTree::noKey;