Chromium Code Reviews| 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" |
| 11 #include "src/isolate.h" | |
| 11 #include "src/messages.h" | 12 #include "src/messages.h" |
| 12 #include "src/parsing/parse-info.h" | 13 #include "src/parsing/parse-info.h" |
| 13 | 14 |
| 14 namespace v8 { | 15 namespace v8 { |
| 15 namespace internal { | 16 namespace internal { |
| 16 | 17 |
| 17 // ---------------------------------------------------------------------------- | 18 // ---------------------------------------------------------------------------- |
| 18 // Implementation of LocalsMap | 19 // Implementation of LocalsMap |
| 19 // | 20 // |
| 20 // Note: We are storing the handle locations as key values in the hash map. | 21 // Note: We are storing the handle locations as key values in the hash map. |
| (...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 689 MaybeAssignedFlag maybe_assigned_flag) { | 690 MaybeAssignedFlag maybe_assigned_flag) { |
| 690 DCHECK(!already_resolved_); | 691 DCHECK(!already_resolved_); |
| 691 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are | 692 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are |
| 692 // introduced during variable allocation, and TEMPORARY variables are | 693 // introduced during variable allocation, and TEMPORARY variables are |
| 693 // allocated via NewTemporary(). | 694 // allocated via NewTemporary(). |
| 694 DCHECK(IsDeclaredVariableMode(mode)); | 695 DCHECK(IsDeclaredVariableMode(mode)); |
| 695 return Declare(zone(), this, name, mode, kind, init_flag, | 696 return Declare(zone(), this, name, mode, kind, init_flag, |
| 696 maybe_assigned_flag); | 697 maybe_assigned_flag); |
| 697 } | 698 } |
| 698 | 699 |
| 700 Variable* Scope::DeclareVariableOrParameter( | |
| 701 Declaration* declaration, DeclarationDescriptor::Kind declaration_kind, | |
| 702 VariableMode mode, InitializationFlag init, | |
| 703 bool allow_harmony_restrictive_generators, | |
| 704 PendingCompilationErrorHandler* error_handler_, int* use_counts, bool* ok) { | |
| 705 DCHECK(IsDeclaredVariableMode(mode) && mode != CONST_LEGACY); | |
| 706 DCHECK(!already_resolved_); | |
| 707 | |
| 708 if (mode == VAR && !is_declaration_scope()) { | |
| 709 return GetDeclarationScope()->DeclareVariableOrParameter( | |
| 710 declaration, declaration_kind, mode, init, | |
| 711 allow_harmony_restrictive_generators, error_handler_, use_counts, ok); | |
| 712 } | |
| 713 DCHECK(!is_catch_scope()); | |
| 714 DCHECK(!is_with_scope()); | |
| 715 DCHECK(is_declaration_scope() || | |
| 716 (IsLexicalVariableMode(mode) && is_block_scope())); | |
| 717 | |
| 718 VariableProxy* proxy = declaration->proxy(); | |
| 719 DCHECK(proxy->raw_name() != NULL); | |
| 720 const AstRawString* name = proxy->raw_name(); | |
| 721 bool is_function_declaration = declaration->IsFunctionDeclaration(); | |
| 722 | |
| 723 Variable* var = NULL; | |
| 724 if (is_eval_scope() && is_sloppy(language_mode()) && mode == VAR) { | |
| 725 // In a var binding in a sloppy direct eval, pollute the enclosing scope | |
| 726 // with this new binding by doing the following: | |
| 727 // The proxy is bound to a lookup variable to force a dynamic declaration | |
| 728 // using the DeclareEvalVar or DeclareEvalFunction runtime functions. | |
| 729 Variable::Kind kind = Variable::NORMAL; | |
| 730 // TODO(sigurds) figure out if kNotAssigned is OK here | |
| 731 var = new (zone()) Variable(this, name, mode, kind, init, kNotAssigned); | |
| 732 var->AllocateTo(VariableLocation::LOOKUP, -1); | |
| 733 } else { | |
| 734 // Declare the variable in the declaration scope. | |
| 735 var = LookupLocal(name); | |
| 736 if (var == NULL) { | |
| 737 // Declare the name. | |
| 738 Variable::Kind kind = Variable::NORMAL; | |
| 739 if (is_function_declaration) { | |
| 740 kind = Variable::FUNCTION; | |
| 741 } | |
| 742 var = DeclareLocal(name, mode, init, kind, kNotAssigned); | |
| 743 } else if (IsLexicalVariableMode(mode) || | |
| 744 IsLexicalVariableMode(var->mode())) { | |
| 745 // Allow duplicate function decls for web compat, see bug 4693. | |
| 746 bool duplicate_allowed = false; | |
| 747 if (is_sloppy(language_mode()) && is_function_declaration && | |
| 748 var->is_function()) { | |
| 749 DCHECK(IsLexicalVariableMode(mode) && | |
| 750 IsLexicalVariableMode(var->mode())); | |
| 751 // If the duplication is allowed, then the var will show up | |
| 752 // in the SloppyBlockFunctionMap and the new FunctionKind | |
| 753 // will be a permitted duplicate. | |
| 754 FunctionKind function_kind = | |
| 755 declaration->AsFunctionDeclaration()->fun()->kind(); | |
| 756 duplicate_allowed = | |
| 757 GetDeclarationScope()->sloppy_block_function_map()->Lookup( | |
| 758 const_cast<AstRawString*>(name), name->hash()) != nullptr && | |
| 759 !IsAsyncFunction(function_kind) && | |
| 760 !(allow_harmony_restrictive_generators && | |
| 761 IsGeneratorFunction(function_kind)); | |
| 762 } | |
| 763 if (duplicate_allowed) { | |
| 764 ++use_counts[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition]; | |
| 765 } else { | |
| 766 // The name was declared in this scope before; check for conflicting | |
| 767 // re-declarations. We have a conflict if either of the declarations | |
| 768 // is not a var (in script scope, we also have to ignore legacy const | |
| 769 // for compatibility). There is similar code in runtime.cc in the | |
| 770 // Declare functions. The function CheckConflictingVarDeclarations | |
| 771 // checks for var and let bindings from different scopes whereas this | |
| 772 // is a check for conflicting declarations within the same scope. This | |
| 773 // check also covers the special case | |
| 774 // | |
| 775 // function () { let x; { var x; } } | |
| 776 // | |
| 777 // because the var declaration is hoisted to the function scope where | |
| 778 // 'x' is already bound. | |
| 779 DCHECK(IsDeclaredVariableMode(var->mode())); | |
| 780 // In harmony we treat re-declarations as early errors. See | |
| 781 // ES5 16 for a definition of early errors. | |
| 782 if (declaration_kind == DeclarationDescriptor::NORMAL) { | |
| 783 error_handler_->ReportMessageAt( | |
| 784 declaration->position(), declaration->proxy()->end_position(), | |
|
marja
2016/08/29 08:31:44
Here the positions are different than they used to
| |
| 785 MessageTemplate::kVarRedeclaration, name); | |
| 786 } else { | |
| 787 error_handler_->ReportMessageAt(declaration->position(), | |
| 788 declaration->proxy()->end_position(), | |
| 789 MessageTemplate::kParamDupe); | |
| 790 } | |
| 791 *ok = false; | |
| 792 return nullptr; | |
| 793 } | |
| 794 } else if (mode == VAR) { | |
| 795 var->set_maybe_assigned(); | |
| 796 } | |
| 797 } | |
| 798 DCHECK_NOT_NULL(var); | |
| 799 | |
| 800 // We add a declaration node for every declaration. The compiler | |
| 801 // will only generate code if necessary. In particular, declarations | |
| 802 // for inner local variables that do not represent functions won't | |
| 803 // result in any generated code. | |
| 804 // | |
| 805 // This will lead to multiple declaration nodes for the | |
| 806 // same variable if it is declared several times. This is not a | |
| 807 // semantic issue, but it may be a performance issue since it may | |
| 808 // lead to repeated DeclareEvalVar or DeclareEvalFunction calls. | |
| 809 decls_.Add(declaration, zone()); | |
|
marja
2016/08/29 08:31:44
Inlined Scope::AddDeclaration here.
| |
| 810 proxy->BindTo(var); | |
| 811 return var; | |
| 812 } | |
| 813 | |
| 699 Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name, | 814 Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name, |
| 700 Variable::Kind kind) { | 815 Variable::Kind kind) { |
| 701 DCHECK(is_script_scope()); | 816 DCHECK(is_script_scope()); |
| 702 return variables_.Declare(zone(), this, name, DYNAMIC_GLOBAL, kind, | 817 return variables_.Declare(zone(), this, name, DYNAMIC_GLOBAL, kind, |
| 703 kCreatedInitialized); | 818 kCreatedInitialized); |
| 704 } | 819 } |
| 705 | 820 |
| 706 | 821 |
| 707 bool Scope::RemoveUnresolved(VariableProxy* var) { | 822 bool Scope::RemoveUnresolved(VariableProxy* var) { |
| 708 if (unresolved_ == var) { | 823 if (unresolved_ == var) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 728 DeclarationScope* scope = GetClosureScope(); | 843 DeclarationScope* scope = GetClosureScope(); |
| 729 Variable* var = new(zone()) Variable(scope, | 844 Variable* var = new(zone()) Variable(scope, |
| 730 name, | 845 name, |
| 731 TEMPORARY, | 846 TEMPORARY, |
| 732 Variable::NORMAL, | 847 Variable::NORMAL, |
| 733 kCreatedInitialized); | 848 kCreatedInitialized); |
| 734 scope->AddLocal(var); | 849 scope->AddLocal(var); |
| 735 return var; | 850 return var; |
| 736 } | 851 } |
| 737 | 852 |
| 738 void Scope::AddDeclaration(Declaration* declaration) { | |
| 739 DCHECK(!already_resolved_); | |
| 740 decls_.Add(declaration, zone()); | |
| 741 } | |
| 742 | |
| 743 | |
| 744 Declaration* Scope::CheckConflictingVarDeclarations() { | 853 Declaration* Scope::CheckConflictingVarDeclarations() { |
| 745 int length = decls_.length(); | 854 int length = decls_.length(); |
| 746 for (int i = 0; i < length; i++) { | 855 for (int i = 0; i < length; i++) { |
| 747 Declaration* decl = decls_[i]; | 856 Declaration* decl = decls_[i]; |
| 748 VariableMode mode = decl->proxy()->var()->mode(); | 857 VariableMode mode = decl->proxy()->var()->mode(); |
| 749 if (IsLexicalVariableMode(mode) && !is_block_scope()) continue; | 858 if (IsLexicalVariableMode(mode) && !is_block_scope()) continue; |
| 750 | 859 |
| 751 // Iterate through all scopes until and including the declaration scope. | 860 // Iterate through all scopes until and including the declaration scope. |
| 752 Scope* previous = NULL; | 861 Scope* previous = NULL; |
| 753 Scope* current = decl->scope(); | 862 Scope* current = decl->scope(); |
| (...skipping 862 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1616 function != nullptr && function->IsContextSlot(); | 1725 function != nullptr && function->IsContextSlot(); |
| 1617 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1726 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
| 1618 (is_function_var_in_context ? 1 : 0); | 1727 (is_function_var_in_context ? 1 : 0); |
| 1619 } | 1728 } |
| 1620 | 1729 |
| 1621 | 1730 |
| 1622 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1731 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
| 1623 | 1732 |
| 1624 } // namespace internal | 1733 } // namespace internal |
| 1625 } // namespace v8 | 1734 } // namespace v8 |
| OLD | NEW |