Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Unified Diff: src/ast/scopes.cc

Issue 2407163003: PreParser: track variable declarations and parameters (Closed)
Patch Set: test fixes + more tests Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ast/scopes.h ('k') | src/parsing/preparser.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
}
« no previous file with comments | « src/ast/scopes.h ('k') | src/parsing/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698