OLD | NEW |
---|---|
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 1234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1245 } | 1245 } |
1246 } | 1246 } |
1247 | 1247 |
1248 void Scope::CheckZones() { | 1248 void Scope::CheckZones() { |
1249 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1249 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
1250 CHECK_EQ(scope->zone(), zone()); | 1250 CHECK_EQ(scope->zone(), zone()); |
1251 } | 1251 } |
1252 } | 1252 } |
1253 #endif // DEBUG | 1253 #endif // DEBUG |
1254 | 1254 |
1255 Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode, | 1255 Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) { |
1256 Variable::Kind kind) { | |
1257 if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone()); | 1256 if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone()); |
1258 VariableMap* map = dynamics_->GetMap(mode); | 1257 VariableMap* map = dynamics_->GetMap(mode); |
1259 Variable* var = map->Lookup(name); | 1258 Variable* var = map->Lookup(name); |
1260 if (var == NULL) { | 1259 if (var == NULL) { |
1261 // Declare a new non-local. | 1260 // Declare a new non-local. |
1262 InitializationFlag init_flag = (mode == VAR) | 1261 InitializationFlag init_flag = (mode == VAR) |
1263 ? kCreatedInitialized : kNeedsInitialization; | 1262 ? kCreatedInitialized : kNeedsInitialization; |
1264 var = map->Declare(zone(), NULL, name, mode, kind, init_flag); | 1263 var = map->Declare(zone(), NULL, name, mode, Variable::NORMAL, init_flag); |
1265 // Allocate it by giving it a dynamic lookup. | 1264 // Allocate it by giving it a dynamic lookup. |
1266 var->AllocateTo(VariableLocation::LOOKUP, -1); | 1265 var->AllocateTo(VariableLocation::LOOKUP, -1); |
1267 } | 1266 } |
1268 return var; | 1267 return var; |
1269 } | 1268 } |
1270 | 1269 |
1271 Variable* Scope::LookupRecursive(VariableProxy* proxy, | 1270 Variable* Scope::LookupRecursive(VariableProxy* proxy, |
1272 BindingKind* binding_kind, | 1271 BindingKind* binding_kind, |
1273 AstNodeFactory* factory, | 1272 AstNodeFactory* factory, |
1274 Scope* max_outer_scope) { | 1273 Scope* max_outer_scope) { |
1275 DCHECK(binding_kind != NULL); | 1274 DCHECK(binding_kind != NULL); |
1276 if (already_resolved() && is_with_scope()) { | |
adamk
2016/08/11 18:27:17
I'm fine with dropping this check, it's a very str
| |
1277 // Short-cut: if the scope is deserialized from a scope info, variable | |
1278 // allocation is already fixed. We can simply return with dynamic lookup. | |
1279 *binding_kind = DYNAMIC_LOOKUP; | |
1280 return NULL; | |
1281 } | |
1282 | |
1283 // Try to find the variable in this scope. | 1275 // Try to find the variable in this scope. |
1284 Variable* var = LookupLocal(proxy->raw_name()); | 1276 Variable* var = LookupLocal(proxy->raw_name()); |
1285 | 1277 |
1286 // We found a variable and we are done. (Even if there is an 'eval' in | 1278 // We found a variable and we are done. (Even if there is an 'eval' in |
1287 // this scope which introduces the same variable again, the resulting | 1279 // this scope which introduces the same variable again, the resulting |
1288 // variable remains the same.) | 1280 // variable remains the same.) |
1289 if (var != NULL) { | 1281 if (var != NULL) { |
1290 *binding_kind = BOUND; | 1282 *binding_kind = BOUND; |
1291 return var; | 1283 return var; |
1292 } | 1284 } |
(...skipping 14 matching lines...) Expand all Loading... | |
1307 var->ForceContextAllocation(); | 1299 var->ForceContextAllocation(); |
1308 } | 1300 } |
1309 } else { | 1301 } else { |
1310 DCHECK(is_script_scope() || this == max_outer_scope); | 1302 DCHECK(is_script_scope() || this == max_outer_scope); |
1311 } | 1303 } |
1312 | 1304 |
1313 // "this" can't be shadowed by "eval"-introduced bindings or by "with" scopes. | 1305 // "this" can't be shadowed by "eval"-introduced bindings or by "with" scopes. |
1314 // TODO(wingo): There are other variables in this category; add them. | 1306 // TODO(wingo): There are other variables in this category; add them. |
1315 bool name_can_be_shadowed = var == nullptr || !var->is_this(); | 1307 bool name_can_be_shadowed = var == nullptr || !var->is_this(); |
1316 | 1308 |
1317 if (is_with_scope() && name_can_be_shadowed) { | 1309 if (is_with_scope() && name_can_be_shadowed) { |
adamk
2016/08/11 18:27:17
This code has moved around due to your other CL, t
Toon Verwaest
2016/08/12 04:49:40
It was a cleanup in the sense that doesn't have un
| |
1318 DCHECK(!already_resolved()); | |
1319 // The current scope is a with scope, so the variable binding can not be | 1310 // The current scope is a with scope, so the variable binding can not be |
1320 // statically resolved. However, note that it was necessary to do a lookup | 1311 // statically resolved. However, note that it was necessary to do a lookup |
1321 // in the outer scope anyway, because if a binding exists in an outer scope, | 1312 // in the outer scope anyway, because if a binding exists in an outer scope, |
1322 // the associated variable has to be marked as potentially being accessed | 1313 // 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 'with' | 1314 // from inside of an inner with scope (the property may not be in the 'with' |
1324 // object). | 1315 // object). |
1325 if (var != NULL) { | 1316 if (!already_resolved() && var != NULL) { |
1326 var->set_is_used(); | 1317 var->set_is_used(); |
1327 var->ForceContextAllocation(); | 1318 var->ForceContextAllocation(); |
1328 if (proxy->is_assigned()) var->set_maybe_assigned(); | 1319 if (proxy->is_assigned()) var->set_maybe_assigned(); |
1329 } | 1320 } |
1330 *binding_kind = DYNAMIC_LOOKUP; | 1321 *binding_kind = DYNAMIC_LOOKUP; |
1331 return NULL; | 1322 return NULL; |
1332 } else if (calls_sloppy_eval() && is_declaration_scope() && | 1323 } else if (calls_sloppy_eval() && is_declaration_scope() && |
1333 !is_script_scope() && name_can_be_shadowed) { | 1324 !is_script_scope() && name_can_be_shadowed) { |
1334 // A variable binding may have been found in an outer scope, but the current | 1325 // A variable binding may have been found in an outer scope, but the current |
1335 // scope makes a sloppy 'eval' call, so the found variable may not be | 1326 // scope makes a sloppy 'eval' call, so the found variable may not be |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1378 name->ToCString().get()); | 1369 name->ToCString().get()); |
1379 } | 1370 } |
1380 VariableLocation location = var->location(); | 1371 VariableLocation location = var->location(); |
1381 CHECK(location == VariableLocation::LOCAL || | 1372 CHECK(location == VariableLocation::LOCAL || |
1382 location == VariableLocation::CONTEXT || | 1373 location == VariableLocation::CONTEXT || |
1383 location == VariableLocation::PARAMETER || | 1374 location == VariableLocation::PARAMETER || |
1384 location == VariableLocation::UNALLOCATED); | 1375 location == VariableLocation::UNALLOCATED); |
1385 } | 1376 } |
1386 #endif | 1377 #endif |
1387 | 1378 |
1388 // TODO(verwaest): 'this' should always be declared and found. That way we can | |
1389 // remove this workaround. | |
1390 Variable::Kind kind = proxy->is_this() ? Variable::THIS : Variable::NORMAL; | |
1391 switch (binding_kind) { | 1379 switch (binding_kind) { |
1392 case BOUND: | 1380 case BOUND: |
1393 break; | 1381 break; |
1394 | 1382 |
1395 case BOUND_EVAL_SHADOWED: | 1383 case BOUND_EVAL_SHADOWED: |
1396 // We either found a variable binding that might be shadowed by eval or | 1384 // We either found a variable binding that might be shadowed by eval or |
1397 // gave up on it (e.g. by encountering a local with the same in the outer | 1385 // gave up on it (e.g. by encountering a local with the same in the outer |
1398 // scope which was not promoted to a context, this can happen if we use | 1386 // scope which was not promoted to a context, this can happen if we use |
1399 // debugger to evaluate arbitrary expressions at a break point). | 1387 // debugger to evaluate arbitrary expressions at a break point). |
1400 if (var->IsGlobalObjectProperty()) { | 1388 if (var->IsGlobalObjectProperty()) { |
1401 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL, kind); | 1389 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); |
1402 } else if (var->is_dynamic()) { | 1390 } else if (var->is_dynamic()) { |
1403 var = NonLocal(proxy->raw_name(), DYNAMIC, kind); | 1391 var = NonLocal(proxy->raw_name(), DYNAMIC); |
1404 } else { | 1392 } else { |
1405 Variable* invalidated = var; | 1393 Variable* invalidated = var; |
1406 var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL, kind); | 1394 var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL); |
1407 var->set_local_if_not_shadowed(invalidated); | 1395 var->set_local_if_not_shadowed(invalidated); |
1408 } | 1396 } |
1409 break; | 1397 break; |
1410 | 1398 |
1411 case UNBOUND: | 1399 case UNBOUND: |
1412 // No binding has been found. Declare a variable on the global object. | 1400 // No binding has been found. Declare a variable on the global object. |
1413 var = info->script_scope()->DeclareDynamicGlobal(proxy->raw_name(), kind); | 1401 var = info->script_scope()->DeclareDynamicGlobal(proxy->raw_name(), |
1402 Variable::NORMAL); | |
1414 break; | 1403 break; |
1415 | 1404 |
1416 case UNBOUND_EVAL_SHADOWED: | 1405 case UNBOUND_EVAL_SHADOWED: |
1417 // No binding has been found. But some scope makes a sloppy 'eval' call. | 1406 // No binding has been found. But some scope makes a sloppy 'eval' call. |
1418 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL, kind); | 1407 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); |
1419 break; | 1408 break; |
1420 | 1409 |
1421 case DYNAMIC_LOOKUP: | 1410 case DYNAMIC_LOOKUP: |
1422 // The variable could not be resolved statically. | 1411 // The variable could not be resolved statically. |
1423 var = NonLocal(proxy->raw_name(), DYNAMIC, kind); | 1412 var = NonLocal(proxy->raw_name(), DYNAMIC); |
1424 break; | 1413 break; |
1425 } | 1414 } |
1426 | 1415 |
1427 DCHECK(var != NULL); | 1416 DCHECK(var != NULL); |
1428 if (proxy->is_assigned()) var->set_maybe_assigned(); | 1417 if (proxy->is_assigned()) var->set_maybe_assigned(); |
1429 | 1418 |
1430 proxy->BindTo(var); | 1419 proxy->BindTo(var); |
1431 } | 1420 } |
1432 | 1421 |
1433 void Scope::ResolveVariablesRecursively(ParseInfo* info, | 1422 void Scope::ResolveVariablesRecursively(ParseInfo* info, |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1795 function != NULL && function->proxy()->var()->IsContextSlot(); | 1784 function != NULL && function->proxy()->var()->IsContextSlot(); |
1796 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1785 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
1797 (is_function_var_in_context ? 1 : 0); | 1786 (is_function_var_in_context ? 1 : 0); |
1798 } | 1787 } |
1799 | 1788 |
1800 | 1789 |
1801 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1790 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
1802 | 1791 |
1803 } // namespace internal | 1792 } // namespace internal |
1804 } // namespace v8 | 1793 } // namespace v8 |
OLD | NEW |