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 |