Index: src/ast/scopes.cc |
diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc |
index fc020ccefb81466a40ad04295019d6b9a226ae65..16ef6a5409efab551542eec2881a7c7519cfc153 100644 |
--- a/src/ast/scopes.cc |
+++ b/src/ast/scopes.cc |
@@ -15,6 +15,10 @@ |
namespace v8 { |
namespace internal { |
+namespace { |
+void* kDummyPreParserVariable = reinterpret_cast<void*>(0x1); |
+} // namespace |
+ |
// ---------------------------------------------------------------------------- |
// Implementation of LocalsMap |
// |
@@ -49,6 +53,17 @@ Variable* VariableMap::Declare(Zone* zone, Scope* scope, |
return reinterpret_cast<Variable*>(p->value); |
} |
+void VariableMap::DeclareName(Zone* zone, const AstRawString* name) { |
+ Entry* p = |
+ ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(), |
+ ZoneAllocationPolicy(zone)); |
+ if (p->value == nullptr) { |
+ // The variable has not been declared yet -> insert it. |
+ DCHECK_EQ(name, p->key); |
+ p->value = kDummyPreParserVariable; |
+ } |
+} |
+ |
void VariableMap::Remove(Variable* var) { |
const AstRawString* name = var->raw_name(); |
ZoneHashMap::Remove(const_cast<AstRawString*>(name), name->hash()); |
@@ -263,7 +278,14 @@ void DeclarationScope::SetDefaults() { |
arguments_ = nullptr; |
this_function_ = nullptr; |
should_eager_compile_ = false; |
- is_lazily_parsed_ = false; |
+ was_lazily_parsed_ = false; |
+#ifdef DEBUG |
+ DeclarationScope* outer_declaration_scope = |
+ outer_scope_ ? outer_scope_->GetDeclarationScope() : nullptr; |
+ is_being_lazily_parsed_ = |
+ outer_declaration_scope ? outer_declaration_scope->is_being_lazily_parsed_ |
+ : false; |
+#endif |
} |
void Scope::SetDefaults() { |
@@ -305,7 +327,7 @@ bool DeclarationScope::ShouldEagerCompile() const { |
} |
void DeclarationScope::set_should_eager_compile() { |
- should_eager_compile_ = !is_lazily_parsed_; |
+ should_eager_compile_ = !was_lazily_parsed_; |
} |
void DeclarationScope::set_asm_module() { |
@@ -866,6 +888,8 @@ Variable* DeclarationScope::DeclareParameter( |
DCHECK(is_function_scope() || is_module_scope()); |
DCHECK(!has_rest_); |
DCHECK(!is_optional || !is_rest); |
+ DCHECK(!is_being_lazily_parsed_); |
+ DCHECK(!was_lazily_parsed_); |
Variable* var; |
if (mode == TEMPORARY) { |
var = NewTemporary(name); |
@@ -890,6 +914,8 @@ Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, |
// introduced during variable allocation, and TEMPORARY variables are |
// allocated via NewTemporary(). |
DCHECK(IsDeclaredVariableMode(mode)); |
+ DCHECK(!GetDeclarationScope()->is_being_lazily_parsed()); |
+ DCHECK(!GetDeclarationScope()->was_lazily_parsed()); |
return Declare(zone(), name, mode, kind, init_flag, maybe_assigned_flag); |
} |
@@ -899,6 +925,8 @@ Variable* Scope::DeclareVariable( |
bool* sloppy_mode_block_scope_function_redefinition, bool* ok) { |
DCHECK(IsDeclaredVariableMode(mode)); |
DCHECK(!already_resolved_); |
+ DCHECK(!GetDeclarationScope()->is_being_lazily_parsed()); |
+ DCHECK(!GetDeclarationScope()->was_lazily_parsed()); |
if (mode == VAR && !is_declaration_scope()) { |
return GetDeclarationScope()->DeclareVariable( |
@@ -997,6 +1025,26 @@ Variable* Scope::DeclareVariable( |
return var; |
} |
+void Scope::DeclareVariableName(const AstRawString* name, VariableMode mode) { |
+ DCHECK(IsDeclaredVariableMode(mode)); |
+ DCHECK(!already_resolved_); |
+ DCHECK(GetDeclarationScope()->is_being_lazily_parsed()); |
+ |
+ if (mode == VAR && !is_declaration_scope()) { |
+ return GetDeclarationScope()->DeclareVariableName(name, mode); |
+ } |
+ DCHECK(!is_catch_scope()); |
+ DCHECK(!is_with_scope()); |
+ DCHECK(!is_eval_scope()); |
+ DCHECK(is_declaration_scope() || |
+ (IsLexicalVariableMode(mode) && is_block_scope())); |
+ |
+ // Declare the variable in the declaration scope. |
+ if (LookupLocal(name) == nullptr) { |
+ variables_.DeclareName(zone(), name); |
+ } |
+} |
+ |
VariableProxy* Scope::NewUnresolved(AstNodeFactory* factory, |
const AstRawString* name, |
int start_position, VariableKind kind) { |
@@ -1271,7 +1319,7 @@ Scope* Scope::GetOuterScopeWithContext() { |
Handle<StringSet> DeclarationScope::CollectNonLocals( |
ParseInfo* info, Handle<StringSet> non_locals) { |
- VariableProxy* free_variables = FetchFreeVariables(this, true, info); |
+ VariableProxy* free_variables = FetchFreeVariables(this, info); |
for (VariableProxy* proxy = free_variables; proxy != nullptr; |
proxy = proxy->next_unresolved()) { |
non_locals = StringSet::Add(non_locals, proxy->name()); |
@@ -1307,9 +1355,10 @@ void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory, |
#ifdef DEBUG |
needs_migration_ = false; |
+ is_being_lazily_parsed_ = false; |
#endif |
- is_lazily_parsed_ = !aborted; |
+ was_lazily_parsed_ = !aborted; |
} |
void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) { |
@@ -1320,9 +1369,8 @@ void DeclarationScope::AnalyzePartially(AstNodeFactory* ast_node_factory) { |
// Try to resolve unresolved variables for this Scope and migrate those |
// which cannot be resolved inside. It doesn't make sense to try to resolve |
// them in the outer Scopes here, because they are incomplete. |
- for (VariableProxy* proxy = |
- FetchFreeVariables(this, !FLAG_lazy_inner_functions); |
- proxy != nullptr; proxy = proxy->next_unresolved()) { |
+ for (VariableProxy* proxy = FetchFreeVariables(this); proxy != nullptr; |
+ proxy = proxy->next_unresolved()) { |
DCHECK(!proxy->is_resolved()); |
VariableProxy* copy = ast_node_factory->CopyVariableProxy(proxy); |
copy->set_next_unresolved(unresolved); |
@@ -1490,7 +1538,7 @@ void Scope::Print(int n) { |
if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); |
if (is_declaration_scope()) { |
DeclarationScope* scope = AsDeclarationScope(); |
- if (scope->is_lazily_parsed()) Indent(n1, "// lazily parsed\n"); |
+ if (scope->was_lazily_parsed()) Indent(n1, "// lazily parsed\n"); |
if (scope->ShouldEagerCompile()) Indent(n1, "// will be compiled\n"); |
} |
if (num_stack_slots_ > 0) { |
@@ -1543,7 +1591,7 @@ void Scope::CheckZones() { |
DCHECK(!needs_migration_); |
for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
if (scope->is_declaration_scope() && |
- scope->AsDeclarationScope()->is_lazily_parsed()) { |
+ scope->AsDeclarationScope()->was_lazily_parsed()) { |
DCHECK_NULL(scope->zone()); |
DCHECK_NULL(scope->inner_scope_); |
continue; |
@@ -1599,6 +1647,13 @@ Variable* Scope::LookupRecursive(VariableProxy* proxy, Scope* outer_scope_end) { |
// The variable could not be resolved statically. |
if (var == nullptr) return var; |
+ // TODO(marja): Separate LookupRecursive for preparsed scopes better. |
+ if (var == kDummyPreParserVariable) { |
+ DCHECK(GetDeclarationScope()->is_being_lazily_parsed()); |
+ DCHECK(FLAG_lazy_inner_functions); |
+ return var; |
+ } |
+ |
if (is_function_scope() && !var->is_dynamic()) { |
var->ForceContextAllocation(); |
} |
@@ -1738,7 +1793,7 @@ void Scope::ResolveVariablesRecursively(ParseInfo* info) { |
// Lazy parsed declaration scopes are already partially analyzed. If there are |
// unresolved references remaining, they just need to be resolved in outer |
// scopes. |
- if (is_declaration_scope() && AsDeclarationScope()->is_lazily_parsed()) { |
+ if (is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()) { |
DCHECK(variables_.occupancy() == 0); |
for (VariableProxy* proxy = unresolved_; proxy != nullptr; |
proxy = proxy->next_unresolved()) { |
@@ -1765,34 +1820,34 @@ void Scope::ResolveVariablesRecursively(ParseInfo* info) { |
} |
VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, |
- bool try_to_resolve, ParseInfo* info, |
+ ParseInfo* info, |
VariableProxy* stack) { |
// Lazy parsed declaration scopes are already partially analyzed. If there are |
// unresolved references remaining, they just need to be resolved in outer |
// scopes. |
Scope* lookup = |
- is_declaration_scope() && AsDeclarationScope()->is_lazily_parsed() |
+ is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed() |
? outer_scope() |
: this; |
for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; |
proxy = next) { |
next = proxy->next_unresolved(); |
DCHECK(!proxy->is_resolved()); |
- Variable* var = nullptr; |
- if (try_to_resolve) { |
- var = lookup->LookupRecursive(proxy, max_outer_scope->outer_scope()); |
- } |
+ Variable* var = |
+ lookup->LookupRecursive(proxy, max_outer_scope->outer_scope()); |
if (var == nullptr) { |
proxy->set_next_unresolved(stack); |
stack = proxy; |
- } else if (info != nullptr) { |
- // In this case we need to leave scopes in a way that they can be |
- // allocated. If we resolved variables from lazy parsed scopes, we need to |
- // context allocate the var. |
- ResolveTo(info, proxy, var); |
- if (!var->is_dynamic() && lookup != this) var->ForceContextAllocation(); |
- } else { |
- var->set_is_used(); |
+ } else if (var != kDummyPreParserVariable) { |
+ if (info != nullptr) { |
+ // In this case we need to leave scopes in a way that they can be |
+ // allocated. If we resolved variables from lazy parsed scopes, we need |
+ // to context allocate the var. |
+ ResolveTo(info, proxy, var); |
+ if (!var->is_dynamic() && lookup != this) var->ForceContextAllocation(); |
+ } else { |
+ var->set_is_used(); |
+ } |
} |
} |
@@ -1800,8 +1855,7 @@ VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, |
unresolved_ = nullptr; |
for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
- stack = |
- scope->FetchFreeVariables(max_outer_scope, try_to_resolve, info, stack); |
+ stack = scope->FetchFreeVariables(max_outer_scope, info, stack); |
} |
return stack; |
@@ -1982,7 +2036,7 @@ void Scope::AllocateVariablesRecursively() { |
DCHECK(!already_resolved_); |
DCHECK_EQ(0, num_stack_slots_); |
// Don't allocate variables of preparsed scopes. |
- if (is_declaration_scope() && AsDeclarationScope()->is_lazily_parsed()) { |
+ if (is_declaration_scope() && AsDeclarationScope()->was_lazily_parsed()) { |
return; |
} |