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 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
202 language_mode_ = is_module_scope() ? STRICT : SLOPPY; | 202 language_mode_ = is_module_scope() ? STRICT : SLOPPY; |
203 | 203 |
204 scope_inside_with_ = false; | 204 scope_inside_with_ = false; |
205 scope_calls_eval_ = false; | 205 scope_calls_eval_ = false; |
206 scope_uses_super_property_ = false; | 206 scope_uses_super_property_ = false; |
207 has_arguments_parameter_ = false; | 207 has_arguments_parameter_ = false; |
208 asm_module_ = false; | 208 asm_module_ = false; |
209 asm_function_ = false; | 209 asm_function_ = false; |
210 scope_nonlinear_ = false; | 210 scope_nonlinear_ = false; |
211 is_hidden_ = false; | 211 is_hidden_ = false; |
212 is_debug_evaluate_scope_ = false; | |
212 | 213 |
213 outer_scope_calls_sloppy_eval_ = false; | 214 outer_scope_calls_sloppy_eval_ = false; |
214 inner_scope_calls_eval_ = false; | 215 inner_scope_calls_eval_ = false; |
215 force_eager_compilation_ = false; | 216 force_eager_compilation_ = false; |
216 force_context_allocation_ = false; | 217 force_context_allocation_ = false; |
217 | 218 |
218 is_declaration_scope_ = false; | 219 is_declaration_scope_ = false; |
219 } | 220 } |
220 | 221 |
221 bool Scope::HasSimpleParameters() { | 222 bool Scope::HasSimpleParameters() { |
222 DeclarationScope* scope = GetClosureScope(); | 223 DeclarationScope* scope = GetClosureScope(); |
223 return !scope->is_function_scope() || scope->has_simple_parameters(); | 224 return !scope->is_function_scope() || scope->has_simple_parameters(); |
224 } | 225 } |
225 | 226 |
226 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, | 227 Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, |
227 Context* context, | 228 Context* context, |
228 DeclarationScope* script_scope, | 229 DeclarationScope* script_scope, |
229 AstValueFactory* ast_value_factory, | 230 AstValueFactory* ast_value_factory, |
230 DeserializationMode deserialization_mode) { | 231 DeserializationMode deserialization_mode) { |
231 // Reconstruct the outer scope chain from a closure's context chain. | 232 // Reconstruct the outer scope chain from a closure's context chain. |
232 Scope* current_scope = nullptr; | 233 Scope* current_scope = nullptr; |
233 Scope* innermost_scope = nullptr; | 234 Scope* innermost_scope = nullptr; |
234 while (!context->IsNativeContext()) { | 235 while (!context->IsNativeContext()) { |
235 if (context->IsWithContext() || context->IsDebugEvaluateContext()) { | 236 if (context->IsWithContext() || context->IsDebugEvaluateContext()) { |
236 // For scope analysis, debug-evaluate is equivalent to a with scope. | 237 // For scope analysis, debug-evaluate is equivalent to a with scope. |
237 Scope* with_scope = new (zone) | 238 Scope* with_scope = new (zone) |
238 Scope(zone, current_scope, WITH_SCOPE, Handle<ScopeInfo>::null()); | 239 Scope(zone, current_scope, WITH_SCOPE, Handle<ScopeInfo>::null()); |
240 // TODO(yangguo): Remove once debug-evaluate properly keeps track of the | |
241 // function scope in which we are evaluating. | |
242 if (context->IsDebugEvaluateContext()) { | |
243 with_scope->set_is_debug_evaluate_scope(); | |
244 } | |
239 current_scope = with_scope; | 245 current_scope = with_scope; |
240 // All the inner scopes are inside a with. | 246 // All the inner scopes are inside a with. |
241 for (Scope* s = innermost_scope; s != nullptr; s = s->outer_scope()) { | 247 for (Scope* s = innermost_scope; s != nullptr; s = s->outer_scope()) { |
242 s->scope_inside_with_ = true; | 248 s->scope_inside_with_ = true; |
243 } | 249 } |
244 } else if (context->IsScriptContext()) { | 250 } else if (context->IsScriptContext()) { |
245 ScopeInfo* scope_info = context->scope_info(); | 251 ScopeInfo* scope_info = context->scope_info(); |
246 current_scope = new (zone) DeclarationScope( | 252 current_scope = new (zone) DeclarationScope( |
247 zone, current_scope, SCRIPT_SCOPE, Handle<ScopeInfo>(scope_info)); | 253 zone, current_scope, SCRIPT_SCOPE, Handle<ScopeInfo>(scope_info)); |
248 } else if (context->IsFunctionContext()) { | 254 } else if (context->IsFunctionContext()) { |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
547 Variable* result = variables_.Lookup(name); | 553 Variable* result = variables_.Lookup(name); |
548 if (result != NULL || scope_info_.is_null()) { | 554 if (result != NULL || scope_info_.is_null()) { |
549 return result; | 555 return result; |
550 } | 556 } |
551 Handle<String> name_handle = name->string(); | 557 Handle<String> name_handle = name->string(); |
552 // The Scope is backed up by ScopeInfo. This means it cannot operate in a | 558 // The Scope is backed up by ScopeInfo. This means it cannot operate in a |
553 // heap-independent mode, and all strings must be internalized immediately. So | 559 // heap-independent mode, and all strings must be internalized immediately. So |
554 // it's ok to get the Handle<String> here. | 560 // it's ok to get the Handle<String> here. |
555 // If we have a serialized scope info, we might find the variable there. | 561 // If we have a serialized scope info, we might find the variable there. |
556 // There should be no local slot with the given name. | 562 // There should be no local slot with the given name. |
557 DCHECK(scope_info_->StackSlotIndex(*name_handle) < 0 || is_block_scope()); | 563 DCHECK(scope_info_->StackSlotIndex(*name_handle) < 0); |
Toon Verwaest
2016/08/12 08:50:20
I don't see how this would be valid for block scop
| |
558 | 564 |
559 // Check context slot lookup. | 565 // Check context slot lookup. |
560 VariableMode mode; | 566 VariableMode mode; |
561 VariableLocation location = VariableLocation::CONTEXT; | 567 VariableLocation location = VariableLocation::CONTEXT; |
562 InitializationFlag init_flag; | 568 InitializationFlag init_flag; |
563 MaybeAssignedFlag maybe_assigned_flag; | 569 MaybeAssignedFlag maybe_assigned_flag; |
564 int index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, | 570 int index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, |
565 &init_flag, &maybe_assigned_flag); | 571 &init_flag, &maybe_assigned_flag); |
566 if (index < 0) { | 572 if (index < 0) { |
567 location = VariableLocation::GLOBAL; | 573 location = VariableLocation::GLOBAL; |
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1236 } | 1242 } |
1237 } | 1243 } |
1238 | 1244 |
1239 void Scope::CheckZones() { | 1245 void Scope::CheckZones() { |
1240 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1246 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
1241 CHECK_EQ(scope->zone(), zone()); | 1247 CHECK_EQ(scope->zone(), zone()); |
1242 } | 1248 } |
1243 } | 1249 } |
1244 #endif // DEBUG | 1250 #endif // DEBUG |
1245 | 1251 |
1246 Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode, | 1252 Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) { |
1247 Variable::Kind kind) { | |
1248 if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone()); | 1253 if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone()); |
1249 VariableMap* map = dynamics_->GetMap(mode); | 1254 VariableMap* map = dynamics_->GetMap(mode); |
1250 Variable* var = map->Lookup(name); | 1255 Variable* var = map->Lookup(name); |
1251 if (var == NULL) { | 1256 if (var == NULL) { |
1252 // Declare a new non-local. | 1257 // Declare a new non-local. |
1253 DCHECK(!IsLexicalVariableMode(mode)); | 1258 DCHECK(!IsLexicalVariableMode(mode)); |
1254 var = map->Declare(zone(), NULL, name, mode, kind, kCreatedInitialized); | 1259 var = map->Declare(zone(), NULL, name, mode, Variable::NORMAL, |
1260 kCreatedInitialized); | |
1255 // Allocate it by giving it a dynamic lookup. | 1261 // Allocate it by giving it a dynamic lookup. |
1256 var->AllocateTo(VariableLocation::LOOKUP, -1); | 1262 var->AllocateTo(VariableLocation::LOOKUP, -1); |
1257 } | 1263 } |
1258 return var; | 1264 return var; |
1259 } | 1265 } |
1260 | 1266 |
1261 Variable* Scope::LookupRecursive(VariableProxy* proxy, | 1267 Variable* Scope::LookupRecursive(VariableProxy* proxy, |
1262 BindingKind* binding_kind, | 1268 BindingKind* binding_kind, |
1263 AstNodeFactory* factory, | 1269 AstNodeFactory* factory, |
1264 Scope* outer_scope_end) { | 1270 Scope* outer_scope_end) { |
1265 DCHECK_NE(outer_scope_end, this); | 1271 DCHECK_NE(outer_scope_end, this); |
1266 DCHECK_NOT_NULL(binding_kind); | 1272 DCHECK_NOT_NULL(binding_kind); |
1267 DCHECK_EQ(UNBOUND, *binding_kind); | 1273 DCHECK_EQ(UNBOUND, *binding_kind); |
1268 if (already_resolved() && is_with_scope()) { | 1274 // Short-cut: whenever we find a debug-evaluate scope, just look everything up |
1269 // Short-cut: if the scope is deserialized from a scope info, variable | 1275 // dynamically. Debug-evaluate doesn't properly create scope info for the |
1270 // allocation is already fixed. We can simply return with dynamic lookup. | 1276 // lookups it does. It may not have a valid 'this' declaration, and anything |
1277 // accessed through debug-evaluate might invalidly resolve to stack-allocated | |
1278 // variables. | |
1279 // TODO(yangguo): Remove once debug-evaluate creates proper ScopeInfo for the | |
1280 // scopes in which it's evaluating. | |
1281 if (is_debug_evaluate_scope_) { | |
1271 *binding_kind = DYNAMIC_LOOKUP; | 1282 *binding_kind = DYNAMIC_LOOKUP; |
1272 return nullptr; | 1283 return nullptr; |
1273 } | 1284 } |
1274 | 1285 |
1275 // Try to find the variable in this scope. | 1286 // Try to find the variable in this scope. |
1276 Variable* var = LookupLocal(proxy->raw_name()); | 1287 Variable* var = LookupLocal(proxy->raw_name()); |
1277 | 1288 |
1278 // We found a variable and we are done. (Even if there is an 'eval' in this | 1289 // We found a variable and we are done. (Even if there is an 'eval' in this |
1279 // scope which introduces the same variable again, the resulting variable | 1290 // scope which introduces the same variable again, the resulting variable |
1280 // remains the same.) | 1291 // remains the same.) |
(...skipping 17 matching lines...) Expand all Loading... | |
1298 outer_scope_end); | 1309 outer_scope_end); |
1299 if (*binding_kind == BOUND && is_function_scope()) { | 1310 if (*binding_kind == BOUND && is_function_scope()) { |
1300 var->ForceContextAllocation(); | 1311 var->ForceContextAllocation(); |
1301 } | 1312 } |
1302 // "this" can't be shadowed by "eval"-introduced bindings or by "with" | 1313 // "this" can't be shadowed by "eval"-introduced bindings or by "with" |
1303 // scopes. | 1314 // scopes. |
1304 // TODO(wingo): There are other variables in this category; add them. | 1315 // TODO(wingo): There are other variables in this category; add them. |
1305 if (var != nullptr && var->is_this()) return var; | 1316 if (var != nullptr && var->is_this()) return var; |
1306 | 1317 |
1307 if (is_with_scope()) { | 1318 if (is_with_scope()) { |
1308 DCHECK(!already_resolved()); | |
1309 // The current scope is a with scope, so the variable binding can not be | 1319 // The current scope is a with scope, so the variable binding can not be |
1310 // statically resolved. However, note that it was necessary to do a lookup | 1320 // statically resolved. However, note that it was necessary to do a lookup |
1311 // in the outer scope anyway, because if a binding exists in an outer | 1321 // in the outer scope anyway, because if a binding exists in an outer |
1312 // scope, the associated variable has to be marked as potentially being | 1322 // scope, the associated variable has to be marked as potentially being |
1313 // accessed from inside of an inner with scope (the property may not be in | 1323 // accessed from inside of an inner with scope (the property may not be in |
1314 // the 'with' object). | 1324 // the 'with' object). |
1315 if (var != nullptr) { | 1325 if (var != nullptr && !already_resolved()) { |
1316 var->set_is_used(); | 1326 var->set_is_used(); |
1317 var->ForceContextAllocation(); | 1327 var->ForceContextAllocation(); |
1318 if (proxy->is_assigned()) var->set_maybe_assigned(); | 1328 if (proxy->is_assigned()) var->set_maybe_assigned(); |
1319 } | 1329 } |
1320 *binding_kind = DYNAMIC_LOOKUP; | 1330 *binding_kind = DYNAMIC_LOOKUP; |
1321 return nullptr; | 1331 return nullptr; |
1322 } | 1332 } |
1323 } else { | 1333 } else { |
1324 DCHECK(is_function_scope() || is_script_scope() || is_eval_scope()); | 1334 DCHECK(is_function_scope() || is_script_scope() || is_eval_scope()); |
1325 DCHECK(!is_with_scope()); | 1335 DCHECK(!is_with_scope()); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1374 name->ToCString().get()); | 1384 name->ToCString().get()); |
1375 } | 1385 } |
1376 VariableLocation location = var->location(); | 1386 VariableLocation location = var->location(); |
1377 CHECK(location == VariableLocation::LOCAL || | 1387 CHECK(location == VariableLocation::LOCAL || |
1378 location == VariableLocation::CONTEXT || | 1388 location == VariableLocation::CONTEXT || |
1379 location == VariableLocation::PARAMETER || | 1389 location == VariableLocation::PARAMETER || |
1380 location == VariableLocation::UNALLOCATED); | 1390 location == VariableLocation::UNALLOCATED); |
1381 } | 1391 } |
1382 #endif | 1392 #endif |
1383 | 1393 |
1384 // TODO(verwaest): 'this' should always be declared and found. That way we can | |
1385 // remove this workaround. | |
1386 Variable::Kind kind = proxy->is_this() ? Variable::THIS : Variable::NORMAL; | |
1387 switch (binding_kind) { | 1394 switch (binding_kind) { |
1388 case BOUND: | 1395 case BOUND: |
1389 break; | 1396 break; |
1390 | 1397 |
1391 case BOUND_EVAL_SHADOWED: | 1398 case BOUND_EVAL_SHADOWED: |
1392 // We either found a variable binding that might be shadowed by eval or | 1399 // We either found a variable binding that might be shadowed by eval or |
1393 // gave up on it (e.g. by encountering a local with the same in the outer | 1400 // gave up on it (e.g. by encountering a local with the same in the outer |
1394 // scope which was not promoted to a context, this can happen if we use | 1401 // scope which was not promoted to a context, this can happen if we use |
1395 // debugger to evaluate arbitrary expressions at a break point). | 1402 // debugger to evaluate arbitrary expressions at a break point). |
1396 if (var->IsGlobalObjectProperty()) { | 1403 if (var->IsGlobalObjectProperty()) { |
1397 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL, kind); | 1404 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); |
1398 } else if (var->is_dynamic()) { | 1405 } else if (var->is_dynamic()) { |
1399 var = NonLocal(proxy->raw_name(), DYNAMIC, kind); | 1406 var = NonLocal(proxy->raw_name(), DYNAMIC); |
1400 } else { | 1407 } else { |
1401 Variable* invalidated = var; | 1408 Variable* invalidated = var; |
1402 var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL, kind); | 1409 var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL); |
1403 var->set_local_if_not_shadowed(invalidated); | 1410 var->set_local_if_not_shadowed(invalidated); |
1404 } | 1411 } |
1405 break; | 1412 break; |
1406 | 1413 |
1407 case UNBOUND: | 1414 case UNBOUND: |
1408 // No binding has been found. Declare a variable on the global object. | 1415 // No binding has been found. Declare a variable on the global object. |
1409 var = info->script_scope()->DeclareDynamicGlobal(proxy->raw_name(), kind); | 1416 var = info->script_scope()->DeclareDynamicGlobal(proxy->raw_name(), |
1417 Variable::NORMAL); | |
1410 break; | 1418 break; |
1411 | 1419 |
1412 case UNBOUND_EVAL_SHADOWED: | 1420 case UNBOUND_EVAL_SHADOWED: |
1413 // No binding has been found. But some scope makes a sloppy 'eval' call. | 1421 // No binding has been found. But some scope makes a sloppy 'eval' call. |
1414 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL, kind); | 1422 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); |
1415 break; | 1423 break; |
1416 | 1424 |
1417 case DYNAMIC_LOOKUP: | 1425 case DYNAMIC_LOOKUP: |
1418 // The variable could not be resolved statically. | 1426 // The variable could not be resolved statically. |
1419 var = NonLocal(proxy->raw_name(), DYNAMIC, kind); | 1427 var = NonLocal(proxy->raw_name(), DYNAMIC); |
1420 break; | 1428 break; |
1421 } | 1429 } |
1422 | 1430 |
1423 DCHECK(var != NULL); | 1431 DCHECK(var != NULL); |
1424 if (proxy->is_assigned()) var->set_maybe_assigned(); | 1432 if (proxy->is_assigned()) var->set_maybe_assigned(); |
1425 | 1433 |
1426 proxy->BindTo(var); | 1434 proxy->BindTo(var); |
1427 } | 1435 } |
1428 | 1436 |
1429 void Scope::ResolveVariablesRecursively(ParseInfo* info, | 1437 void Scope::ResolveVariablesRecursively(ParseInfo* info, |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1790 function != nullptr && function->IsContextSlot(); | 1798 function != nullptr && function->IsContextSlot(); |
1791 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1799 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
1792 (is_function_var_in_context ? 1 : 0); | 1800 (is_function_var_in_context ? 1 : 0); |
1793 } | 1801 } |
1794 | 1802 |
1795 | 1803 |
1796 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1804 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
1797 | 1805 |
1798 } // namespace internal | 1806 } // namespace internal |
1799 } // namespace v8 | 1807 } // namespace v8 |
OLD | NEW |