Index: src/ast/scopes.cc |
diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc |
index 4ce1c0d85f7970f0b1cd5807d0519aac825d88c3..b5516fdd913d77c6a1f82e6bb0e02d6cc08af681 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) { |
Toon Verwaest
2016/12/01 10:50:56
We should probably have a debug mode flag to check
marja
2016/12/05 16:05:19
We already have is_lazily_parsed, but that's set t
|
+ 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()); |
@@ -884,6 +899,22 @@ Variable* DeclarationScope::DeclareParameter( |
return var; |
} |
+void DeclarationScope::DeclareParameterName( |
+ const AstRawString* name, bool is_optional, bool is_rest, |
+ bool* is_duplicate, AstValueFactory* ast_value_factory) { |
+ DCHECK(!already_resolved_); |
+ DCHECK(is_function_scope() || is_module_scope()); |
+ DCHECK(!has_rest_); |
+ DCHECK(!is_optional || !is_rest); |
+ variables_.DeclareName(zone(), name); |
+ // TODO(wingo): Avoid O(n^2) check. |
Toon Verwaest
2016/12/01 10:50:56
Does it make sense to still add TODO's for wingo?
marja
2016/12/05 16:05:19
Was just copied over; but I deleted this whole fun
|
+ *is_duplicate = IsDeclaredParameter(name); |
+ has_rest_ = is_rest; |
Toon Verwaest
2016/12/01 10:50:56
Do we care about rest? Isn't that just used to dea
marja
2016/12/05 16:05:19
Ditto; the downside is that now preparsed scopes d
|
+ if (name == ast_value_factory->arguments_string()) { |
Toon Verwaest
2016/12/01 10:50:56
Do we care about arguments? Isn't that just used t
marja
2016/12/05 16:05:19
Ditto
|
+ has_arguments_parameter_ = true; |
+ } |
+} |
+ |
Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, |
InitializationFlag init_flag, VariableKind kind, |
MaybeAssignedFlag maybe_assigned_flag) { |
@@ -999,6 +1030,25 @@ Variable* Scope::DeclareVariable( |
return var; |
} |
+void Scope::DeclareVariableName(const AstRawString* name, VariableMode mode) { |
+ DCHECK(IsDeclaredVariableMode(mode)); |
+ DCHECK(!already_resolved_); |
+ |
+ 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) { |
@@ -1273,7 +1323,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()); |
@@ -1322,9 +1372,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); |
@@ -1601,6 +1650,8 @@ Variable* Scope::LookupRecursive(VariableProxy* proxy, Scope* outer_scope_end) { |
// The variable could not be resolved statically. |
if (var == nullptr) return var; |
+ if (var == kDummyPreParserVariable) return var; |
Toon Verwaest
2016/12/01 10:50:56
Mmh. We should probably stop sharing LookupRecursi
marja
2016/12/05 16:05:19
Ok, added a TODO about that. For that we should so
|
+ |
if (is_function_scope() && !var->is_dynamic()) { |
var->ForceContextAllocation(); |
} |
@@ -1767,7 +1818,7 @@ void Scope::ResolveVariablesRecursively(ParseInfo* info) { |
} |
VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, |
- bool try_to_resolve, ParseInfo* info, |
+ ParseInfo* info, |
Toon Verwaest
2016/12/01 10:50:56
That obviously makes this slightly more complicate
marja
2016/12/05 16:05:19
I might need to introduce a new parameter here whi
|
VariableProxy* stack) { |
// Lazy parsed declaration scopes are already partially analyzed. If there are |
// unresolved references remaining, they just need to be resolved in outer |
@@ -1780,21 +1831,21 @@ VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, |
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(); |
+ } |
} |
} |
@@ -1802,8 +1853,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; |