| 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 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 if (context->IsDebugEvaluateContext()) { | 279 if (context->IsDebugEvaluateContext()) { |
| 280 outer_scope->set_is_debug_evaluate_scope(); | 280 outer_scope->set_is_debug_evaluate_scope(); |
| 281 } | 281 } |
| 282 } else if (context->IsScriptContext()) { | 282 } else if (context->IsScriptContext()) { |
| 283 // If we reach a script context, it's the outermost context with scope | 283 // If we reach a script context, it's the outermost context with scope |
| 284 // info. The next context will be the native context. Install the scope | 284 // info. The next context will be the native context. Install the scope |
| 285 // info of this script context onto the existing script scope to avoid | 285 // info of this script context onto the existing script scope to avoid |
| 286 // nesting script scopes. | 286 // nesting script scopes. |
| 287 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); | 287 Handle<ScopeInfo> scope_info(context->scope_info(), isolate); |
| 288 script_scope->SetScriptScopeInfo(scope_info); | 288 script_scope->SetScriptScopeInfo(scope_info); |
| 289 script_scope->DeserializeScopeInfo(isolate, ast_value_factory); |
| 290 if (deserialization_mode == DeserializationMode::kDeserializeOffHeap) { |
| 291 script_scope->scope_info_ = Handle<ScopeInfo>::null(); |
| 292 } |
| 289 DCHECK(context->previous()->IsNativeContext()); | 293 DCHECK(context->previous()->IsNativeContext()); |
| 290 break; | 294 break; |
| 291 } else if (context->IsFunctionContext()) { | 295 } else if (context->IsFunctionContext()) { |
| 292 Handle<ScopeInfo> scope_info(context->closure()->shared()->scope_info(), | 296 Handle<ScopeInfo> scope_info(context->closure()->shared()->scope_info(), |
| 293 isolate); | 297 isolate); |
| 294 // TODO(neis): For an eval scope, we currently create an ordinary function | 298 // TODO(neis): For an eval scope, we currently create an ordinary function |
| 295 // context. This is wrong and needs to be fixed. | 299 // context. This is wrong and needs to be fixed. |
| 296 // https://bugs.chromium.org/p/v8/issues/detail?id=5295 | 300 // https://bugs.chromium.org/p/v8/issues/detail?id=5295 |
| 297 DCHECK(scope_info->scope_type() == FUNCTION_SCOPE || | 301 DCHECK(scope_info->scope_type() == FUNCTION_SCOPE || |
| 298 scope_info->scope_type() == EVAL_SCOPE); | 302 scope_info->scope_type() == EVAL_SCOPE); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 314 } else { | 318 } else { |
| 315 DCHECK(context->IsCatchContext()); | 319 DCHECK(context->IsCatchContext()); |
| 316 String* name = context->catch_name(); | 320 String* name = context->catch_name(); |
| 317 outer_scope = new (zone) | 321 outer_scope = new (zone) |
| 318 Scope(zone, ast_value_factory->GetString(handle(name, isolate))); | 322 Scope(zone, ast_value_factory->GetString(handle(name, isolate))); |
| 319 } | 323 } |
| 320 if (current_scope != nullptr) { | 324 if (current_scope != nullptr) { |
| 321 outer_scope->AddInnerScope(current_scope); | 325 outer_scope->AddInnerScope(current_scope); |
| 322 } | 326 } |
| 323 current_scope = outer_scope; | 327 current_scope = outer_scope; |
| 328 current_scope->DeserializeScopeInfo(isolate, ast_value_factory); |
| 324 if (deserialization_mode == DeserializationMode::kDeserializeOffHeap) { | 329 if (deserialization_mode == DeserializationMode::kDeserializeOffHeap) { |
| 325 current_scope->DeserializeScopeInfo(isolate, ast_value_factory); | 330 current_scope->scope_info_ = Handle<ScopeInfo>::null(); |
| 326 } | 331 } |
| 327 if (innermost_scope == nullptr) innermost_scope = current_scope; | 332 if (innermost_scope == nullptr) innermost_scope = current_scope; |
| 328 context = context->previous(); | 333 context = context->previous(); |
| 329 } | 334 } |
| 330 | 335 |
| 331 if (innermost_scope == nullptr) return script_scope; | 336 if (innermost_scope == nullptr) return script_scope; |
| 332 script_scope->AddInnerScope(current_scope); | 337 script_scope->AddInnerScope(current_scope); |
| 333 script_scope->PropagateScopeInfo(); | 338 script_scope->PropagateScopeInfo(); |
| 334 return innermost_scope; | 339 return innermost_scope; |
| 335 } | 340 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 Handle<String> name_handle(scope_info_->FunctionName(), isolate); | 396 Handle<String> name_handle(scope_info_->FunctionName(), isolate); |
| 392 const AstRawString* name = ast_value_factory->GetString(name_handle); | 397 const AstRawString* name = ast_value_factory->GetString(name_handle); |
| 393 VariableMode mode; | 398 VariableMode mode; |
| 394 int index = scope_info_->FunctionContextSlotIndex(*name_handle, &mode); | 399 int index = scope_info_->FunctionContextSlotIndex(*name_handle, &mode); |
| 395 if (index >= 0) { | 400 if (index >= 0) { |
| 396 Variable* result = AsDeclarationScope()->DeclareFunctionVar(name); | 401 Variable* result = AsDeclarationScope()->DeclareFunctionVar(name); |
| 397 DCHECK_EQ(mode, result->mode()); | 402 DCHECK_EQ(mode, result->mode()); |
| 398 result->AllocateTo(VariableLocation::CONTEXT, index); | 403 result->AllocateTo(VariableLocation::CONTEXT, index); |
| 399 } | 404 } |
| 400 } | 405 } |
| 401 | |
| 402 scope_info_ = Handle<ScopeInfo>::null(); | |
| 403 } | 406 } |
| 404 | 407 |
| 405 DeclarationScope* Scope::AsDeclarationScope() { | 408 DeclarationScope* Scope::AsDeclarationScope() { |
| 406 DCHECK(is_declaration_scope()); | 409 DCHECK(is_declaration_scope()); |
| 407 return static_cast<DeclarationScope*>(this); | 410 return static_cast<DeclarationScope*>(this); |
| 408 } | 411 } |
| 409 | 412 |
| 410 const DeclarationScope* Scope::AsDeclarationScope() const { | 413 const DeclarationScope* Scope::AsDeclarationScope() const { |
| 411 DCHECK(is_declaration_scope()); | 414 DCHECK(is_declaration_scope()); |
| 412 return static_cast<const DeclarationScope*>(this); | 415 return static_cast<const DeclarationScope*>(this); |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 } | 605 } |
| 603 | 606 |
| 604 | 607 |
| 605 void Scope::PropagateUsageFlagsToScope(Scope* other) { | 608 void Scope::PropagateUsageFlagsToScope(Scope* other) { |
| 606 DCHECK_NOT_NULL(other); | 609 DCHECK_NOT_NULL(other); |
| 607 DCHECK(!already_resolved_); | 610 DCHECK(!already_resolved_); |
| 608 DCHECK(!other->already_resolved_); | 611 DCHECK(!other->already_resolved_); |
| 609 if (calls_eval()) other->RecordEvalCall(); | 612 if (calls_eval()) other->RecordEvalCall(); |
| 610 } | 613 } |
| 611 | 614 |
| 612 Variable* Scope::LookupInScopeInfo(const AstRawString* name) { | |
| 613 Handle<String> name_handle = name->string(); | |
| 614 // The Scope is backed up by ScopeInfo. This means it cannot operate in a | |
| 615 // heap-independent mode, and all strings must be internalized immediately. So | |
| 616 // it's ok to get the Handle<String> here. | |
| 617 // If we have a serialized scope info, we might find the variable there. | |
| 618 // There should be no local slot with the given name. | |
| 619 DCHECK(scope_info_->StackSlotIndex(*name_handle) < 0); | |
| 620 | |
| 621 VariableMode mode; | |
| 622 InitializationFlag init_flag; | |
| 623 MaybeAssignedFlag maybe_assigned_flag; | |
| 624 | |
| 625 VariableLocation location = VariableLocation::CONTEXT; | |
| 626 int index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, | |
| 627 &init_flag, &maybe_assigned_flag); | |
| 628 if (index < 0) { | |
| 629 location = VariableLocation::GLOBAL; | |
| 630 index = ScopeInfo::ContextGlobalSlotIndex(scope_info_, name_handle, &mode, | |
| 631 &init_flag, &maybe_assigned_flag); | |
| 632 DCHECK(index < 0 || (is_script_scope() && mode == VAR)); | |
| 633 } | |
| 634 if (index < 0) { | |
| 635 location = VariableLocation::LOOKUP; | |
| 636 index = scope_info_->ParameterIndex(*name_handle); | |
| 637 if (index >= 0) { | |
| 638 mode = DYNAMIC; | |
| 639 init_flag = kCreatedInitialized; | |
| 640 // Be conservative and flag parameters as maybe assigned. Better | |
| 641 // information would require ScopeInfo to serialize the maybe_assigned bit | |
| 642 // also for parameters. | |
| 643 maybe_assigned_flag = kMaybeAssigned; | |
| 644 } | |
| 645 } | |
| 646 if (index < 0 && scope_type() == MODULE_SCOPE) { | |
| 647 location = VariableLocation::MODULE; | |
| 648 index = -1; // TODO(neis): Find module variables in scope info. | |
| 649 } | |
| 650 if (index < 0) return nullptr; // Nowhere found. | |
| 651 | |
| 652 Variable::Kind kind = Variable::NORMAL; | |
| 653 if (location == VariableLocation::CONTEXT && | |
| 654 index == scope_info_->ReceiverContextSlotIndex()) { | |
| 655 kind = Variable::THIS; | |
| 656 } | |
| 657 // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and | |
| 658 // ARGUMENTS bindings as their corresponding Variable::Kind. | |
| 659 | |
| 660 Variable* var = variables_.Declare(zone(), this, name, mode, kind, init_flag, | |
| 661 maybe_assigned_flag); | |
| 662 var->AllocateTo(location, index); | |
| 663 return var; | |
| 664 } | |
| 665 | |
| 666 Variable* DeclarationScope::LookupFunctionVar(const AstRawString* name) { | 615 Variable* DeclarationScope::LookupFunctionVar(const AstRawString* name) { |
| 667 if (function_ != nullptr && function_->raw_name() == name) { | 616 if (function_ != nullptr && function_->raw_name() == name) return function_; |
| 668 return function_; | 617 return nullptr; |
| 669 } else if (!scope_info_.is_null()) { | |
| 670 // If we are backed by a scope info, try to lookup the variable there. | |
| 671 VariableMode mode; | |
| 672 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); | |
| 673 if (index < 0) return nullptr; | |
| 674 Variable* var = DeclareFunctionVar(name); | |
| 675 DCHECK_EQ(mode, var->mode()); | |
| 676 var->AllocateTo(VariableLocation::CONTEXT, index); | |
| 677 return var; | |
| 678 } else { | |
| 679 return nullptr; | |
| 680 } | |
| 681 } | 618 } |
| 682 | 619 |
| 683 | 620 |
| 684 Variable* Scope::Lookup(const AstRawString* name) { | 621 Variable* Scope::Lookup(const AstRawString* name) { |
| 685 for (Scope* scope = this; | 622 for (Scope* scope = this; |
| 686 scope != NULL; | 623 scope != NULL; |
| 687 scope = scope->outer_scope()) { | 624 scope = scope->outer_scope()) { |
| 688 Variable* var = scope->LookupLocal(name); | 625 Variable* var = scope->LookupLocal(name); |
| 689 if (var != NULL) return var; | 626 if (var != NULL) return var; |
| 690 } | 627 } |
| (...skipping 959 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1650 function != nullptr && function->IsContextSlot(); | 1587 function != nullptr && function->IsContextSlot(); |
| 1651 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1588 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
| 1652 (is_function_var_in_context ? 1 : 0); | 1589 (is_function_var_in_context ? 1 : 0); |
| 1653 } | 1590 } |
| 1654 | 1591 |
| 1655 | 1592 |
| 1656 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1593 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
| 1657 | 1594 |
| 1658 } // namespace internal | 1595 } // namespace internal |
| 1659 } // namespace v8 | 1596 } // namespace v8 |
| OLD | NEW |