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 |