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 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 this_function_ = | 469 this_function_ = |
| 470 Declare(zone(), this, ast_value_factory->this_function_string(), CONST, | 470 Declare(zone(), this, ast_value_factory->this_function_string(), CONST, |
| 471 Variable::NORMAL, kCreatedInitialized); | 471 Variable::NORMAL, kCreatedInitialized); |
| 472 } | 472 } |
| 473 } | 473 } |
| 474 | 474 |
| 475 Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name) { | 475 Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name) { |
| 476 DCHECK(is_function_scope()); | 476 DCHECK(is_function_scope()); |
| 477 DCHECK_NULL(function_); | 477 DCHECK_NULL(function_); |
| 478 VariableMode mode = is_strict(language_mode()) ? CONST : CONST_LEGACY; | 478 VariableMode mode = is_strict(language_mode()) ? CONST : CONST_LEGACY; |
| 479 function_ = new (zone()) | 479 bool preexists = variables_.Lookup(name); |
| 480 Variable(this, name, mode, Variable::NORMAL, kCreatedInitialized); | 480 if (preexists || calls_sloppy_eval()) { |
|
adamk
2016/08/24 18:15:49
This logic is pretty tricky (I find it trickier th
| |
| 481 function_ = new (zone()) | |
|
adamk
2016/08/24 20:22:48
Maybe we should just skip creating the function_ v
| |
| 482 Variable(this, name, mode, Variable::NORMAL, kCreatedInitialized); | |
| 483 if (!preexists) NonLocal(name, DYNAMIC); | |
| 484 } else { | |
| 485 function_ = variables_.Declare(zone(), this, name, mode, Variable::NORMAL, | |
| 486 kCreatedInitialized); | |
| 487 } | |
| 481 return function_; | 488 return function_; |
| 482 } | 489 } |
| 483 | 490 |
| 484 Scope* Scope::FinalizeBlockScope() { | 491 Scope* Scope::FinalizeBlockScope() { |
| 485 DCHECK(is_block_scope()); | 492 DCHECK(is_block_scope()); |
| 486 | 493 |
| 487 if (variables_.occupancy() > 0 || | 494 if (variables_.occupancy() > 0 || |
| 488 (is_declaration_scope() && calls_sloppy_eval())) { | 495 (is_declaration_scope() && calls_sloppy_eval())) { |
| 489 return this; | 496 return this; |
| 490 } | 497 } |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 611 int index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, | 618 int index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, |
| 612 &init_flag, &maybe_assigned_flag); | 619 &init_flag, &maybe_assigned_flag); |
| 613 if (index < 0) { | 620 if (index < 0) { |
| 614 location = VariableLocation::GLOBAL; | 621 location = VariableLocation::GLOBAL; |
| 615 index = ScopeInfo::ContextGlobalSlotIndex(scope_info_, name_handle, &mode, | 622 index = ScopeInfo::ContextGlobalSlotIndex(scope_info_, name_handle, &mode, |
| 616 &init_flag, &maybe_assigned_flag); | 623 &init_flag, &maybe_assigned_flag); |
| 617 } | 624 } |
| 618 if (index < 0) { | 625 if (index < 0) { |
| 619 // Check parameters. | 626 // Check parameters. |
| 620 index = scope_info_->ParameterIndex(*name_handle); | 627 index = scope_info_->ParameterIndex(*name_handle); |
| 621 if (index < 0) return NULL; | 628 if (index < 0) { |
| 629 index = scope_info_->FunctionContextSlotIndex(*name_handle, &mode); | |
| 630 if (index < 0) return nullptr; | |
| 631 Variable* var = AsDeclarationScope()->DeclareFunctionVar(name); | |
| 632 DCHECK_EQ(mode, var->mode()); | |
| 633 var->AllocateTo(VariableLocation::CONTEXT, index); | |
| 634 return variables_.Lookup(name); | |
| 635 } | |
| 622 | 636 |
| 623 mode = DYNAMIC; | 637 mode = DYNAMIC; |
| 624 location = VariableLocation::LOOKUP; | 638 location = VariableLocation::LOOKUP; |
| 625 init_flag = kCreatedInitialized; | 639 init_flag = kCreatedInitialized; |
| 626 // Be conservative and flag parameters as maybe assigned. Better information | 640 // Be conservative and flag parameters as maybe assigned. Better information |
| 627 // would require ScopeInfo to serialize the maybe_assigned bit also for | 641 // would require ScopeInfo to serialize the maybe_assigned bit also for |
| 628 // parameters. | 642 // parameters. |
| 629 maybe_assigned_flag = kMaybeAssigned; | 643 maybe_assigned_flag = kMaybeAssigned; |
| 630 } else { | 644 } else { |
| 631 DCHECK(location != VariableLocation::GLOBAL || | 645 DCHECK(location != VariableLocation::GLOBAL || |
| 632 (is_script_scope() && IsDeclaredVariableMode(mode) && | 646 (is_script_scope() && IsDeclaredVariableMode(mode) && |
| 633 !IsLexicalVariableMode(mode))); | 647 !IsLexicalVariableMode(mode))); |
| 634 } | 648 } |
| 635 | 649 |
| 636 Variable::Kind kind = Variable::NORMAL; | 650 Variable::Kind kind = Variable::NORMAL; |
| 637 if (location == VariableLocation::CONTEXT && | 651 if (location == VariableLocation::CONTEXT && |
| 638 index == scope_info_->ReceiverContextSlotIndex()) { | 652 index == scope_info_->ReceiverContextSlotIndex()) { |
| 639 kind = Variable::THIS; | 653 kind = Variable::THIS; |
| 640 } | 654 } |
| 641 // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and | 655 // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and |
| 642 // ARGUMENTS bindings as their corresponding Variable::Kind. | 656 // ARGUMENTS bindings as their corresponding Variable::Kind. |
| 643 | 657 |
| 644 Variable* var = variables_.Declare(zone(), this, name, mode, kind, init_flag, | 658 Variable* var = variables_.Declare(zone(), this, name, mode, kind, init_flag, |
| 645 maybe_assigned_flag); | 659 maybe_assigned_flag); |
| 646 var->AllocateTo(location, index); | 660 var->AllocateTo(location, index); |
| 647 return var; | 661 return var; |
| 648 } | 662 } |
| 649 | 663 |
| 650 Variable* DeclarationScope::LookupFunctionVar(const AstRawString* name) { | |
| 651 if (function_ != nullptr && function_->raw_name() == name) { | |
| 652 return function_; | |
| 653 } else if (!scope_info_.is_null()) { | |
| 654 // If we are backed by a scope info, try to lookup the variable there. | |
| 655 VariableMode mode; | |
| 656 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); | |
| 657 if (index < 0) return nullptr; | |
| 658 Variable* var = DeclareFunctionVar(name); | |
| 659 DCHECK_EQ(mode, var->mode()); | |
| 660 var->AllocateTo(VariableLocation::CONTEXT, index); | |
| 661 return var; | |
| 662 } else { | |
| 663 return nullptr; | |
| 664 } | |
| 665 } | |
| 666 | |
| 667 | |
| 668 Variable* Scope::Lookup(const AstRawString* name) { | 664 Variable* Scope::Lookup(const AstRawString* name) { |
| 669 for (Scope* scope = this; | 665 for (Scope* scope = this; |
| 670 scope != NULL; | 666 scope != NULL; |
| 671 scope = scope->outer_scope()) { | 667 scope = scope->outer_scope()) { |
| 672 Variable* var = scope->LookupLocal(name); | 668 Variable* var = scope->LookupLocal(name); |
| 673 if (var != NULL) return var; | 669 if (var != NULL) return var; |
| 674 } | 670 } |
| 675 return NULL; | 671 return NULL; |
| 676 } | 672 } |
| 677 | 673 |
| (...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1238 } | 1234 } |
| 1239 | 1235 |
| 1240 // Try to find the variable in this scope. | 1236 // Try to find the variable in this scope. |
| 1241 Variable* var = LookupLocal(proxy->raw_name()); | 1237 Variable* var = LookupLocal(proxy->raw_name()); |
| 1242 | 1238 |
| 1243 // We found a variable and we are done. (Even if there is an 'eval' in this | 1239 // We found a variable and we are done. (Even if there is an 'eval' in this |
| 1244 // scope which introduces the same variable again, the resulting variable | 1240 // scope which introduces the same variable again, the resulting variable |
| 1245 // remains the same.) | 1241 // remains the same.) |
| 1246 if (var != nullptr) return var; | 1242 if (var != nullptr) return var; |
| 1247 | 1243 |
| 1248 // We did not find a variable locally. Check against the function variable, if | |
| 1249 // any. | |
| 1250 if (is_function_scope()) { | |
| 1251 var = AsDeclarationScope()->LookupFunctionVar(proxy->raw_name()); | |
| 1252 if (var != nullptr) { | |
| 1253 if (calls_sloppy_eval()) return NonLocal(proxy->raw_name(), DYNAMIC); | |
| 1254 return var; | |
| 1255 } | |
| 1256 } | |
| 1257 | |
| 1258 if (outer_scope_ == outer_scope_end) { | 1244 if (outer_scope_ == outer_scope_end) { |
| 1259 if (!declare_free) return nullptr; | 1245 if (!declare_free) return nullptr; |
| 1260 DCHECK(is_script_scope()); | 1246 DCHECK(is_script_scope()); |
| 1261 // No binding has been found. Declare a variable on the global object. | 1247 // No binding has been found. Declare a variable on the global object. |
| 1262 return AsDeclarationScope()->DeclareDynamicGlobal(proxy->raw_name(), | 1248 return AsDeclarationScope()->DeclareDynamicGlobal(proxy->raw_name(), |
| 1263 Variable::NORMAL); | 1249 Variable::NORMAL); |
| 1264 } | 1250 } |
| 1265 | 1251 |
| 1266 DCHECK(!is_script_scope()); | 1252 DCHECK(!is_script_scope()); |
| 1267 | 1253 |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1673 function != nullptr && function->IsContextSlot(); | 1659 function != nullptr && function->IsContextSlot(); |
| 1674 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - | 1660 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - num_global_slots() - |
| 1675 (is_function_var_in_context ? 1 : 0); | 1661 (is_function_var_in_context ? 1 : 0); |
| 1676 } | 1662 } |
| 1677 | 1663 |
| 1678 | 1664 |
| 1679 int Scope::ContextGlobalCount() const { return num_global_slots(); } | 1665 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
| 1680 | 1666 |
| 1681 } // namespace internal | 1667 } // namespace internal |
| 1682 } // namespace v8 | 1668 } // namespace v8 |
| OLD | NEW |