Commit 11a25229 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[parser] Cache scope-info-backed lookup results on entry scope

We'll always lookup variables in the entry scope-info-backed chain through a
single entrypoint, hence we can cache any variables we create in that chain on
the entry-point's VariableMap. Otherwise we always have to redo all negative
lookups until we hit the scope that introduces it (the script scope being the
final possible scope to introduce it).

This should allow us to get rid of the ContextSlotCache as well.

Change-Id: I2dc2c9c35d69f35dab3fe3d0353aba1ac68515a5
Reviewed-on: https://chromium-review.googlesource.com/c/1337729Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57542}
parent b434ee97
...@@ -157,7 +157,7 @@ DeclarationScope::DeclarationScope(Zone* zone, ...@@ -157,7 +157,7 @@ DeclarationScope::DeclarationScope(Zone* zone,
// Make sure that if we don't find the global 'this', it won't be declared as // Make sure that if we don't find the global 'this', it won't be declared as
// a regular dynamic global by predeclaring it with the right variable kind. // a regular dynamic global by predeclaring it with the right variable kind.
DeclareDynamicGlobal(ast_value_factory->this_string(), THIS_VARIABLE); DeclareDynamicGlobal(ast_value_factory->this_string(), THIS_VARIABLE, this);
} }
DeclarationScope::DeclarationScope(Zone* zone, Scope* outer_scope, DeclarationScope::DeclarationScope(Zone* zone, Scope* outer_scope,
...@@ -566,7 +566,7 @@ void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) { ...@@ -566,7 +566,7 @@ void DeclarationScope::HoistSloppyBlockFunctions(AstNodeFactory* factory) {
do { do {
var = query_scope->scope_info_.is_null() var = query_scope->scope_info_.is_null()
? query_scope->LookupLocal(name) ? query_scope->LookupLocal(name)
: query_scope->LookupInScopeInfo(name); : query_scope->LookupInScopeInfo(name, query_scope);
if (var != nullptr && IsLexical(var)) { if (var != nullptr && IsLexical(var)) {
should_hoist = false; should_hoist = false;
break; break;
...@@ -920,9 +920,9 @@ void Scope::ReplaceOuterScope(Scope* outer) { ...@@ -920,9 +920,9 @@ void Scope::ReplaceOuterScope(Scope* outer) {
outer_scope_ = outer; outer_scope_ = outer;
} }
Variable* Scope::LookupInScopeInfo(const AstRawString* name) { Variable* Scope::LookupInScopeInfo(const AstRawString* name, Scope* cache) {
DCHECK(!scope_info_.is_null()); DCHECK(!scope_info_.is_null());
Variable* cached = variables_.Lookup(name); Variable* cached = cache->variables_.Lookup(name);
if (cached) return cached; if (cached) return cached;
Handle<String> name_handle = name->string(); Handle<String> name_handle = name->string();
...@@ -968,8 +968,8 @@ Variable* Scope::LookupInScopeInfo(const AstRawString* name) { ...@@ -968,8 +968,8 @@ Variable* Scope::LookupInScopeInfo(const AstRawString* name) {
// TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and
// ARGUMENTS bindings as their corresponding VariableKind. // ARGUMENTS bindings as their corresponding VariableKind.
Variable* var = variables_.Declare(zone(), this, name, mode, kind, init_flag, Variable* var = cache->variables_.Declare(zone(), this, name, mode, kind,
maybe_assigned_flag); init_flag, maybe_assigned_flag);
var->AllocateTo(location, index); var->AllocateTo(location, index);
return var; return var;
} }
...@@ -1188,10 +1188,11 @@ void Scope::AddUnresolved(VariableProxy* proxy) { ...@@ -1188,10 +1188,11 @@ void Scope::AddUnresolved(VariableProxy* proxy) {
} }
Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name, Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name,
VariableKind kind) { VariableKind kind,
Scope* cache) {
DCHECK(is_script_scope()); DCHECK(is_script_scope());
return variables_.Declare(zone(), this, name, VariableMode::kDynamicGlobal, return cache->variables_.Declare(zone(), this, name,
kind); VariableMode::kDynamicGlobal, kind);
// TODO(neis): Mark variable as maybe-assigned? // TODO(neis): Mark variable as maybe-assigned?
} }
...@@ -1809,6 +1810,7 @@ Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) { ...@@ -1809,6 +1810,7 @@ Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
template <Scope::ScopeLookupMode mode> template <Scope::ScopeLookupMode mode>
Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope, Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope,
Scope* outer_scope_end, bool force_context_allocation) { Scope* outer_scope_end, bool force_context_allocation) {
Scope* entry_point = scope;
while (true) { while (true) {
DCHECK_IMPLIES(mode == kParsedScope, !scope->is_debug_evaluate_scope_); DCHECK_IMPLIES(mode == kParsedScope, !scope->is_debug_evaluate_scope_);
// Short-cut: whenever we find a debug-evaluate scope, just look everything // Short-cut: whenever we find a debug-evaluate scope, just look everything
...@@ -1824,9 +1826,9 @@ Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope, ...@@ -1824,9 +1826,9 @@ Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope,
} }
// Try to find the variable in this scope. // Try to find the variable in this scope.
Variable* var = mode == kParsedScope Variable* var = mode == kParsedScope ? scope->LookupLocal(proxy->raw_name())
? scope->LookupLocal(proxy->raw_name()) : scope->LookupInScopeInfo(
: scope->LookupInScopeInfo(proxy->raw_name()); proxy->raw_name(), entry_point);
// We found a variable and we are done. (Even if there is an 'eval' in this // We found a variable and we are done. (Even if there is an 'eval' in this
// scope which introduces the same variable again, the resulting variable // scope which introduces the same variable again, the resulting variable
...@@ -1869,8 +1871,9 @@ Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope, ...@@ -1869,8 +1871,9 @@ Variable* Scope::Lookup(VariableProxy* proxy, Scope* scope,
if (V8_UNLIKELY(proxy->is_private_name())) return nullptr; if (V8_UNLIKELY(proxy->is_private_name())) return nullptr;
// No binding has been found. Declare a variable on the global object. // No binding has been found. Declare a variable on the global object.
return scope->AsDeclarationScope()->DeclareDynamicGlobal(proxy->raw_name(), return scope->AsDeclarationScope()->DeclareDynamicGlobal(
NORMAL_VARIABLE); proxy->raw_name(), NORMAL_VARIABLE,
mode == kDeserializedScope ? entry_point : scope);
} }
template Variable* Scope::Lookup<Scope::kParsedScope>( template Variable* Scope::Lookup<Scope::kParsedScope>(
......
...@@ -188,7 +188,7 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { ...@@ -188,7 +188,7 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
return variables_.Lookup(name); return variables_.Lookup(name);
} }
Variable* LookupInScopeInfo(const AstRawString* name); Variable* LookupInScopeInfo(const AstRawString* name, Scope* cache);
// Declare a local variable in this scope. If the variable has been // Declare a local variable in this scope. If the variable has been
// declared before, the previously declared variable is returned. // declared before, the previously declared variable is returned.
...@@ -485,7 +485,7 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) { ...@@ -485,7 +485,7 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
for (Scope* scope = this; scope != nullptr; scope = scope->outer_scope()) { for (Scope* scope = this; scope != nullptr; scope = scope->outer_scope()) {
Variable* var = scope->scope_info_.is_null() Variable* var = scope->scope_info_.is_null()
? scope->LookupLocal(name) ? scope->LookupLocal(name)
: scope->LookupInScopeInfo(name); : scope->LookupInScopeInfo(name, scope);
if (var != nullptr) return var; if (var != nullptr) return var;
} }
return nullptr; return nullptr;
...@@ -709,7 +709,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope { ...@@ -709,7 +709,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
Variable* LookupInModule(const AstRawString* name) { Variable* LookupInModule(const AstRawString* name) {
DCHECK(is_module_scope()); DCHECK(is_module_scope());
Variable* var = LookupInScopeInfo(name); Variable* var = LookupInScopeInfo(name, this);
DCHECK_NOT_NULL(var); DCHECK_NOT_NULL(var);
return var; return var;
} }
...@@ -779,7 +779,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope { ...@@ -779,7 +779,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
// scope) by a reference to an unresolved variable with no intervening // scope) by a reference to an unresolved variable with no intervening
// with statements or eval calls. // with statements or eval calls.
Variable* DeclareDynamicGlobal(const AstRawString* name, Variable* DeclareDynamicGlobal(const AstRawString* name,
VariableKind variable_kind); VariableKind variable_kind, Scope* cache);
// The variable corresponding to the 'this' value. // The variable corresponding to the 'this' value.
Variable* receiver() { Variable* receiver() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment