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" |
| (...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 689 MaybeAssignedFlag maybe_assigned_flag) { | 689 MaybeAssignedFlag maybe_assigned_flag) { |
| 690 DCHECK(!already_resolved_); | 690 DCHECK(!already_resolved_); |
| 691 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are | 691 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are |
| 692 // introduced during variable allocation, and TEMPORARY variables are | 692 // introduced during variable allocation, and TEMPORARY variables are |
| 693 // allocated via NewTemporary(). | 693 // allocated via NewTemporary(). |
| 694 DCHECK(IsDeclaredVariableMode(mode)); | 694 DCHECK(IsDeclaredVariableMode(mode)); |
| 695 return Declare(zone(), this, name, mode, kind, init_flag, | 695 return Declare(zone(), this, name, mode, kind, init_flag, |
| 696 maybe_assigned_flag); | 696 maybe_assigned_flag); |
| 697 } | 697 } |
| 698 | 698 |
| 699 Variable* Scope::DeclareVariable( | |
| 700 Declaration* declaration, VariableMode mode, InitializationFlag init, | |
| 701 bool allow_harmony_restrictive_generators, | |
| 702 bool* sloppy_mode_block_scope_function_redefinition, bool* ok) { | |
| 703 DCHECK(IsDeclaredVariableMode(mode) && mode != CONST_LEGACY); | |
| 704 DCHECK(!already_resolved_); | |
| 705 | |
| 706 if (mode == VAR && !is_declaration_scope()) { | |
| 707 return GetDeclarationScope()->DeclareVariable( | |
| 708 declaration, mode, init, allow_harmony_restrictive_generators, | |
| 709 sloppy_mode_block_scope_function_redefinition, ok); | |
| 710 } | |
| 711 DCHECK(!is_catch_scope()); | |
| 712 DCHECK(!is_with_scope()); | |
| 713 DCHECK(is_declaration_scope() || | |
| 714 (IsLexicalVariableMode(mode) && is_block_scope())); | |
| 715 | |
| 716 VariableProxy* proxy = declaration->proxy(); | |
| 717 DCHECK(proxy->raw_name() != NULL); | |
| 718 const AstRawString* name = proxy->raw_name(); | |
| 719 bool is_function_declaration = declaration->IsFunctionDeclaration(); | |
| 720 | |
| 721 Variable* var = nullptr; | |
| 722 if (is_eval_scope() && is_sloppy(language_mode()) && mode == VAR) { | |
| 723 // In a var binding in a sloppy direct eval, pollute the enclosing scope | |
| 724 // with this new binding by doing the following: | |
| 725 // The proxy is bound to a lookup variable to force a dynamic declaration | |
| 726 // using the DeclareEvalVar or DeclareEvalFunction runtime functions. | |
| 727 Variable::Kind kind = Variable::NORMAL; | |
| 728 // TODO(sigurds) figure out if kNotAssigned is OK here | |
| 729 var = new (zone()) Variable(this, name, mode, kind, init, kNotAssigned); | |
| 730 var->AllocateTo(VariableLocation::LOOKUP, -1); | |
| 731 } else { | |
| 732 // Declare the variable in the declaration scope. | |
| 733 var = LookupLocal(name); | |
| 734 if (var == NULL) { | |
| 735 // Declare the name. | |
| 736 Variable::Kind kind = Variable::NORMAL; | |
| 737 if (is_function_declaration) { | |
| 738 kind = Variable::FUNCTION; | |
| 739 } | |
| 740 var = DeclareLocal(name, mode, init, kind, kNotAssigned); | |
| 741 } else if (IsLexicalVariableMode(mode) || | |
| 742 IsLexicalVariableMode(var->mode())) { | |
| 743 // Allow duplicate function decls for web compat, see bug 4693. | |
| 744 bool duplicate_allowed = false; | |
| 745 if (is_sloppy(language_mode()) && is_function_declaration && | |
| 746 var->is_function()) { | |
| 747 DCHECK(IsLexicalVariableMode(mode) && | |
| 748 IsLexicalVariableMode(var->mode())); | |
| 749 // If the duplication is allowed, then the var will show up | |
| 750 // in the SloppyBlockFunctionMap and the new FunctionKind | |
| 751 // will be a permitted duplicate. | |
| 752 FunctionKind function_kind = | |
| 753 declaration->AsFunctionDeclaration()->fun()->kind(); | |
| 754 duplicate_allowed = | |
| 755 GetDeclarationScope()->sloppy_block_function_map()->Lookup( | |
| 756 const_cast<AstRawString*>(name), name->hash()) != nullptr && | |
| 757 !IsAsyncFunction(function_kind) && | |
| 758 !(allow_harmony_restrictive_generators && | |
| 759 IsGeneratorFunction(function_kind)); | |
| 760 } | |
| 761 if (duplicate_allowed) { | |
| 762 *sloppy_mode_block_scope_function_redefinition = true; | |
| 763 } else { | |
| 764 // The name was declared in this scope before; check for conflicting | |
|
adamk
2016/08/30 18:58:32
This comment seems out of place and out of date. M
marja
2016/08/31 07:44:53
Ok, then I won't do anything for it..
| |
| 765 // re-declarations. We have a conflict if either of the declarations | |
| 766 // is not a var (in script scope, we also have to ignore legacy const | |
| 767 // for compatibility). There is similar code in runtime.cc in the | |
| 768 // Declare functions. The function CheckConflictingVarDeclarations | |
| 769 // checks for var and let bindings from different scopes whereas this | |
| 770 // is a check for conflicting declarations within the same scope. This | |
| 771 // check also covers the special case | |
| 772 // | |
| 773 // function () { let x; { var x; } } | |
| 774 // | |
| 775 // because the var declaration is hoisted to the function scope where | |
| 776 // 'x' is already bound. | |
| 777 DCHECK(IsDeclaredVariableMode(var->mode())); | |
| 778 // In harmony we treat re-declarations as early errors. See | |
|
adamk
2016/08/30 18:58:32
This comment is now out of place (it belongs in th
marja
2016/08/31 07:44:53
Hmm, but the decision to set *ok = false is done h
adamk
2016/08/31 18:10:34
Ah, I hadn't thought about it that way. I was thin
| |
| 779 // ES5 16 for a definition of early errors. | |
| 780 *ok = false; | |
| 781 return nullptr; | |
| 782 } | |
| 783 } else if (mode == VAR) { | |
| 784 var->set_maybe_assigned(); | |
| 785 } | |
| 786 } | |
| 787 DCHECK_NOT_NULL(var); | |
| 788 | |
| 789 // We add a declaration node for every declaration. The compiler | |
| 790 // will only generate code if necessary. In particular, declarations | |
| 791 // for inner local variables that do not represent functions won't | |
| 792 // result in any generated code. | |
| 793 // | |
| 794 // This will lead to multiple declaration nodes for the | |
| 795 // same variable if it is declared several times. This is not a | |
| 796 // semantic issue, but it may be a performance issue since it may | |
| 797 // lead to repeated DeclareEvalVar or DeclareEvalFunction calls. | |
| 798 decls_.Add(declaration, zone()); | |
| 799 proxy->BindTo(var); | |
| 800 return var; | |
| 801 } | |
| 802 | |
| 699 Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name, | 803 Variable* DeclarationScope::DeclareDynamicGlobal(const AstRawString* name, |
| 700 Variable::Kind kind) { | 804 Variable::Kind kind) { |
| 701 DCHECK(is_script_scope()); | 805 DCHECK(is_script_scope()); |
| 702 return variables_.Declare(zone(), this, name, DYNAMIC_GLOBAL, kind, | 806 return variables_.Declare(zone(), this, name, DYNAMIC_GLOBAL, kind, |
| 703 kCreatedInitialized); | 807 kCreatedInitialized); |
| 704 } | 808 } |
| 705 | 809 |
| 706 | 810 |
| 707 bool Scope::RemoveUnresolved(VariableProxy* var) { | 811 bool Scope::RemoveUnresolved(VariableProxy* var) { |
| 708 if (unresolved_ == var) { | 812 if (unresolved_ == var) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 728 DeclarationScope* scope = GetClosureScope(); | 832 DeclarationScope* scope = GetClosureScope(); |
| 729 Variable* var = new(zone()) Variable(scope, | 833 Variable* var = new(zone()) Variable(scope, |
| 730 name, | 834 name, |
| 731 TEMPORARY, | 835 TEMPORARY, |
| 732 Variable::NORMAL, | 836 Variable::NORMAL, |
| 733 kCreatedInitialized); | 837 kCreatedInitialized); |
| 734 scope->AddLocal(var); | 838 scope->AddLocal(var); |
| 735 return var; | 839 return var; |
| 736 } | 840 } |
| 737 | 841 |
| 738 void Scope::AddDeclaration(Declaration* declaration) { | |
| 739 DCHECK(!already_resolved_); | |
| 740 decls_.Add(declaration, zone()); | |
| 741 } | |
| 742 | |
| 743 | |
| 744 Declaration* Scope::CheckConflictingVarDeclarations() { | 842 Declaration* Scope::CheckConflictingVarDeclarations() { |
| 745 int length = decls_.length(); | 843 int length = decls_.length(); |
| 746 for (int i = 0; i < length; i++) { | 844 for (int i = 0; i < length; i++) { |
| 747 Declaration* decl = decls_[i]; | 845 Declaration* decl = decls_[i]; |
| 748 VariableMode mode = decl->proxy()->var()->mode(); | 846 VariableMode mode = decl->proxy()->var()->mode(); |
| 749 if (IsLexicalVariableMode(mode) && !is_block_scope()) continue; | 847 if (IsLexicalVariableMode(mode) && !is_block_scope()) continue; |
| 750 | 848 |
| 751 // Iterate through all scopes until and including the declaration scope. | 849 // Iterate through all scopes until and including the declaration scope. |
| 752 Scope* previous = NULL; | 850 Scope* previous = NULL; |
| 753 Scope* current = decl->scope(); | 851 Scope* current = decl->scope(); |
| (...skipping 862 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1616 function != nullptr && function->IsContextSlot(); | 1714 function != nullptr && function->IsContextSlot(); |
| 1617 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1715 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
| 1618 (is_function_var_in_context ? 1 : 0); | 1716 (is_function_var_in_context ? 1 : 0); |
| 1619 } | 1717 } |
| 1620 | 1718 |
| 1621 | 1719 |
| 1622 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1720 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
| 1623 | 1721 |
| 1624 } // namespace internal | 1722 } // namespace internal |
| 1625 } // namespace v8 | 1723 } // namespace v8 |
| OLD | NEW |