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

Side by Side Diff: src/ast/scopes.cc

Issue 2230323004: Cleanup scope resolution (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add eval scope 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 unified diff | Download patch
« no previous file with comments | « src/ast/scopes.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/ast/scopes.h" 5 #include "src/ast/scopes.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "src/accessors.h" 9 #include "src/accessors.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 1252 matching lines...) Expand 10 before | Expand all | Expand 10 after
1263 var = map->Declare(zone(), NULL, name, mode, Variable::NORMAL, init_flag); 1263 var = map->Declare(zone(), NULL, name, mode, Variable::NORMAL, init_flag);
1264 // Allocate it by giving it a dynamic lookup. 1264 // Allocate it by giving it a dynamic lookup.
1265 var->AllocateTo(VariableLocation::LOOKUP, -1); 1265 var->AllocateTo(VariableLocation::LOOKUP, -1);
1266 } 1266 }
1267 return var; 1267 return var;
1268 } 1268 }
1269 1269
1270 Variable* Scope::LookupRecursive(VariableProxy* proxy, 1270 Variable* Scope::LookupRecursive(VariableProxy* proxy,
1271 BindingKind* binding_kind, 1271 BindingKind* binding_kind,
1272 AstNodeFactory* factory, 1272 AstNodeFactory* factory,
1273 Scope* max_outer_scope) { 1273 Scope* outer_scope_end) {
1274 DCHECK(binding_kind != NULL); 1274 DCHECK_NE(outer_scope_end, this);
1275 DCHECK_NOT_NULL(binding_kind);
1276 DCHECK_EQ(UNBOUND, *binding_kind);
1275 if (already_resolved() && is_with_scope()) { 1277 if (already_resolved() && is_with_scope()) {
1276 // Short-cut: if the scope is deserialized from a scope info, variable 1278 // Short-cut: if the scope is deserialized from a scope info, variable
1277 // allocation is already fixed. We can simply return with dynamic lookup. 1279 // allocation is already fixed. We can simply return with dynamic lookup.
1278 *binding_kind = DYNAMIC_LOOKUP; 1280 *binding_kind = DYNAMIC_LOOKUP;
1279 return NULL; 1281 return nullptr;
1280 } 1282 }
1281 1283
1282 // Try to find the variable in this scope. 1284 // Try to find the variable in this scope.
1283 Variable* var = LookupLocal(proxy->raw_name()); 1285 Variable* var = LookupLocal(proxy->raw_name());
1284 1286
1285 // We found a variable and we are done. (Even if there is an 'eval' in 1287 // We found a variable and we are done. (Even if there is an 'eval' in
1286 // this scope which introduces the same variable again, the resulting 1288 // this scope which introduces the same variable again, the resulting
1287 // variable remains the same.) 1289 // variable remains the same.)
1288 if (var != NULL) { 1290 if (var != nullptr) {
1289 *binding_kind = BOUND; 1291 *binding_kind = BOUND;
1290 return var; 1292 return var;
1291 } 1293 }
1292 1294
1293 // We did not find a variable locally. Check against the function variable, if 1295 // We did not find a variable locally. Check against the function variable, if
1294 // any. 1296 // any.
1295 *binding_kind = UNBOUND; 1297 if (is_function_scope()) {
1296 var = 1298 var = AsDeclarationScope()->LookupFunctionVar(proxy->raw_name(), factory);
1297 is_function_scope() 1299 if (var != nullptr) {
1298 ? AsDeclarationScope()->LookupFunctionVar(proxy->raw_name(), factory) 1300 *binding_kind = BOUND;
1299 : nullptr; 1301 return var;
marja 2016/08/11 09:37:35 As discussed offline, this changes the behavior wr
1300 if (var != NULL) { 1302 }
1301 *binding_kind = BOUND; 1303 }
1302 } else if (outer_scope_ != nullptr && this != max_outer_scope) { 1304
1305 if (outer_scope_ != outer_scope_end) {
1303 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory, 1306 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory,
1304 max_outer_scope); 1307 outer_scope_end);
1305 if (*binding_kind == BOUND && is_function_scope()) { 1308 if (*binding_kind == BOUND && is_function_scope()) {
1306 var->ForceContextAllocation(); 1309 var->ForceContextAllocation();
1307 } 1310 }
1311 // "this" can't be shadowed by "eval"-introduced bindings or by "with"
1312 // scopes.
1313 // TODO(wingo): There are other variables in this category; add them.
1314 if (var != nullptr && var->is_this()) return var;
1315
1316 if (is_with_scope()) {
1317 DCHECK(!already_resolved());
1318 // The current scope is a with scope, so the variable binding can not be
1319 // statically resolved. However, note that it was necessary to do a lookup
1320 // in the outer scope anyway, because if a binding exists in an outer
1321 // scope,
marja 2016/08/11 09:37:35 pls re-wrap this
1322 // the associated variable has to be marked as potentially being accessed
1323 // from inside of an inner with scope (the property may not be in the
1324 // 'with'
1325 // object).
1326 if (var != nullptr) {
1327 var->set_is_used();
1328 var->ForceContextAllocation();
1329 if (proxy->is_assigned()) var->set_maybe_assigned();
1330 }
1331 *binding_kind = DYNAMIC_LOOKUP;
1332 return nullptr;
1333 }
1308 } else { 1334 } else {
1309 DCHECK(is_script_scope() || this == max_outer_scope); 1335 DCHECK(is_function_scope() || is_script_scope() || is_eval_scope());
1336 DCHECK(!is_with_scope());
1310 } 1337 }
1311 1338
1312 // "this" can't be shadowed by "eval"-introduced bindings or by "with" scopes. 1339 if (calls_sloppy_eval() && is_declaration_scope() && !is_script_scope()) {
1313 // TODO(wingo): There are other variables in this category; add them.
1314 bool name_can_be_shadowed = var == nullptr || !var->is_this();
1315
1316 if (is_with_scope() && name_can_be_shadowed) {
1317 DCHECK(!already_resolved());
1318 // The current scope is a with scope, so the variable binding can not be
1319 // statically resolved. However, note that it was necessary to do a lookup
1320 // in the outer scope anyway, because if a binding exists in an outer scope,
1321 // the associated variable has to be marked as potentially being accessed
1322 // from inside of an inner with scope (the property may not be in the 'with'
1323 // object).
1324 if (var != NULL) {
1325 var->set_is_used();
1326 var->ForceContextAllocation();
1327 if (proxy->is_assigned()) var->set_maybe_assigned();
1328 }
1329 *binding_kind = DYNAMIC_LOOKUP;
1330 return NULL;
1331 } else if (calls_sloppy_eval() && is_declaration_scope() &&
1332 !is_script_scope() && name_can_be_shadowed) {
1333 // A variable binding may have been found in an outer scope, but the current 1340 // A variable binding may have been found in an outer scope, but the current
1334 // scope makes a sloppy 'eval' call, so the found variable may not be 1341 // scope makes a sloppy 'eval' call, so the found variable may not be the
1335 // the correct one (the 'eval' may introduce a binding with the same name). 1342 // correct one (the 'eval' may introduce a binding with the same name). In
1336 // In that case, change the lookup result to reflect this situation. 1343 // that case, change the lookup result to reflect this situation. Only
1337 // Only scopes that can host var bindings (declaration scopes) need be 1344 // scopes that can host var bindings (declaration scopes) need be considered
1338 // considered here (this excludes block and catch scopes), and variable 1345 // here (this excludes block and catch scopes), and variable lookups at
1339 // lookups at script scope are always dynamic. 1346 // script scope are always dynamic.
1340 if (*binding_kind == BOUND) { 1347 if (*binding_kind == BOUND) {
1341 *binding_kind = BOUND_EVAL_SHADOWED; 1348 *binding_kind = BOUND_EVAL_SHADOWED;
1342 } else if (*binding_kind == UNBOUND) { 1349 } else if (*binding_kind == UNBOUND) {
1343 *binding_kind = UNBOUND_EVAL_SHADOWED; 1350 *binding_kind = UNBOUND_EVAL_SHADOWED;
1344 } 1351 }
1345 } 1352 }
1353
1346 return var; 1354 return var;
1347 } 1355 }
1348 1356
1349 void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy, 1357 void Scope::ResolveVariable(ParseInfo* info, VariableProxy* proxy,
1350 AstNodeFactory* factory) { 1358 AstNodeFactory* factory) {
1351 DCHECK(info->script_scope()->is_script_scope()); 1359 DCHECK(info->script_scope()->is_script_scope());
1352 1360
1353 // If the proxy is already resolved there's nothing to do 1361 // If the proxy is already resolved there's nothing to do
1354 // (functions and consts may be resolved by the parser). 1362 // (functions and consts may be resolved by the parser).
1355 if (proxy->is_resolved()) return; 1363 if (proxy->is_resolved()) return;
1356 1364
1357 // Otherwise, try to resolve the variable. 1365 // Otherwise, try to resolve the variable.
1358 BindingKind binding_kind; 1366 BindingKind binding_kind = UNBOUND;
1359 Variable* var = LookupRecursive(proxy, &binding_kind, factory); 1367 Variable* var = LookupRecursive(proxy, &binding_kind, factory);
1360 1368
1361 ResolveTo(info, binding_kind, proxy, var); 1369 ResolveTo(info, binding_kind, proxy, var);
1362 } 1370 }
1363 1371
1364 void Scope::ResolveTo(ParseInfo* info, BindingKind binding_kind, 1372 void Scope::ResolveTo(ParseInfo* info, BindingKind binding_kind,
1365 VariableProxy* proxy, Variable* var) { 1373 VariableProxy* proxy, Variable* var) {
1366 #ifdef DEBUG 1374 #ifdef DEBUG
1367 if (info->script_is_native()) { 1375 if (info->script_is_native()) {
1368 // To avoid polluting the global object in native scripts 1376 // To avoid polluting the global object in native scripts
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1438 1446
1439 // Resolve unresolved variables for inner scopes. 1447 // Resolve unresolved variables for inner scopes.
1440 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { 1448 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) {
1441 scope->ResolveVariablesRecursively(info, factory); 1449 scope->ResolveVariablesRecursively(info, factory);
1442 } 1450 }
1443 } 1451 }
1444 1452
1445 VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, 1453 VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope,
1446 ParseInfo* info, 1454 ParseInfo* info,
1447 VariableProxy* stack) { 1455 VariableProxy* stack) {
1448 BindingKind binding_kind = BOUND;
1449 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr; 1456 for (VariableProxy *proxy = unresolved_, *next = nullptr; proxy != nullptr;
1450 proxy = next) { 1457 proxy = next) {
1451 next = proxy->next_unresolved(); 1458 next = proxy->next_unresolved();
1452 if (proxy->is_resolved()) continue; 1459 if (proxy->is_resolved()) continue;
1453 // Note that we pass nullptr as AstNodeFactory: this phase should not create 1460 // Note that we pass nullptr as AstNodeFactory: this phase should not create
1454 // any new AstNodes, since none of the Scopes involved are backed up by 1461 // any new AstNodes, since none of the Scopes involved are backed up by
1455 // ScopeInfo. 1462 // ScopeInfo.
1456 Variable* var = 1463 BindingKind binding_kind = UNBOUND;
1457 LookupRecursive(proxy, &binding_kind, nullptr, max_outer_scope); 1464 Variable* var = LookupRecursive(proxy, &binding_kind, nullptr,
1465 max_outer_scope->outer_scope());
1458 // Anything that was bound 1466 // Anything that was bound
marja 2016/08/11 09:37:35 What is this comment? (Not introduced by this CL b
1459 if (var == nullptr) { 1467 if (var == nullptr) {
1460 proxy->set_next_unresolved(stack); 1468 proxy->set_next_unresolved(stack);
1461 stack = proxy; 1469 stack = proxy;
1462 } else if (info != nullptr) { 1470 } else if (info != nullptr) {
1463 DCHECK_NE(UNBOUND, binding_kind); 1471 DCHECK_NE(UNBOUND, binding_kind);
1464 DCHECK_NE(UNBOUND_EVAL_SHADOWED, binding_kind); 1472 DCHECK_NE(UNBOUND_EVAL_SHADOWED, binding_kind);
1465 ResolveTo(info, binding_kind, proxy, var); 1473 ResolveTo(info, binding_kind, proxy, var);
1466 } 1474 }
1467 } 1475 }
1468 1476
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
1791 function != NULL && function->proxy()->var()->IsContextSlot(); 1799 function != NULL && function->proxy()->var()->IsContextSlot();
1792 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - 1800 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() -
1793 (is_function_var_in_context ? 1 : 0); 1801 (is_function_var_in_context ? 1 : 0);
1794 } 1802 }
1795 1803
1796 1804
1797 int Scope::ContextGlobalCount() const { return num_global_slots(); } 1805 int Scope::ContextGlobalCount() const { return num_global_slots(); }
1798 1806
1799 } // namespace internal 1807 } // namespace internal
1800 } // namespace v8 1808 } // namespace v8
OLDNEW
« no previous file with comments | « src/ast/scopes.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698