author | Matthew Gaudet <mgaudet@mozilla.com> |
Fri, 06 Dec 2019 16:25:27 +0000 | |
changeset 505832 | 351c88e680a33ea769a863b67800afedc75319fb |
parent 505831 | 325e83234dd53f2abdb182acc382857978c57666 |
child 505833 | 0f59860a21ef5cd460d9850bcb7719de85c5eca3 |
push id | 36889 |
push user | dluca@mozilla.com |
push date | Fri, 06 Dec 2019 21:48:33 +0000 |
treeherder | mozilla-central@0d24f14c0847 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | tcampbell |
bugs | 1592102 |
milestone | 73.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
js/src/vm/Scope.cpp | file | annotate | diff | comparison | revisions | |
js/src/vm/Scope.h | file | annotate | diff | comparison | revisions |
--- a/js/src/vm/Scope.cpp +++ b/js/src/vm/Scope.cpp @@ -558,33 +558,45 @@ LexicalScope* LexicalScope::create(JSCon Rooted<UniquePtr<Data>> copy(cx, CopyScopeData<LexicalScope>(cx, data)); if (!copy) { return nullptr; } return createWithData(cx, kind, ©, firstFrameSlot, enclosing); } -/* static */ -LexicalScope* LexicalScope::createWithData(JSContext* cx, ScopeKind kind, +bool LexicalScope::prepareForScopeCreation(JSContext* cx, ScopeKind kind, + uint32_t firstFrameSlot, + HandleScope enclosing, MutableHandle<UniquePtr<Data>> data, - uint32_t firstFrameSlot, - HandleScope enclosing) { + MutableHandleShape envShape) { bool isNamedLambda = kind == ScopeKind::NamedLambda || kind == ScopeKind::StrictNamedLambda; MOZ_ASSERT_IF(!isNamedLambda && firstFrameSlot != 0, firstFrameSlot == nextFrameSlot(enclosing)); MOZ_ASSERT_IF(isNamedLambda, firstFrameSlot == LOCALNO_LIMIT); - RootedShape envShape(cx); BindingIter bi(*data, firstFrameSlot, isNamedLambda); if (!PrepareScopeData<LexicalScope>( cx, bi, data, &LexicalEnvironmentObject::class_, - BaseShape::NOT_EXTENSIBLE | BaseShape::DELEGATE, &envShape)) { + BaseShape::NOT_EXTENSIBLE | BaseShape::DELEGATE, envShape)) { + return false; + } + return true; +} + +/* static */ +LexicalScope* LexicalScope::createWithData(JSContext* cx, ScopeKind kind, + MutableHandle<UniquePtr<Data>> data, + uint32_t firstFrameSlot, + HandleScope enclosing) { + RootedShape envShape(cx); + if (!prepareForScopeCreation(cx, kind, firstFrameSlot, enclosing, data, + &envShape)) { return nullptr; } auto scope = Scope::create<LexicalScope>(cx, kind, enclosing, envShape, data); if (!scope) { return nullptr; } @@ -675,53 +687,64 @@ FunctionScope* FunctionScope::create(JSC } return createWithData( cx, &data, hasParameterExprs, dataArg ? dataArg->isFieldInitializer : IsFieldInitializer::No, needsEnvironment, fun, enclosing); } -/* static */ -FunctionScope* FunctionScope::createWithData( +bool FunctionScope::prepareForScopeCreation( JSContext* cx, MutableHandle<UniquePtr<Data>> data, bool hasParameterExprs, IsFieldInitializer isFieldInitializer, bool needsEnvironment, - HandleFunction fun, HandleScope enclosing) { - MOZ_ASSERT(data); - MOZ_ASSERT(fun->isTenured()); - - // FunctionScope::Data has GCManagedDeletePolicy because it contains a - // GCPtr. Destruction of |data| below may trigger calls into the GC. - - RootedShape envShape(cx); - + HandleFunction fun, MutableHandleShape envShape) { BindingIter bi(*data, hasParameterExprs); uint32_t shapeFlags = FunctionScopeEnvShapeFlags(hasParameterExprs); if (!PrepareScopeData<FunctionScope>(cx, bi, data, &CallObject::class_, - shapeFlags, &envShape)) { - return nullptr; + shapeFlags, envShape)) { + return false; } data->isFieldInitializer = isFieldInitializer; data->hasParameterExprs = hasParameterExprs; data->canonicalFunction.init(fun); // An environment may be needed regardless of existence of any closed over // bindings: // - Extensible scopes (i.e., due to direct eval) // - Needing a home object // - Being a derived class constructor // - Being a generator if (!envShape && needsEnvironment) { - envShape = getEmptyEnvironmentShape(cx, hasParameterExprs); + envShape.set(getEmptyEnvironmentShape(cx, hasParameterExprs)); if (!envShape) { - return nullptr; + return false; } } + return true; +} + +/* static */ +FunctionScope* FunctionScope::createWithData( + JSContext* cx, MutableHandle<UniquePtr<Data>> data, bool hasParameterExprs, + IsFieldInitializer isFieldInitializer, bool needsEnvironment, + HandleFunction fun, HandleScope enclosing) { + MOZ_ASSERT(data); + MOZ_ASSERT(fun->isTenured()); + + // FunctionScope::Data has GCManagedDeletePolicy because it contains a + // GCPtr. Destruction of |data| below may trigger calls into the GC. + RootedShape envShape(cx); + + if (!prepareForScopeCreation(cx, data, hasParameterExprs, isFieldInitializer, + needsEnvironment, fun, &envShape)) { + return nullptr; + } + return Scope::create<FunctionScope>(cx, ScopeKind::Function, enclosing, envShape, data); } JSScript* FunctionScope::script() const { return canonicalFunction()->nonLazyScript(); } @@ -862,42 +885,54 @@ VarScope* VarScope::create(JSContext* cx if (!data) { return nullptr; } return createWithData(cx, kind, &data, firstFrameSlot, needsEnvironment, enclosing); } +bool VarScope::prepareForScopeCreation(JSContext* cx, ScopeKind kind, + MutableHandle<UniquePtr<Data>> data, + uint32_t firstFrameSlot, + bool needsEnvironment, + MutableHandleShape envShape) { + BindingIter bi(*data, firstFrameSlot); + if (!PrepareScopeData<VarScope>(cx, bi, data, &VarEnvironmentObject::class_, + VarScopeEnvShapeFlags, envShape)) { + return false; + } + + // An environment may be needed regardless of existence of any closed over + // bindings: + // - Extensible scopes (i.e., due to direct eval) + // - Being a generator + if (!envShape && needsEnvironment) { + envShape.set(getEmptyEnvironmentShape(cx)); + if (!envShape) { + return false; + } + } + return true; +} + /* static */ VarScope* VarScope::createWithData(JSContext* cx, ScopeKind kind, MutableHandle<UniquePtr<Data>> data, uint32_t firstFrameSlot, bool needsEnvironment, HandleScope enclosing) { MOZ_ASSERT(data); RootedShape envShape(cx); - BindingIter bi(*data, firstFrameSlot); - if (!PrepareScopeData<VarScope>(cx, bi, data, &VarEnvironmentObject::class_, - VarScopeEnvShapeFlags, &envShape)) { + if (!prepareForScopeCreation(cx, kind, data, firstFrameSlot, needsEnvironment, + &envShape)) { return nullptr; } - // An environment may be needed regardless of existence of any closed over - // bindings: - // - Extensible scopes (i.e., due to direct eval) - // - Being a generator - if (!envShape && needsEnvironment) { - envShape = getEmptyEnvironmentShape(cx); - if (!envShape) { - return nullptr; - } - } - return Scope::create<VarScope>(cx, kind, enclosing, envShape, data); } /* static */ Shape* VarScope::getEmptyEnvironmentShape(JSContext* cx) { const JSClass* cls = &VarEnvironmentObject::class_; return EmptyEnvironmentShape(cx, cls, JSSLOT_FREE(cls), VarScopeEnvShapeFlags); @@ -1102,39 +1137,48 @@ EvalScope* EvalScope::create(JSContext* : NewEmptyScopeData<EvalScope>(cx)); if (!data) { return nullptr; } return createWithData(cx, scopeKind, &data, enclosing); } +bool EvalScope::prepareForScopeCreation(JSContext* cx, ScopeKind scopeKind, + MutableHandle<UniquePtr<Data>> data, + MutableHandleShape envShape) { + if (scopeKind == ScopeKind::StrictEval) { + BindingIter bi(*data, true); + if (!PrepareScopeData<EvalScope>(cx, bi, data, + &VarEnvironmentObject::class_, + EvalScopeEnvShapeFlags, envShape)) { + return false; + } + } + + // Strict eval and direct eval in parameter expressions always get their own + // var environment even if there are no bindings. + if (!envShape && scopeKind == ScopeKind::StrictEval) { + envShape.set(getEmptyEnvironmentShape(cx)); + if (!envShape) { + return false; + } + } + return true; +} + /* static */ EvalScope* EvalScope::createWithData(JSContext* cx, ScopeKind scopeKind, MutableHandle<UniquePtr<Data>> data, HandleScope enclosing) { MOZ_ASSERT(data); RootedShape envShape(cx); - if (scopeKind == ScopeKind::StrictEval) { - BindingIter bi(*data, true); - if (!PrepareScopeData<EvalScope>(cx, bi, data, - &VarEnvironmentObject::class_, - EvalScopeEnvShapeFlags, &envShape)) { - return nullptr; - } - } - - // Strict eval and direct eval in parameter expressions always get their own - // var environment even if there are no bindings. - if (!envShape && scopeKind == ScopeKind::StrictEval) { - envShape = getEmptyEnvironmentShape(cx); - if (!envShape) { - return nullptr; - } + if (!prepareForScopeCreation(cx, scopeKind, data, &envShape)) { + return nullptr; } return Scope::create<EvalScope>(cx, scopeKind, enclosing, envShape, data); } /* static */ Scope* EvalScope::nearestVarScopeForDirectEval(Scope* scope) { for (ScopeIter si(scope); si; si++) { @@ -1208,57 +1252,68 @@ static const uint32_t ModuleScopeEnvShap Zone* ModuleScope::Data::zone() const { return module ? module->zone() : nullptr; } /* static */ ModuleScope* ModuleScope::create(JSContext* cx, Handle<Data*> dataArg, HandleModuleObject module, HandleScope enclosing) { + // ModuleScope::Data has GCManagedDeletePolicy because it contains a + // GCPtr. Destruction of |data| below may trigger calls into the GC. + + // The data that's passed in is from the frontend and is LifoAlloc'd. + // Copy it now that we're creating a permanent VM scope. Rooted<UniquePtr<Data>> data(cx, dataArg ? CopyScopeData<ModuleScope>(cx, dataArg) : NewEmptyScopeData<ModuleScope>(cx)); if (!data) { return nullptr; } return createWithData(cx, &data, module, enclosing); } /* static */ +bool ModuleScope::prepareForScopeCreation(JSContext* cx, + MutableHandle<UniquePtr<Data>> data, + HandleModuleObject module, + MutableHandleShape envShape) { + BindingIter bi(*data); + if (!PrepareScopeData<ModuleScope>(cx, bi, data, + &ModuleEnvironmentObject::class_, + ModuleScopeEnvShapeFlags, envShape)) { + return false; + } + + // Modules always need an environment object for now. + if (!envShape) { + envShape.set(getEmptyEnvironmentShape(cx)); + if (!envShape) { + return false; + } + } + + data->module.init(module); + return true; +} + +/* static */ ModuleScope* ModuleScope::createWithData(JSContext* cx, MutableHandle<UniquePtr<Data>> data, HandleModuleObject module, HandleScope enclosing) { MOZ_ASSERT(data); MOZ_ASSERT(enclosing->is<GlobalScope>()); - // ModuleScope::Data has GCManagedDeletePolicy because it contains a - // GCPtr. Destruction of |copy| below may trigger calls into the GC. - - // The data that's passed in is from the frontend and is LifoAlloc'd. - // Copy it now that we're creating a permanent VM scope. RootedShape envShape(cx); - BindingIter bi(*data); - if (!PrepareScopeData<ModuleScope>(cx, bi, data, - &ModuleEnvironmentObject::class_, - ModuleScopeEnvShapeFlags, &envShape)) { + if (!prepareForScopeCreation(cx, data, module, &envShape)) { return nullptr; } - // Modules always need an environment object for now. - if (!envShape) { - envShape = getEmptyEnvironmentShape(cx); - if (!envShape) { - return nullptr; - } - } - - data->module.init(module); - return Scope::create<ModuleScope>(cx, ScopeKind::Module, enclosing, envShape, data); } /* static */ Shape* ModuleScope::getEmptyEnvironmentShape(JSContext* cx) { const JSClass* cls = &ModuleEnvironmentObject::class_; return EmptyEnvironmentShape(cx, cls, JSSLOT_FREE(cls),
--- a/js/src/vm/Scope.h +++ b/js/src/vm/Scope.h @@ -423,16 +423,22 @@ class LexicalScope : public Scope { HandleScope enclosing, MutableHandleScope scope); private: static LexicalScope* createWithData(JSContext* cx, ScopeKind kind, MutableHandle<UniquePtr<Data>> data, uint32_t firstFrameSlot, HandleScope enclosing); + static bool prepareForScopeCreation(JSContext* cx, ScopeKind kind, + uint32_t firstFrameSlot, + HandleScope enclosing, + MutableHandle<UniquePtr<Data>> data, + MutableHandleShape envShape); + Data& data() { return *static_cast<Data*>(data_); } const Data& data() const { return *static_cast<Data*>(data_); } static uint32_t nextFrameSlot(Scope* start); public: uint32_t firstFrameSlot() const; @@ -536,16 +542,23 @@ class FunctionScope : public Scope { void trace(JSTracer* trc); }; static FunctionScope* create(JSContext* cx, Handle<Data*> data, bool hasParameterExprs, bool needsEnvironment, HandleFunction fun, HandleScope enclosing); + static bool prepareForScopeCreation(JSContext* cx, + MutableHandle<UniquePtr<Data>> data, + bool hasParameterExprs, + IsFieldInitializer isFieldInitializer, + bool needsEnvironment, HandleFunction fun, + MutableHandleShape envShape); + static FunctionScope* clone(JSContext* cx, Handle<FunctionScope*> scope, HandleFunction fun, HandleScope enclosing); template <XDRMode mode> static XDRResult XDR(XDRState<mode>* xdr, HandleFunction fun, HandleScope enclosing, MutableHandleScope scope); private: @@ -634,16 +647,22 @@ class VarScope : public Scope { HandleScope enclosing, MutableHandleScope scope); private: static VarScope* createWithData(JSContext* cx, ScopeKind kind, MutableHandle<UniquePtr<Data>> data, uint32_t firstFrameSlot, bool needsEnvironment, HandleScope enclosing); + static bool prepareForScopeCreation(JSContext* cx, ScopeKind kind, + MutableHandle<UniquePtr<Data>> data, + uint32_t firstFrameSlot, + bool needsEnvironment, + MutableHandleShape envShape); + Data& data() { return *static_cast<Data*>(data_); } const Data& data() const { return *static_cast<Data*>(data_); } public: uint32_t firstFrameSlot() const; uint32_t nextFrameSlot() const { return data().nextFrameSlot; } @@ -806,16 +825,20 @@ class EvalScope : public Scope { static XDRResult XDR(XDRState<mode>* xdr, ScopeKind kind, HandleScope enclosing, MutableHandleScope scope); private: static EvalScope* createWithData(JSContext* cx, ScopeKind kind, MutableHandle<UniquePtr<Data>> data, HandleScope enclosing); + static bool prepareForScopeCreation(JSContext* cx, ScopeKind scopeKind, + MutableHandle<UniquePtr<Data>> data, + MutableHandleShape envShape); + Data& data() { return *static_cast<Data*>(data_); } const Data& data() const { return *static_cast<Data*>(data_); } public: // Starting a scope, the nearest var scope that a direct eval can // introduce vars on. static Scope* nearestVarScopeForDirectEval(Scope* scope); @@ -893,16 +916,21 @@ class ModuleScope : public Scope { HandleScope enclosing); private: static ModuleScope* createWithData(JSContext* cx, MutableHandle<UniquePtr<Data>> data, Handle<ModuleObject*> module, HandleScope enclosing); + static bool prepareForScopeCreation(JSContext* cx, + MutableHandle<UniquePtr<Data>> data, + HandleModuleObject module, + MutableHandleShape envShape); + Data& data() { return *static_cast<Data*>(data_); } const Data& data() const { return *static_cast<Data*>(data_); } public: uint32_t nextFrameSlot() const { return data().nextFrameSlot; } ModuleObject* module() const { return data().module; }