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

Unified Diff: src/ast/scopes.cc

Issue 2230323004: Cleanup scope resolution (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebase Created 4 years, 4 months 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') | test/mjsunit/function-name-eval-shadowed.js » ('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 c49d60400a168ea1167b1114e86da003cbe47764..c6ec5640bc3aae6ab04cf47a43c1ef22bb5b8d3c 100644
--- a/src/ast/scopes.cc
+++ b/src/ast/scopes.cc
@@ -1261,78 +1261,85 @@ Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
Variable* Scope::LookupRecursive(VariableProxy* proxy,
BindingKind* binding_kind,
AstNodeFactory* factory,
- Scope* max_outer_scope) {
- DCHECK(binding_kind != NULL);
+ Scope* outer_scope_end) {
+ DCHECK_NE(outer_scope_end, this);
+ DCHECK_NOT_NULL(binding_kind);
+ DCHECK_EQ(UNBOUND, *binding_kind);
if (already_resolved() && is_with_scope()) {
// Short-cut: if the scope is deserialized from a scope info, variable
// allocation is already fixed. We can simply return with dynamic lookup.
*binding_kind = DYNAMIC_LOOKUP;
- return NULL;
+ return nullptr;
}
// Try to find the variable in this scope.
Variable* var = LookupLocal(proxy->raw_name());
- // 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 remains the same.)
- if (var != NULL) {
+ // 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
+ // remains the same.)
+ if (var != nullptr) {
*binding_kind = BOUND;
return var;
}
// We did not find a variable locally. Check against the function variable, if
// any.
- *binding_kind = UNBOUND;
- var = is_function_scope()
- ? AsDeclarationScope()->LookupFunctionVar(proxy->raw_name())
- : nullptr;
- if (var != NULL) {
- *binding_kind = BOUND;
- } else if (outer_scope_ != nullptr && this != max_outer_scope) {
+ if (is_function_scope()) {
+ var = AsDeclarationScope()->LookupFunctionVar(proxy->raw_name());
+ if (var != nullptr) {
+ *binding_kind = calls_sloppy_eval() ? BOUND_EVAL_SHADOWED : BOUND;
+ return var;
+ }
+ }
+
+ if (outer_scope_ != outer_scope_end) {
var = outer_scope_->LookupRecursive(proxy, binding_kind, factory,
- max_outer_scope);
+ outer_scope_end);
if (*binding_kind == BOUND && is_function_scope()) {
var->ForceContextAllocation();
}
- } else {
- DCHECK(is_script_scope() || this == max_outer_scope);
- }
-
- // "this" can't be shadowed by "eval"-introduced bindings or by "with" scopes.
- // TODO(wingo): There are other variables in this category; add them.
- bool name_can_be_shadowed = var == nullptr || !var->is_this();
-
- if (is_with_scope() && name_can_be_shadowed) {
- DCHECK(!already_resolved());
- // The current scope is a with scope, so the variable binding can not be
- // statically resolved. However, note that it was necessary to do a lookup
- // in the outer scope anyway, because if a binding exists in an outer scope,
- // the associated variable has to be marked as potentially being accessed
- // from inside of an inner with scope (the property may not be in the 'with'
- // object).
- if (var != NULL) {
- var->set_is_used();
- var->ForceContextAllocation();
- if (proxy->is_assigned()) var->set_maybe_assigned();
+ // "this" can't be shadowed by "eval"-introduced bindings or by "with"
+ // scopes.
+ // TODO(wingo): There are other variables in this category; add them.
+ if (var != nullptr && var->is_this()) return var;
+
+ if (is_with_scope()) {
+ DCHECK(!already_resolved());
+ // The current scope is a with scope, so the variable binding can not be
+ // statically resolved. However, note that it was necessary to do a lookup
+ // in the outer scope anyway, because if a binding exists in an outer
+ // scope, the associated variable has to be marked as potentially being
+ // accessed from inside of an inner with scope (the property may not be in
+ // the 'with' object).
+ if (var != nullptr) {
+ var->set_is_used();
+ var->ForceContextAllocation();
+ if (proxy->is_assigned()) var->set_maybe_assigned();
+ }
+ *binding_kind = DYNAMIC_LOOKUP;
+ return nullptr;
}
- *binding_kind = DYNAMIC_LOOKUP;
- return NULL;
- } else if (calls_sloppy_eval() && is_declaration_scope() &&
- !is_script_scope() && name_can_be_shadowed) {
+ } else {
+ DCHECK(is_function_scope() || is_script_scope() || is_eval_scope());
+ DCHECK(!is_with_scope());
adamk 2016/08/11 18:19:19 If you want this DCHECK to be useful it's gotta go
Toon Verwaest 2016/08/12 05:16:58 I don't see the issue with checking both? I can re
adamk 2016/08/15 17:45:00 What I mean is that a with scope will fail on the
+ }
+
+ if (calls_sloppy_eval() && is_declaration_scope() && !is_script_scope()) {
adamk 2016/08/11 18:19:19 This is no longer guarded by "name_can_be_shadowed
Toon Verwaest 2016/08/12 05:16:58 It is. Either we have a var null since outer scope
adamk 2016/08/15 17:45:00 Point taken :)
// A variable binding may have been found in an outer scope, but the current
- // scope makes a sloppy 'eval' call, so the found variable may not be
- // the correct one (the 'eval' may introduce a binding with the same name).
- // In that case, change the lookup result to reflect this situation.
- // Only scopes that can host var bindings (declaration scopes) need be
- // considered here (this excludes block and catch scopes), and variable
- // lookups at script scope are always dynamic.
+ // scope makes a sloppy 'eval' call, so the found variable may not be the
+ // correct one (the 'eval' may introduce a binding with the same name). In
+ // that case, change the lookup result to reflect this situation. Only
+ // scopes that can host var bindings (declaration scopes) need be considered
+ // here (this excludes block and catch scopes), and variable lookups at
+ // script scope are always dynamic.
if (*binding_kind == BOUND) {
*binding_kind = BOUND_EVAL_SHADOWED;
} else if (*binding_kind == UNBOUND) {
*binding_kind = UNBOUND_EVAL_SHADOWED;
}
}
+
return var;
}
@@ -1345,7 +1352,7 @@ void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy,
if (proxy->is_resolved()) return;
// Otherwise, try to resolve the variable.
- BindingKind binding_kind;
+ BindingKind binding_kind = UNBOUND;
Variable* var = LookupRecursive(proxy, &binding_kind, factory);
ResolveTo(info, binding_kind, proxy, var);
@@ -1435,7 +1442,6 @@ void Scope::ResolveVariablesRecursively(ParseInfo* info,
VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope,
ParseInfo* info,
VariableProxy* stack) {
- BindingKind binding_kind = BOUND;
for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr;
proxy = next) {
next = proxy->next_unresolved();
@@ -1443,9 +1449,9 @@ VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope,
// Note that we pass nullptr as AstNodeFactory: this phase should not create
// any new AstNodes, since none of the Scopes involved are backed up by
// ScopeInfo.
- Variable* var =
- LookupRecursive(proxy, &binding_kind, nullptr, max_outer_scope);
- // Anything that was bound
+ BindingKind binding_kind = UNBOUND;
+ Variable* var = LookupRecursive(proxy, &binding_kind, nullptr,
+ max_outer_scope->outer_scope());
if (var == nullptr) {
proxy->set_next_unresolved(stack);
stack = proxy;
« no previous file with comments | « src/ast/scopes.h ('k') | test/mjsunit/function-name-eval-shadowed.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698