| 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 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 VariableLocation location = VariableLocation::LOOKUP; | 326 VariableLocation location = VariableLocation::LOOKUP; |
| 327 Variable::Kind kind = Variable::NORMAL; | 327 Variable::Kind kind = Variable::NORMAL; |
| 328 | 328 |
| 329 Variable* result = variables_.Declare(zone(), this, name, mode, kind, | 329 Variable* result = variables_.Declare(zone(), this, name, mode, kind, |
| 330 init_flag, maybe_assigned_flag); | 330 init_flag, maybe_assigned_flag); |
| 331 result->AllocateTo(location, index); | 331 result->AllocateTo(location, index); |
| 332 } | 332 } |
| 333 | 333 |
| 334 // Internalize function proxy for this scope. | 334 // Internalize function proxy for this scope. |
| 335 if (scope_info_->HasFunctionName()) { | 335 if (scope_info_->HasFunctionName()) { |
| 336 AstNodeFactory factory(ast_value_factory); | |
| 337 Handle<String> name_handle(scope_info_->FunctionName(), isolate); | 336 Handle<String> name_handle(scope_info_->FunctionName(), isolate); |
| 338 const AstRawString* name = ast_value_factory->GetString(name_handle); | 337 const AstRawString* name = ast_value_factory->GetString(name_handle); |
| 339 VariableMode mode; | 338 VariableMode mode; |
| 340 int index = scope_info_->FunctionContextSlotIndex(*name_handle, &mode); | 339 int index = scope_info_->FunctionContextSlotIndex(*name_handle, &mode); |
| 341 if (index >= 0) { | 340 if (index >= 0) { |
| 342 Variable* result = new (zone()) | 341 Variable* result = AsDeclarationScope()->DeclareFunctionVar(name); |
| 343 Variable(this, name, mode, Variable::NORMAL, kCreatedInitialized); | 342 DCHECK_EQ(mode, result->mode()); |
| 344 VariableProxy* proxy = factory.NewVariableProxy(result); | |
| 345 VariableDeclaration* declaration = | |
| 346 factory.NewVariableDeclaration(proxy, this, kNoSourcePosition); | |
| 347 AsDeclarationScope()->DeclareFunctionVar(declaration); | |
| 348 result->AllocateTo(VariableLocation::CONTEXT, index); | 343 result->AllocateTo(VariableLocation::CONTEXT, index); |
| 349 } | 344 } |
| 350 } | 345 } |
| 351 | 346 |
| 352 scope_info_ = Handle<ScopeInfo>::null(); | 347 scope_info_ = Handle<ScopeInfo>::null(); |
| 353 } | 348 } |
| 354 | 349 |
| 355 DeclarationScope* Scope::AsDeclarationScope() { | 350 DeclarationScope* Scope::AsDeclarationScope() { |
| 356 DCHECK(is_declaration_scope()); | 351 DCHECK(is_declaration_scope()); |
| 357 return static_cast<DeclarationScope*>(this); | 352 return static_cast<DeclarationScope*>(this); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 CONST, Variable::NORMAL, kCreatedInitialized); | 418 CONST, Variable::NORMAL, kCreatedInitialized); |
| 424 | 419 |
| 425 if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) || | 420 if (IsConciseMethod(function_kind_) || IsClassConstructor(function_kind_) || |
| 426 IsAccessorFunction(function_kind_)) { | 421 IsAccessorFunction(function_kind_)) { |
| 427 this_function_ = variables_.Declare( | 422 this_function_ = variables_.Declare( |
| 428 zone(), this, ast_value_factory->this_function_string(), CONST, | 423 zone(), this, ast_value_factory->this_function_string(), CONST, |
| 429 Variable::NORMAL, kCreatedInitialized); | 424 Variable::NORMAL, kCreatedInitialized); |
| 430 } | 425 } |
| 431 } | 426 } |
| 432 | 427 |
| 428 Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name) { |
| 429 DCHECK(is_function_scope()); |
| 430 DCHECK_NULL(function_); |
| 431 VariableMode mode = is_strict(language_mode()) ? CONST : CONST_LEGACY; |
| 432 function_ = new (zone()) |
| 433 Variable(this, name, mode, Variable::NORMAL, kCreatedInitialized); |
| 434 return function_; |
| 435 } |
| 433 | 436 |
| 434 Scope* Scope::FinalizeBlockScope() { | 437 Scope* Scope::FinalizeBlockScope() { |
| 435 DCHECK(is_block_scope()); | 438 DCHECK(is_block_scope()); |
| 436 | 439 |
| 437 if (variables_.occupancy() > 0 || | 440 if (variables_.occupancy() > 0 || |
| 438 (is_declaration_scope() && calls_sloppy_eval())) { | 441 (is_declaration_scope() && calls_sloppy_eval())) { |
| 439 return this; | 442 return this; |
| 440 } | 443 } |
| 441 | 444 |
| 442 // Remove this scope from outer scope. | 445 // Remove this scope from outer scope. |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 } | 593 } |
| 591 // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and | 594 // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and |
| 592 // ARGUMENTS bindings as their corresponding Variable::Kind. | 595 // ARGUMENTS bindings as their corresponding Variable::Kind. |
| 593 | 596 |
| 594 Variable* var = variables_.Declare(zone(), this, name, mode, kind, init_flag, | 597 Variable* var = variables_.Declare(zone(), this, name, mode, kind, init_flag, |
| 595 maybe_assigned_flag); | 598 maybe_assigned_flag); |
| 596 var->AllocateTo(location, index); | 599 var->AllocateTo(location, index); |
| 597 return var; | 600 return var; |
| 598 } | 601 } |
| 599 | 602 |
| 600 Variable* DeclarationScope::LookupFunctionVar(const AstRawString* name, | 603 Variable* DeclarationScope::LookupFunctionVar(const AstRawString* name) { |
| 601 AstNodeFactory* factory) { | 604 if (function_ != nullptr && function_->raw_name() == name) { |
| 602 if (function_ != NULL && function_->proxy()->raw_name() == name) { | 605 return function_; |
| 603 return function_->proxy()->var(); | |
| 604 } else if (!scope_info_.is_null()) { | 606 } else if (!scope_info_.is_null()) { |
| 605 // If we are backed by a scope info, try to lookup the variable there. | 607 // If we are backed by a scope info, try to lookup the variable there. |
| 606 VariableMode mode; | 608 VariableMode mode; |
| 607 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); | 609 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); |
| 608 if (index < 0) return NULL; | 610 if (index < 0) return nullptr; |
| 609 Variable* var = new (zone()) | 611 Variable* var = DeclareFunctionVar(name); |
| 610 Variable(this, name, mode, Variable::NORMAL, kCreatedInitialized); | 612 DCHECK_EQ(mode, var->mode()); |
| 611 DCHECK_NOT_NULL(factory); | |
| 612 VariableProxy* proxy = factory->NewVariableProxy(var); | |
| 613 VariableDeclaration* declaration = | |
| 614 factory->NewVariableDeclaration(proxy, this, kNoSourcePosition); | |
| 615 DCHECK_EQ(factory->zone(), zone()); | |
| 616 DeclareFunctionVar(declaration); | |
| 617 var->AllocateTo(VariableLocation::CONTEXT, index); | 613 var->AllocateTo(VariableLocation::CONTEXT, index); |
| 618 return var; | 614 return var; |
| 619 } else { | 615 } else { |
| 620 return NULL; | 616 return nullptr; |
| 621 } | 617 } |
| 622 } | 618 } |
| 623 | 619 |
| 624 | 620 |
| 625 Variable* Scope::Lookup(const AstRawString* name) { | 621 Variable* Scope::Lookup(const AstRawString* name) { |
| 626 for (Scope* scope = this; | 622 for (Scope* scope = this; |
| 627 scope != NULL; | 623 scope != NULL; |
| 628 scope = scope->outer_scope()) { | 624 scope = scope->outer_scope()) { |
| 629 Variable* var = scope->LookupLocal(name); | 625 Variable* var = scope->LookupLocal(name); |
| 630 if (var != NULL) return var; | 626 if (var != NULL) return var; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 DCHECK(!already_resolved()); | 734 DCHECK(!already_resolved()); |
| 739 decls_.Add(declaration, zone()); | 735 decls_.Add(declaration, zone()); |
| 740 } | 736 } |
| 741 | 737 |
| 742 | 738 |
| 743 Declaration* Scope::CheckConflictingVarDeclarations() { | 739 Declaration* Scope::CheckConflictingVarDeclarations() { |
| 744 int length = decls_.length(); | 740 int length = decls_.length(); |
| 745 for (int i = 0; i < length; i++) { | 741 for (int i = 0; i < length; i++) { |
| 746 Declaration* decl = decls_[i]; | 742 Declaration* decl = decls_[i]; |
| 747 VariableMode mode = decl->proxy()->var()->mode(); | 743 VariableMode mode = decl->proxy()->var()->mode(); |
| 748 // We don't create a separate scope to hold the function name of a function | |
| 749 // expression, so we have to make sure not to consider it when checking for | |
| 750 // conflicts (since it's conceptually "outside" the declaration scope). | |
| 751 if (is_function_scope() && decl == AsDeclarationScope()->function()) | |
| 752 continue; | |
| 753 if (IsLexicalVariableMode(mode) && !is_block_scope()) continue; | 744 if (IsLexicalVariableMode(mode) && !is_block_scope()) continue; |
| 754 | 745 |
| 755 // Iterate through all scopes until and including the declaration scope. | 746 // Iterate through all scopes until and including the declaration scope. |
| 756 Scope* previous = NULL; | 747 Scope* previous = NULL; |
| 757 Scope* current = decl->scope(); | 748 Scope* current = decl->scope(); |
| 758 // Lexical vs lexical conflicts within the same scope have already been | 749 // Lexical vs lexical conflicts within the same scope have already been |
| 759 // captured in Parser::Declare. The only conflicts we still need to check | 750 // captured in Parser::Declare. The only conflicts we still need to check |
| 760 // are lexical vs VAR, or any declarations within a declaration block scope | 751 // are lexical vs VAR, or any declarations within a declaration block scope |
| 761 // vs lexical declarations in its surrounding (function) scope. | 752 // vs lexical declarations in its surrounding (function) scope. |
| 762 if (IsLexicalVariableMode(mode)) current = current->outer_scope_; | 753 if (IsLexicalVariableMode(mode)) current = current->outer_scope_; |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1139 FunctionKind function_kind = is_function_scope() | 1130 FunctionKind function_kind = is_function_scope() |
| 1140 ? AsDeclarationScope()->function_kind() | 1131 ? AsDeclarationScope()->function_kind() |
| 1141 : kNormalFunction; | 1132 : kNormalFunction; |
| 1142 Indent(n0, Header(scope_type_, function_kind, is_declaration_scope())); | 1133 Indent(n0, Header(scope_type_, function_kind, is_declaration_scope())); |
| 1143 if (scope_name_ != nullptr && !scope_name_->IsEmpty()) { | 1134 if (scope_name_ != nullptr && !scope_name_->IsEmpty()) { |
| 1144 PrintF(" "); | 1135 PrintF(" "); |
| 1145 PrintName(scope_name_); | 1136 PrintName(scope_name_); |
| 1146 } | 1137 } |
| 1147 | 1138 |
| 1148 // Print parameters, if any. | 1139 // Print parameters, if any. |
| 1149 VariableDeclaration* function = nullptr; | 1140 Variable* function = nullptr; |
| 1150 if (is_function_scope()) { | 1141 if (is_function_scope()) { |
| 1151 AsDeclarationScope()->PrintParameters(); | 1142 AsDeclarationScope()->PrintParameters(); |
| 1152 function = AsDeclarationScope()->function(); | 1143 function = AsDeclarationScope()->function_var(); |
| 1153 } | 1144 } |
| 1154 | 1145 |
| 1155 PrintF(" { // (%d, %d)\n", start_position(), end_position()); | 1146 PrintF(" { // (%d, %d)\n", start_position(), end_position()); |
| 1156 | 1147 |
| 1157 // Function name, if any (named function literals, only). | 1148 // Function name, if any (named function literals, only). |
| 1158 if (function != nullptr) { | 1149 if (function != nullptr) { |
| 1159 Indent(n1, "// (local) function name: "); | 1150 Indent(n1, "// (local) function name: "); |
| 1160 PrintName(function->proxy()->raw_name()); | 1151 PrintName(function->raw_name()); |
| 1161 PrintF("\n"); | 1152 PrintF("\n"); |
| 1162 } | 1153 } |
| 1163 | 1154 |
| 1164 // Scope info. | 1155 // Scope info. |
| 1165 if (HasTrivialOuterContext()) { | 1156 if (HasTrivialOuterContext()) { |
| 1166 Indent(n1, "// scope has trivial outer context\n"); | 1157 Indent(n1, "// scope has trivial outer context\n"); |
| 1167 } | 1158 } |
| 1168 if (is_strict(language_mode())) { | 1159 if (is_strict(language_mode())) { |
| 1169 Indent(n1, "// strict mode scope\n"); | 1160 Indent(n1, "// strict mode scope\n"); |
| 1170 } | 1161 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1184 } | 1175 } |
| 1185 if (num_heap_slots_ > 0) { | 1176 if (num_heap_slots_ > 0) { |
| 1186 Indent(n1, "// "); | 1177 Indent(n1, "// "); |
| 1187 PrintF("%d heap slots (including %d global slots)\n", num_heap_slots_, | 1178 PrintF("%d heap slots (including %d global slots)\n", num_heap_slots_, |
| 1188 num_global_slots_); | 1179 num_global_slots_); |
| 1189 } | 1180 } |
| 1190 | 1181 |
| 1191 // Print locals. | 1182 // Print locals. |
| 1192 if (function != nullptr) { | 1183 if (function != nullptr) { |
| 1193 Indent(n1, "// function var:\n"); | 1184 Indent(n1, "// function var:\n"); |
| 1194 PrintVar(n1, function->proxy()->var()); | 1185 PrintVar(n1, function); |
| 1195 } | 1186 } |
| 1196 | 1187 |
| 1197 if (is_declaration_scope()) { | 1188 if (is_declaration_scope()) { |
| 1198 bool printed_header = false; | 1189 bool printed_header = false; |
| 1199 ZoneList<Variable*>* temps = AsDeclarationScope()->temps(); | 1190 ZoneList<Variable*>* temps = AsDeclarationScope()->temps(); |
| 1200 for (int i = 0; i < temps->length(); i++) { | 1191 for (int i = 0; i < temps->length(); i++) { |
| 1201 if ((*temps)[i] != nullptr) { | 1192 if ((*temps)[i] != nullptr) { |
| 1202 if (!printed_header) { | 1193 if (!printed_header) { |
| 1203 printed_header = true; | 1194 printed_header = true; |
| 1204 Indent(n1, "// temporary vars:\n"); | 1195 Indent(n1, "// temporary vars:\n"); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1286 // this scope which introduces the same variable again, the resulting | 1277 // this scope which introduces the same variable again, the resulting |
| 1287 // variable remains the same.) | 1278 // variable remains the same.) |
| 1288 if (var != NULL) { | 1279 if (var != NULL) { |
| 1289 *binding_kind = BOUND; | 1280 *binding_kind = BOUND; |
| 1290 return var; | 1281 return var; |
| 1291 } | 1282 } |
| 1292 | 1283 |
| 1293 // We did not find a variable locally. Check against the function variable, if | 1284 // We did not find a variable locally. Check against the function variable, if |
| 1294 // any. | 1285 // any. |
| 1295 *binding_kind = UNBOUND; | 1286 *binding_kind = UNBOUND; |
| 1296 var = | 1287 var = is_function_scope() |
| 1297 is_function_scope() | 1288 ? AsDeclarationScope()->LookupFunctionVar(proxy->raw_name()) |
| 1298 ? AsDeclarationScope()->LookupFunctionVar(proxy->raw_name(), factory) | 1289 : nullptr; |
| 1299 : nullptr; | |
| 1300 if (var != NULL) { | 1290 if (var != NULL) { |
| 1301 *binding_kind = BOUND; | 1291 *binding_kind = BOUND; |
| 1302 } else if (outer_scope_ != nullptr && this != max_outer_scope) { | 1292 } else if (outer_scope_ != nullptr && this != max_outer_scope) { |
| 1303 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory, | 1293 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory, |
| 1304 max_outer_scope); | 1294 max_outer_scope); |
| 1305 if (*binding_kind == BOUND && is_function_scope()) { | 1295 if (*binding_kind == BOUND && is_function_scope()) { |
| 1306 var->ForceContextAllocation(); | 1296 var->ForceContextAllocation(); |
| 1307 } | 1297 } |
| 1308 } else { | 1298 } else { |
| 1309 DCHECK(is_script_scope() || this == max_outer_scope); | 1299 DCHECK(is_script_scope() || this == max_outer_scope); |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1690 AsDeclarationScope()->AllocateLocals(ast_value_factory); | 1680 AsDeclarationScope()->AllocateLocals(ast_value_factory); |
| 1691 } | 1681 } |
| 1692 } | 1682 } |
| 1693 | 1683 |
| 1694 void DeclarationScope::AllocateLocals(AstValueFactory* ast_value_factory) { | 1684 void DeclarationScope::AllocateLocals(AstValueFactory* ast_value_factory) { |
| 1695 // For now, function_ must be allocated at the very end. If it gets | 1685 // For now, function_ must be allocated at the very end. If it gets |
| 1696 // allocated in the context, it must be the last slot in the context, | 1686 // allocated in the context, it must be the last slot in the context, |
| 1697 // because of the current ScopeInfo implementation (see | 1687 // because of the current ScopeInfo implementation (see |
| 1698 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). | 1688 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). |
| 1699 if (function_ != nullptr) { | 1689 if (function_ != nullptr) { |
| 1700 AllocateNonParameterLocal(function_->proxy()->var(), ast_value_factory); | 1690 AllocateNonParameterLocal(function_, ast_value_factory); |
| 1701 } | 1691 } |
| 1702 | 1692 |
| 1703 if (rest_parameter_ != nullptr) { | 1693 if (rest_parameter_ != nullptr) { |
| 1704 AllocateNonParameterLocal(rest_parameter_, ast_value_factory); | 1694 AllocateNonParameterLocal(rest_parameter_, ast_value_factory); |
| 1705 } | 1695 } |
| 1706 | 1696 |
| 1707 if (new_target_ != nullptr && !MustAllocate(new_target_)) { | 1697 if (new_target_ != nullptr && !MustAllocate(new_target_)) { |
| 1708 new_target_ = nullptr; | 1698 new_target_ = nullptr; |
| 1709 } | 1699 } |
| 1710 | 1700 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1769 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) { | 1759 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) { |
| 1770 num_heap_slots_ = 0; | 1760 num_heap_slots_ = 0; |
| 1771 } | 1761 } |
| 1772 | 1762 |
| 1773 // Allocation done. | 1763 // Allocation done. |
| 1774 DCHECK(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 1764 DCHECK(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
| 1775 } | 1765 } |
| 1776 | 1766 |
| 1777 | 1767 |
| 1778 int Scope::StackLocalCount() const { | 1768 int Scope::StackLocalCount() const { |
| 1779 VariableDeclaration* function = | 1769 Variable* function = |
| 1780 is_function_scope() ? AsDeclarationScope()->function() : nullptr; | 1770 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; |
| 1781 return num_stack_slots() - | 1771 return num_stack_slots() - |
| 1782 (function != NULL && function->proxy()->var()->IsStackLocal() ? 1 : 0); | 1772 (function != nullptr && function->IsStackLocal() ? 1 : 0); |
| 1783 } | 1773 } |
| 1784 | 1774 |
| 1785 | 1775 |
| 1786 int Scope::ContextLocalCount() const { | 1776 int Scope::ContextLocalCount() const { |
| 1787 if (num_heap_slots() == 0) return 0; | 1777 if (num_heap_slots() == 0) return 0; |
| 1788 VariableDeclaration* function = | 1778 Variable* function = |
| 1789 is_function_scope() ? AsDeclarationScope()->function() : nullptr; | 1779 is_function_scope() ? AsDeclarationScope()->function_var() : nullptr; |
| 1790 bool is_function_var_in_context = | 1780 bool is_function_var_in_context = |
| 1791 function != NULL && function->proxy()->var()->IsContextSlot(); | 1781 function != nullptr && function->IsContextSlot(); |
| 1792 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1782 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
| 1793 (is_function_var_in_context ? 1 : 0); | 1783 (is_function_var_in_context ? 1 : 0); |
| 1794 } | 1784 } |
| 1795 | 1785 |
| 1796 | 1786 |
| 1797 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1787 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
| 1798 | 1788 |
| 1799 } // namespace internal | 1789 } // namespace internal |
| 1800 } // namespace v8 | 1790 } // namespace v8 |
| OLD | NEW |