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/ast/ast.h" | 10 #include "src/ast/ast.h" |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 } else if (context->IsScriptContext()) { | 330 } else if (context->IsScriptContext()) { |
331 // If we reach a script context, it's the outermost context with scope | 331 // If we reach a script context, it's the outermost context with scope |
332 // info. The next context will be the native context. Install the scope | 332 // info. The next context will be the native context. Install the scope |
333 // info of this script context onto the existing script scope to avoid | 333 // info of this script context onto the existing script scope to avoid |
334 // nesting script scopes. | 334 // nesting script scopes. |
335 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); | 335 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); |
336 script_scope->SetScriptScopeInfo(scope_info); | 336 script_scope->SetScriptScopeInfo(scope_info); |
337 DCHECK(context->previous()->IsNativeContext()); | 337 DCHECK(context->previous()->IsNativeContext()); |
338 break; | 338 break; |
339 } else if (context->IsFunctionContext()) { | 339 } else if (context->IsFunctionContext()) { |
340 Handle<ScopeInfo> scope_info(context->closure()->shared()->scope_info(), | 340 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); |
341 isolate); | |
342 // TODO(neis): For an eval scope, we currently create an ordinary function | 341 // TODO(neis): For an eval scope, we currently create an ordinary function |
343 // context. This is wrong and needs to be fixed. | 342 // context. This is wrong and needs to be fixed. |
344 // https://bugs.chromium.org/p/v8/issues/detail?id=5295 | 343 // https://bugs.chromium.org/p/v8/issues/detail?id=5295 |
345 DCHECK(scope_info->scope_type() == FUNCTION_SCOPE || | 344 DCHECK(scope_info->scope_type() == FUNCTION_SCOPE || |
346 scope_info->scope_type() == EVAL_SCOPE); | 345 scope_info->scope_type() == EVAL_SCOPE); |
347 outer_scope = | 346 outer_scope = |
348 new (zone) DeclarationScope(zone, FUNCTION_SCOPE, scope_info); | 347 new (zone) DeclarationScope(zone, FUNCTION_SCOPE, scope_info); |
349 if (scope_info->IsAsmFunction()) | 348 if (scope_info->IsAsmFunction()) |
350 outer_scope->AsDeclarationScope()->set_asm_function(); | 349 outer_scope->AsDeclarationScope()->set_asm_function(); |
351 if (scope_info->IsAsmModule()) | 350 if (scope_info->IsAsmModule()) |
352 outer_scope->AsDeclarationScope()->set_asm_module(); | 351 outer_scope->AsDeclarationScope()->set_asm_module(); |
353 } else if (context->IsBlockContext()) { | 352 } else if (context->IsBlockContext()) { |
354 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); | 353 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); |
355 DCHECK_EQ(scope_info->scope_type(), BLOCK_SCOPE); | 354 DCHECK_EQ(scope_info->scope_type(), BLOCK_SCOPE); |
356 if (scope_info->is_declaration_scope()) { | 355 if (scope_info->is_declaration_scope()) { |
357 outer_scope = | 356 outer_scope = |
358 new (zone) DeclarationScope(zone, BLOCK_SCOPE, scope_info); | 357 new (zone) DeclarationScope(zone, BLOCK_SCOPE, scope_info); |
359 } else { | 358 } else { |
360 outer_scope = new (zone) Scope(zone, BLOCK_SCOPE, scope_info); | 359 outer_scope = new (zone) Scope(zone, BLOCK_SCOPE, scope_info); |
361 } | 360 } |
362 } else if (context->IsModuleContext()) { | 361 } else if (context->IsModuleContext()) { |
363 ScopeInfo* scope_info = context->closure()->shared()->scope_info(); | 362 ScopeInfo* scope_info = context->scope_info(); |
364 DCHECK_EQ(scope_info->scope_type(), MODULE_SCOPE); | 363 DCHECK_EQ(scope_info->scope_type(), MODULE_SCOPE); |
365 outer_scope = new (zone) ModuleScope( | 364 outer_scope = new (zone) ModuleScope( |
366 isolate, Handle<ScopeInfo>(scope_info), ast_value_factory); | 365 isolate, Handle<ScopeInfo>(scope_info), ast_value_factory); |
367 } else { | 366 } else { |
368 DCHECK(context->IsCatchContext()); | 367 DCHECK(context->IsCatchContext()); |
369 String* name = context->catch_name(); | 368 String* name = context->catch_name(); |
370 outer_scope = new (zone) | 369 outer_scope = new (zone) |
371 Scope(zone, ast_value_factory->GetString(handle(name, isolate)), | 370 Scope(zone, ast_value_factory->GetString(handle(name, isolate)), |
372 Handle<ScopeInfo>(context->scope_info())); | 371 Handle<ScopeInfo>(context->scope_info())); |
373 } | 372 } |
374 if (current_scope != nullptr) { | 373 if (current_scope != nullptr) { |
375 outer_scope->AddInnerScope(current_scope); | 374 outer_scope->AddInnerScope(current_scope); |
| 375 DCHECK_IMPLIES( |
| 376 deserialization_mode == DeserializationMode::kKeepScopeInfo, |
| 377 current_scope->scope_info_->HasOuterScopeInfo()); |
| 378 DCHECK_IMPLIES( |
| 379 deserialization_mode == DeserializationMode::kKeepScopeInfo, |
| 380 outer_scope->scope_info_->Equals( |
| 381 current_scope->scope_info_->OuterScopeInfo())); |
376 } | 382 } |
377 current_scope = outer_scope; | 383 current_scope = outer_scope; |
378 if (deserialization_mode == DeserializationMode::kDeserializeOffHeap) { | 384 if (deserialization_mode == DeserializationMode::kDeserializeOffHeap) { |
379 current_scope->DeserializeScopeInfo(isolate, ast_value_factory); | 385 current_scope->DeserializeScopeInfo(isolate, ast_value_factory); |
380 } | 386 } |
381 if (innermost_scope == nullptr) innermost_scope = current_scope; | 387 if (innermost_scope == nullptr) innermost_scope = current_scope; |
382 context = context->previous(); | 388 context = context->previous(); |
383 } | 389 } |
384 | 390 |
385 if (innermost_scope == nullptr) return script_scope; | 391 if (innermost_scope == nullptr) return script_scope; |
386 script_scope->AddInnerScope(current_scope); | 392 script_scope->AddInnerScope(current_scope); |
| 393 #if DEBUG |
| 394 if (deserialization_mode == DeserializationMode::kKeepScopeInfo) { |
| 395 if (script_scope->scope_info_.is_null()) { |
| 396 DCHECK(!current_scope->scope_info_->HasOuterScopeInfo()); |
| 397 } else { |
| 398 DCHECK(!script_scope->scope_info_->HasOuterScopeInfo()); |
| 399 DCHECK(script_scope->scope_info_->Equals( |
| 400 current_scope->scope_info_->OuterScopeInfo())); |
| 401 } |
| 402 } |
| 403 #endif |
387 return innermost_scope; | 404 return innermost_scope; |
388 } | 405 } |
389 | 406 |
390 void Scope::DeserializeScopeInfo(Isolate* isolate, | 407 void Scope::DeserializeScopeInfo(Isolate* isolate, |
391 AstValueFactory* ast_value_factory) { | 408 AstValueFactory* ast_value_factory) { |
392 if (scope_info_.is_null()) return; | 409 if (scope_info_.is_null()) return; |
393 | 410 |
394 DCHECK(ThreadId::Current().Equals(isolate->thread_id())); | 411 DCHECK(ThreadId::Current().Equals(isolate->thread_id())); |
395 | 412 |
396 // Internalize context local variables. | 413 // Internalize context local variables. |
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
949 } | 966 } |
950 DCHECK(false); | 967 DCHECK(false); |
951 } | 968 } |
952 } | 969 } |
953 return nullptr; | 970 return nullptr; |
954 } | 971 } |
955 | 972 |
956 void DeclarationScope::AllocateVariables(ParseInfo* info, AnalyzeMode mode) { | 973 void DeclarationScope::AllocateVariables(ParseInfo* info, AnalyzeMode mode) { |
957 ResolveVariablesRecursively(info); | 974 ResolveVariablesRecursively(info); |
958 AllocateVariablesRecursively(); | 975 AllocateVariablesRecursively(); |
959 AllocateScopeInfosRecursively(info->isolate(), mode); | 976 |
| 977 MaybeHandle<ScopeInfo> outer_scope; |
| 978 for (const Scope* s = outer_scope_; s != nullptr; s = s->outer_scope_) { |
| 979 if (s->scope_info_.is_null()) continue; |
| 980 outer_scope = s->scope_info_; |
| 981 break; |
| 982 } |
| 983 AllocateScopeInfosRecursively(info->isolate(), mode, outer_scope); |
960 } | 984 } |
961 | 985 |
962 bool Scope::AllowsLazyParsing() const { | 986 bool Scope::AllowsLazyParsing() const { |
963 // If we are inside a block scope, we must parse eagerly to find out how | 987 // If we are inside a block scope, we must parse eagerly to find out how |
964 // to allocate variables on the block scope. At this point, declarations may | 988 // to allocate variables on the block scope. At this point, declarations may |
965 // not have yet been parsed. | 989 // not have yet been parsed. |
966 for (const Scope* s = this; s != nullptr; s = s->outer_scope_) { | 990 for (const Scope* s = this; s != nullptr; s = s->outer_scope_) { |
967 if (s->is_block_scope()) return false; | 991 if (s->is_block_scope()) return false; |
968 } | 992 } |
969 return true; | 993 return true; |
(...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1680 // If we didn't allocate any locals in the local context, then we only | 1704 // If we didn't allocate any locals in the local context, then we only |
1681 // need the minimal number of slots if we must have a context. | 1705 // need the minimal number of slots if we must have a context. |
1682 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) { | 1706 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) { |
1683 num_heap_slots_ = 0; | 1707 num_heap_slots_ = 0; |
1684 } | 1708 } |
1685 | 1709 |
1686 // Allocation done. | 1710 // Allocation done. |
1687 DCHECK(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 1711 DCHECK(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
1688 } | 1712 } |
1689 | 1713 |
1690 void Scope::AllocateScopeInfosRecursively(Isolate* isolate, AnalyzeMode mode) { | 1714 void Scope::AllocateScopeInfosRecursively(Isolate* isolate, AnalyzeMode mode, |
| 1715 MaybeHandle<ScopeInfo> outer_scope) { |
1691 DCHECK(scope_info_.is_null()); | 1716 DCHECK(scope_info_.is_null()); |
1692 if (mode == AnalyzeMode::kDebugger || NeedsScopeInfo()) { | 1717 if (mode == AnalyzeMode::kDebugger || NeedsScopeInfo()) { |
1693 scope_info_ = ScopeInfo::Create(isolate, zone(), this); | 1718 scope_info_ = ScopeInfo::Create(isolate, zone(), this, outer_scope); |
1694 } | 1719 } |
1695 | 1720 |
| 1721 // The ScopeInfo chain should mirror the context chain, so we only link to |
| 1722 // the next outer scope that needs a context. |
| 1723 MaybeHandle<ScopeInfo> next_outer_scope = outer_scope; |
| 1724 if (NeedsContext()) next_outer_scope = scope_info_; |
| 1725 |
1696 // Allocate ScopeInfos for inner scopes. | 1726 // Allocate ScopeInfos for inner scopes. |
1697 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { | 1727 for (Scope* scope = inner_scope_; scope != nullptr; scope = scope->sibling_) { |
1698 scope->AllocateScopeInfosRecursively(isolate, mode); | 1728 scope->AllocateScopeInfosRecursively(isolate, mode, next_outer_scope); |
1699 } | 1729 } |
1700 } | 1730 } |
1701 | 1731 |
1702 int Scope::StackLocalCount() const { | 1732 int Scope::StackLocalCount() const { |
1703 Variable* function = | 1733 Variable* function = |
1704 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; | 1734 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; |
1705 return num_stack_slots() - | 1735 return num_stack_slots() - |
1706 (function != nullptr && function->IsStackLocal() ? 1 : 0); | 1736 (function != nullptr && function->IsStackLocal() ? 1 : 0); |
1707 } | 1737 } |
1708 | 1738 |
1709 | 1739 |
1710 int Scope::ContextLocalCount() const { | 1740 int Scope::ContextLocalCount() const { |
1711 if (num_heap_slots() == 0) return 0; | 1741 if (num_heap_slots() == 0) return 0; |
1712 Variable* function = | 1742 Variable* function = |
1713 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; | 1743 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; |
1714 bool is_function_var_in_context = | 1744 bool is_function_var_in_context = |
1715 function != nullptr && function->IsContextSlot(); | 1745 function != nullptr && function->IsContextSlot(); |
1716 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1746 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
1717 (is_function_var_in_context ? 1 : 0); | 1747 (is_function_var_in_context ? 1 : 0); |
1718 } | 1748 } |
1719 | 1749 |
1720 } // namespace internal | 1750 } // namespace internal |
1721 } // namespace v8 | 1751 } // namespace v8 |
OLD | NEW |