| 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/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/messages.h" | 9 #include "src/messages.h" |
| 10 #include "src/parser.h" | 10 #include "src/parser.h" |
| 11 #include "src/scopeinfo.h" | 11 #include "src/scopeinfo.h" |
| 12 #include "src/scopes.h" | 12 #include "src/scopes.h" |
| 13 | 13 |
| 14 namespace v8 { | 14 namespace v8 { |
| 15 namespace internal { | 15 namespace internal { |
| 16 | 16 |
| 17 // TODO(ishell): remove this once compiler support is landed. |
| 18 bool enable_context_globals = false; |
| 19 |
| 17 // ---------------------------------------------------------------------------- | 20 // ---------------------------------------------------------------------------- |
| 18 // Implementation of LocalsMap | 21 // Implementation of LocalsMap |
| 19 // | 22 // |
| 20 // Note: We are storing the handle locations as key values in the hash map. | 23 // Note: We are storing the handle locations as key values in the hash map. |
| 21 // When inserting a new variable via Declare(), we rely on the fact that | 24 // When inserting a new variable via Declare(), we rely on the fact that |
| 22 // the handle location remains alive for the duration of that variable | 25 // the handle location remains alive for the duration of that variable |
| 23 // use. Because a Variable holding a handle with the same location exists | 26 // use. Because a Variable holding a handle with the same location exists |
| 24 // this is ensured. | 27 // this is ensured. |
| 25 | 28 |
| 26 VariableMap::VariableMap(Zone* zone) | 29 VariableMap::VariableMap(Zone* zone) |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 language_mode_ = outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY; | 174 language_mode_ = outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY; |
| 172 outer_scope_calls_sloppy_eval_ = false; | 175 outer_scope_calls_sloppy_eval_ = false; |
| 173 inner_scope_calls_eval_ = false; | 176 inner_scope_calls_eval_ = false; |
| 174 inner_scope_uses_arguments_ = false; | 177 inner_scope_uses_arguments_ = false; |
| 175 force_eager_compilation_ = false; | 178 force_eager_compilation_ = false; |
| 176 force_context_allocation_ = (outer_scope != NULL && !is_function_scope()) | 179 force_context_allocation_ = (outer_scope != NULL && !is_function_scope()) |
| 177 ? outer_scope->has_forced_context_allocation() : false; | 180 ? outer_scope->has_forced_context_allocation() : false; |
| 178 num_var_or_const_ = 0; | 181 num_var_or_const_ = 0; |
| 179 num_stack_slots_ = 0; | 182 num_stack_slots_ = 0; |
| 180 num_heap_slots_ = 0; | 183 num_heap_slots_ = 0; |
| 184 num_global_slots_ = 0; |
| 181 num_modules_ = 0; | 185 num_modules_ = 0; |
| 182 module_var_ = NULL, | 186 module_var_ = NULL, |
| 183 rest_parameter_ = NULL; | 187 rest_parameter_ = NULL; |
| 184 rest_index_ = -1; | 188 rest_index_ = -1; |
| 185 scope_info_ = scope_info; | 189 scope_info_ = scope_info; |
| 186 start_position_ = RelocInfo::kNoPosition; | 190 start_position_ = RelocInfo::kNoPosition; |
| 187 end_position_ = RelocInfo::kNoPosition; | 191 end_position_ = RelocInfo::kNoPosition; |
| 188 if (!scope_info.is_null()) { | 192 if (!scope_info.is_null()) { |
| 189 scope_calls_eval_ = scope_info->CallsEval(); | 193 scope_calls_eval_ = scope_info->CallsEval(); |
| 190 language_mode_ = scope_info->language_mode(); | 194 language_mode_ = scope_info->language_mode(); |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 Handle<String> name_handle = name->string(); | 385 Handle<String> name_handle = name->string(); |
| 382 // The Scope is backed up by ScopeInfo. This means it cannot operate in a | 386 // The Scope is backed up by ScopeInfo. This means it cannot operate in a |
| 383 // heap-independent mode, and all strings must be internalized immediately. So | 387 // heap-independent mode, and all strings must be internalized immediately. So |
| 384 // it's ok to get the Handle<String> here. | 388 // it's ok to get the Handle<String> here. |
| 385 // If we have a serialized scope info, we might find the variable there. | 389 // If we have a serialized scope info, we might find the variable there. |
| 386 // There should be no local slot with the given name. | 390 // There should be no local slot with the given name. |
| 387 DCHECK(scope_info_->StackSlotIndex(*name_handle) < 0 || is_block_scope()); | 391 DCHECK(scope_info_->StackSlotIndex(*name_handle) < 0 || is_block_scope()); |
| 388 | 392 |
| 389 // Check context slot lookup. | 393 // Check context slot lookup. |
| 390 VariableMode mode; | 394 VariableMode mode; |
| 391 Variable::Location location = Variable::CONTEXT; | 395 VariableLocation location; |
| 392 InitializationFlag init_flag; | 396 InitializationFlag init_flag; |
| 393 MaybeAssignedFlag maybe_assigned_flag; | 397 MaybeAssignedFlag maybe_assigned_flag; |
| 394 int index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, | 398 int index = |
| 395 &init_flag, &maybe_assigned_flag); | 399 ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, &location, |
| 400 &init_flag, &maybe_assigned_flag); |
| 396 if (index < 0) { | 401 if (index < 0) { |
| 397 // Check parameters. | 402 // Check parameters. |
| 398 index = scope_info_->ParameterIndex(*name_handle); | 403 index = scope_info_->ParameterIndex(*name_handle); |
| 399 if (index < 0) return NULL; | 404 if (index < 0) return NULL; |
| 400 | 405 |
| 401 mode = DYNAMIC; | 406 mode = DYNAMIC; |
| 402 location = Variable::LOOKUP; | 407 location = VariableLocation::LOOKUP; |
| 403 init_flag = kCreatedInitialized; | 408 init_flag = kCreatedInitialized; |
| 404 // Be conservative and flag parameters as maybe assigned. Better information | 409 // Be conservative and flag parameters as maybe assigned. Better information |
| 405 // would require ScopeInfo to serialize the maybe_assigned bit also for | 410 // would require ScopeInfo to serialize the maybe_assigned bit also for |
| 406 // parameters. | 411 // parameters. |
| 407 maybe_assigned_flag = kMaybeAssigned; | 412 maybe_assigned_flag = kMaybeAssigned; |
| 413 } else { |
| 414 DCHECK(location != VariableLocation::GLOBAL || |
| 415 (is_script_scope() && IsDeclaredVariableMode(mode) && |
| 416 !IsLexicalVariableMode(mode))); |
| 408 } | 417 } |
| 409 | 418 |
| 410 Variable::Kind kind = Variable::NORMAL; | 419 Variable::Kind kind = Variable::NORMAL; |
| 411 if (location == Variable::CONTEXT && | 420 if (location == VariableLocation::CONTEXT && |
| 412 index == scope_info_->ReceiverContextSlotIndex()) { | 421 index == scope_info_->ReceiverContextSlotIndex()) { |
| 413 kind = Variable::THIS; | 422 kind = Variable::THIS; |
| 414 } | 423 } |
| 415 // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and | 424 // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and |
| 416 // ARGUMENTS bindings as their corresponding Variable::Kind. | 425 // ARGUMENTS bindings as their corresponding Variable::Kind. |
| 417 | 426 |
| 418 Variable* var = variables_.Declare(this, name, mode, kind, init_flag, | 427 Variable* var = variables_.Declare(this, name, mode, kind, init_flag, |
| 419 maybe_assigned_flag); | 428 maybe_assigned_flag); |
| 420 var->AllocateTo(location, index); | 429 var->AllocateTo(location, index); |
| 421 return var; | 430 return var; |
| 422 } | 431 } |
| 423 | 432 |
| 424 | 433 |
| 425 Variable* Scope::LookupFunctionVar(const AstRawString* name, | 434 Variable* Scope::LookupFunctionVar(const AstRawString* name, |
| 426 AstNodeFactory* factory) { | 435 AstNodeFactory* factory) { |
| 427 if (function_ != NULL && function_->proxy()->raw_name() == name) { | 436 if (function_ != NULL && function_->proxy()->raw_name() == name) { |
| 428 return function_->proxy()->var(); | 437 return function_->proxy()->var(); |
| 429 } else if (!scope_info_.is_null()) { | 438 } else if (!scope_info_.is_null()) { |
| 430 // If we are backed by a scope info, try to lookup the variable there. | 439 // If we are backed by a scope info, try to lookup the variable there. |
| 431 VariableMode mode; | 440 VariableMode mode; |
| 432 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); | 441 int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); |
| 433 if (index < 0) return NULL; | 442 if (index < 0) return NULL; |
| 434 Variable* var = new (zone()) | 443 Variable* var = new (zone()) |
| 435 Variable(this, name, mode, Variable::NORMAL, kCreatedInitialized); | 444 Variable(this, name, mode, Variable::NORMAL, kCreatedInitialized); |
| 436 VariableProxy* proxy = factory->NewVariableProxy(var); | 445 VariableProxy* proxy = factory->NewVariableProxy(var); |
| 437 VariableDeclaration* declaration = factory->NewVariableDeclaration( | 446 VariableDeclaration* declaration = factory->NewVariableDeclaration( |
| 438 proxy, mode, this, RelocInfo::kNoPosition); | 447 proxy, mode, this, RelocInfo::kNoPosition); |
| 439 DeclareFunctionVar(declaration); | 448 DeclareFunctionVar(declaration); |
| 440 var->AllocateTo(Variable::CONTEXT, index); | 449 var->AllocateTo(VariableLocation::CONTEXT, index); |
| 441 return var; | 450 return var; |
| 442 } else { | 451 } else { |
| 443 return NULL; | 452 return NULL; |
| 444 } | 453 } |
| 445 } | 454 } |
| 446 | 455 |
| 447 | 456 |
| 448 Variable* Scope::Lookup(const AstRawString* name) { | 457 Variable* Scope::Lookup(const AstRawString* name) { |
| 449 for (Scope* scope = this; | 458 for (Scope* scope = this; |
| 450 scope != NULL; | 459 scope != NULL; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 } | 605 } |
| 597 | 606 |
| 598 private: | 607 private: |
| 599 Variable* var_; | 608 Variable* var_; |
| 600 int order_; | 609 int order_; |
| 601 }; | 610 }; |
| 602 | 611 |
| 603 | 612 |
| 604 void Scope::CollectStackAndContextLocals( | 613 void Scope::CollectStackAndContextLocals( |
| 605 ZoneList<Variable*>* stack_locals, ZoneList<Variable*>* context_locals, | 614 ZoneList<Variable*>* stack_locals, ZoneList<Variable*>* context_locals, |
| 615 ZoneList<Variable*>* context_globals, |
| 606 ZoneList<Variable*>* strong_mode_free_variables) { | 616 ZoneList<Variable*>* strong_mode_free_variables) { |
| 607 DCHECK(stack_locals != NULL); | 617 DCHECK(stack_locals != NULL); |
| 608 DCHECK(context_locals != NULL); | 618 DCHECK(context_locals != NULL); |
| 619 DCHECK(context_globals != NULL); |
| 609 | 620 |
| 610 // Collect internals which are always allocated on the heap. | 621 // Collect internals which are always allocated on the heap. |
| 611 for (int i = 0; i < internals_.length(); i++) { | 622 for (int i = 0; i < internals_.length(); i++) { |
| 612 Variable* var = internals_[i]; | 623 Variable* var = internals_[i]; |
| 613 if (var->is_used()) { | 624 if (var->is_used()) { |
| 614 DCHECK(var->IsContextSlot()); | 625 DCHECK(var->IsContextSlot()); |
| 615 context_locals->Add(var, zone()); | 626 context_locals->Add(var, zone()); |
| 616 } | 627 } |
| 617 } | 628 } |
| 618 | 629 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 647 } | 658 } |
| 648 } | 659 } |
| 649 vars.Sort(VarAndOrder::Compare); | 660 vars.Sort(VarAndOrder::Compare); |
| 650 int var_count = vars.length(); | 661 int var_count = vars.length(); |
| 651 for (int i = 0; i < var_count; i++) { | 662 for (int i = 0; i < var_count; i++) { |
| 652 Variable* var = vars[i].var(); | 663 Variable* var = vars[i].var(); |
| 653 if (var->IsStackLocal()) { | 664 if (var->IsStackLocal()) { |
| 654 stack_locals->Add(var, zone()); | 665 stack_locals->Add(var, zone()); |
| 655 } else if (var->IsContextSlot()) { | 666 } else if (var->IsContextSlot()) { |
| 656 context_locals->Add(var, zone()); | 667 context_locals->Add(var, zone()); |
| 668 } else if (var->IsGlobalSlot()) { |
| 669 context_globals->Add(var, zone()); |
| 657 } | 670 } |
| 658 } | 671 } |
| 659 } | 672 } |
| 660 | 673 |
| 661 | 674 |
| 662 bool Scope::AllocateVariables(ParseInfo* info, AstNodeFactory* factory) { | 675 bool Scope::AllocateVariables(ParseInfo* info, AstNodeFactory* factory) { |
| 663 // 1) Propagate scope information. | 676 // 1) Propagate scope information. |
| 664 bool outer_scope_calls_sloppy_eval = false; | 677 bool outer_scope_calls_sloppy_eval = false; |
| 665 if (outer_scope_ != NULL) { | 678 if (outer_scope_ != NULL) { |
| 666 outer_scope_calls_sloppy_eval = | 679 outer_scope_calls_sloppy_eval = |
| (...skipping 19 matching lines...) Expand all Loading... |
| 686 | 699 |
| 687 | 700 |
| 688 bool Scope::HasTrivialContext() const { | 701 bool Scope::HasTrivialContext() const { |
| 689 // A function scope has a trivial context if it always is the global | 702 // A function scope has a trivial context if it always is the global |
| 690 // context. We iteratively scan out the context chain to see if | 703 // context. We iteratively scan out the context chain to see if |
| 691 // there is anything that makes this scope non-trivial; otherwise we | 704 // there is anything that makes this scope non-trivial; otherwise we |
| 692 // return true. | 705 // return true. |
| 693 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) { | 706 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) { |
| 694 if (scope->is_eval_scope()) return false; | 707 if (scope->is_eval_scope()) return false; |
| 695 if (scope->scope_inside_with_) return false; | 708 if (scope->scope_inside_with_) return false; |
| 696 if (scope->num_heap_slots_ > 0) return false; | 709 if (scope->ContextLocalCount() > 0) return false; |
| 697 } | 710 } |
| 698 return true; | 711 return true; |
| 699 } | 712 } |
| 700 | 713 |
| 701 | 714 |
| 702 bool Scope::HasTrivialOuterContext() const { | 715 bool Scope::HasTrivialOuterContext() const { |
| 703 Scope* outer = outer_scope_; | 716 Scope* outer = outer_scope_; |
| 704 if (outer == NULL) return true; | 717 if (outer == NULL) return true; |
| 705 // Note that the outer context may be trivial in general, but the current | 718 // Note that the outer context may be trivial in general, but the current |
| 706 // scope may be inside a 'with' statement in which case the outer context | 719 // scope may be inside a 'with' statement in which case the outer context |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 821 } | 834 } |
| 822 | 835 |
| 823 | 836 |
| 824 static void PrintName(const AstRawString* name) { | 837 static void PrintName(const AstRawString* name) { |
| 825 PrintF("%.*s", name->length(), name->raw_data()); | 838 PrintF("%.*s", name->length(), name->raw_data()); |
| 826 } | 839 } |
| 827 | 840 |
| 828 | 841 |
| 829 static void PrintLocation(Variable* var) { | 842 static void PrintLocation(Variable* var) { |
| 830 switch (var->location()) { | 843 switch (var->location()) { |
| 831 case Variable::UNALLOCATED: | 844 case VariableLocation::UNALLOCATED: |
| 832 break; | 845 break; |
| 833 case Variable::PARAMETER: | 846 case VariableLocation::PARAMETER: |
| 834 PrintF("parameter[%d]", var->index()); | 847 PrintF("parameter[%d]", var->index()); |
| 835 break; | 848 break; |
| 836 case Variable::LOCAL: | 849 case VariableLocation::LOCAL: |
| 837 PrintF("local[%d]", var->index()); | 850 PrintF("local[%d]", var->index()); |
| 838 break; | 851 break; |
| 839 case Variable::CONTEXT: | 852 case VariableLocation::CONTEXT: |
| 840 PrintF("context[%d]", var->index()); | 853 PrintF("context[%d]", var->index()); |
| 841 break; | 854 break; |
| 842 case Variable::LOOKUP: | 855 case VariableLocation::GLOBAL: |
| 856 PrintF("global[%d]", var->index()); |
| 857 break; |
| 858 case VariableLocation::LOOKUP: |
| 843 PrintF("lookup"); | 859 PrintF("lookup"); |
| 844 break; | 860 break; |
| 845 } | 861 } |
| 846 } | 862 } |
| 847 | 863 |
| 848 | 864 |
| 849 static void PrintVar(int indent, Variable* var) { | 865 static void PrintVar(int indent, Variable* var) { |
| 850 if (var->is_used() || !var->IsUnallocated()) { | 866 if (var->is_used() || !var->IsUnallocated()) { |
| 851 Indent(indent, Variable::Mode2String(var->mode())); | 867 Indent(indent, Variable::Mode2String(var->mode())); |
| 852 PrintF(" "); | 868 PrintF(" "); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 864 PrintF("maybe assigned"); | 880 PrintF("maybe assigned"); |
| 865 } | 881 } |
| 866 PrintF("\n"); | 882 PrintF("\n"); |
| 867 } | 883 } |
| 868 } | 884 } |
| 869 | 885 |
| 870 | 886 |
| 871 static void PrintMap(int indent, VariableMap* map) { | 887 static void PrintMap(int indent, VariableMap* map) { |
| 872 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { | 888 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { |
| 873 Variable* var = reinterpret_cast<Variable*>(p->value); | 889 Variable* var = reinterpret_cast<Variable*>(p->value); |
| 874 PrintVar(indent, var); | 890 if (var == NULL) { |
| 891 Indent(indent, "<?>\n"); |
| 892 } else { |
| 893 PrintVar(indent, var); |
| 894 } |
| 875 } | 895 } |
| 876 } | 896 } |
| 877 | 897 |
| 878 | 898 |
| 879 void Scope::Print(int n) { | 899 void Scope::Print(int n) { |
| 880 int n0 = (n > 0 ? n : 0); | 900 int n0 = (n > 0 ? n : 0); |
| 881 int n1 = n0 + 2; // indentation | 901 int n1 = n0 + 2; // indentation |
| 882 | 902 |
| 883 // Print header. | 903 // Print header. |
| 884 Indent(n0, Header(scope_type_)); | 904 Indent(n0, Header(scope_type_)); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 921 if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n"); | 941 if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n"); |
| 922 if (scope_uses_super_property_) | 942 if (scope_uses_super_property_) |
| 923 Indent(n1, "// scope uses 'super' property\n"); | 943 Indent(n1, "// scope uses 'super' property\n"); |
| 924 if (inner_scope_uses_arguments_) { | 944 if (inner_scope_uses_arguments_) { |
| 925 Indent(n1, "// inner scope uses 'arguments'\n"); | 945 Indent(n1, "// inner scope uses 'arguments'\n"); |
| 926 } | 946 } |
| 927 if (outer_scope_calls_sloppy_eval_) { | 947 if (outer_scope_calls_sloppy_eval_) { |
| 928 Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); | 948 Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); |
| 929 } | 949 } |
| 930 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); | 950 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); |
| 931 if (num_stack_slots_ > 0) { Indent(n1, "// "); | 951 if (num_stack_slots_ > 0) { |
| 932 PrintF("%d stack slots\n", num_stack_slots_); } | 952 Indent(n1, "// "); |
| 933 if (num_heap_slots_ > 0) { Indent(n1, "// "); | 953 PrintF("%d stack slots\n", num_stack_slots_); |
| 934 PrintF("%d heap slots\n", num_heap_slots_); } | 954 } |
| 955 if (num_heap_slots_ > 0) { |
| 956 Indent(n1, "// "); |
| 957 PrintF("%d heap slots (including %d global slots)\n", num_heap_slots_, |
| 958 num_global_slots_); |
| 959 } |
| 935 | 960 |
| 936 // Print locals. | 961 // Print locals. |
| 937 if (function_ != NULL) { | 962 if (function_ != NULL) { |
| 938 Indent(n1, "// function var:\n"); | 963 Indent(n1, "// function var:\n"); |
| 939 PrintVar(n1, function_->proxy()->var()); | 964 PrintVar(n1, function_->proxy()->var()); |
| 940 } | 965 } |
| 941 | 966 |
| 942 if (temps_.length() > 0) { | 967 if (temps_.length() > 0) { |
| 943 Indent(n1, "// temporary vars:\n"); | 968 Indent(n1, "// temporary vars:\n"); |
| 944 for (int i = 0; i < temps_.length(); i++) { | 969 for (int i = 0; i < temps_.length(); i++) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 if (var == NULL) { | 1010 if (var == NULL) { |
| 986 // Declare a new non-local. | 1011 // Declare a new non-local. |
| 987 InitializationFlag init_flag = (mode == VAR) | 1012 InitializationFlag init_flag = (mode == VAR) |
| 988 ? kCreatedInitialized : kNeedsInitialization; | 1013 ? kCreatedInitialized : kNeedsInitialization; |
| 989 var = map->Declare(NULL, | 1014 var = map->Declare(NULL, |
| 990 name, | 1015 name, |
| 991 mode, | 1016 mode, |
| 992 Variable::NORMAL, | 1017 Variable::NORMAL, |
| 993 init_flag); | 1018 init_flag); |
| 994 // Allocate it by giving it a dynamic lookup. | 1019 // Allocate it by giving it a dynamic lookup. |
| 995 var->AllocateTo(Variable::LOOKUP, -1); | 1020 var->AllocateTo(VariableLocation::LOOKUP, -1); |
| 996 } | 1021 } |
| 997 return var; | 1022 return var; |
| 998 } | 1023 } |
| 999 | 1024 |
| 1000 | 1025 |
| 1001 Variable* Scope::LookupRecursive(VariableProxy* proxy, | 1026 Variable* Scope::LookupRecursive(VariableProxy* proxy, |
| 1002 BindingKind* binding_kind, | 1027 BindingKind* binding_kind, |
| 1003 AstNodeFactory* factory) { | 1028 AstNodeFactory* factory) { |
| 1004 DCHECK(binding_kind != NULL); | 1029 DCHECK(binding_kind != NULL); |
| 1005 if (already_resolved() && is_with_scope()) { | 1030 if (already_resolved() && is_with_scope()) { |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1336 } | 1361 } |
| 1337 } | 1362 } |
| 1338 return false; | 1363 return false; |
| 1339 } | 1364 } |
| 1340 | 1365 |
| 1341 | 1366 |
| 1342 void Scope::AllocateStackSlot(Variable* var) { | 1367 void Scope::AllocateStackSlot(Variable* var) { |
| 1343 if (is_block_scope()) { | 1368 if (is_block_scope()) { |
| 1344 DeclarationScope()->AllocateStackSlot(var); | 1369 DeclarationScope()->AllocateStackSlot(var); |
| 1345 } else { | 1370 } else { |
| 1346 var->AllocateTo(Variable::LOCAL, num_stack_slots_++); | 1371 var->AllocateTo(VariableLocation::LOCAL, num_stack_slots_++); |
| 1347 } | 1372 } |
| 1348 } | 1373 } |
| 1349 | 1374 |
| 1350 | 1375 |
| 1351 void Scope::AllocateHeapSlot(Variable* var) { | 1376 void Scope::AllocateHeapSlot(Variable* var) { |
| 1352 var->AllocateTo(Variable::CONTEXT, num_heap_slots_++); | 1377 var->AllocateTo(VariableLocation::CONTEXT, num_heap_slots_++); |
| 1353 } | 1378 } |
| 1354 | 1379 |
| 1355 | 1380 |
| 1356 void Scope::AllocateParameterLocals(Isolate* isolate) { | 1381 void Scope::AllocateParameterLocals(Isolate* isolate) { |
| 1357 DCHECK(is_function_scope()); | 1382 DCHECK(is_function_scope()); |
| 1358 Variable* arguments = LookupLocal(ast_value_factory_->arguments_string()); | 1383 Variable* arguments = LookupLocal(ast_value_factory_->arguments_string()); |
| 1359 // Functions have 'arguments' declared implicitly in all non arrow functions. | 1384 // Functions have 'arguments' declared implicitly in all non arrow functions. |
| 1360 DCHECK(arguments != nullptr || is_arrow_scope()); | 1385 DCHECK(arguments != nullptr || is_arrow_scope()); |
| 1361 | 1386 |
| 1362 bool uses_sloppy_arguments = false; | 1387 bool uses_sloppy_arguments = false; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1407 void Scope::AllocateParameter(Variable* var, int index) { | 1432 void Scope::AllocateParameter(Variable* var, int index) { |
| 1408 if (MustAllocate(var)) { | 1433 if (MustAllocate(var)) { |
| 1409 if (MustAllocateInContext(var)) { | 1434 if (MustAllocateInContext(var)) { |
| 1410 DCHECK(var->IsUnallocated() || var->IsContextSlot()); | 1435 DCHECK(var->IsUnallocated() || var->IsContextSlot()); |
| 1411 if (var->IsUnallocated()) { | 1436 if (var->IsUnallocated()) { |
| 1412 AllocateHeapSlot(var); | 1437 AllocateHeapSlot(var); |
| 1413 } | 1438 } |
| 1414 } else { | 1439 } else { |
| 1415 DCHECK(var->IsUnallocated() || var->IsParameter()); | 1440 DCHECK(var->IsUnallocated() || var->IsParameter()); |
| 1416 if (var->IsUnallocated()) { | 1441 if (var->IsUnallocated()) { |
| 1417 var->AllocateTo(Variable::PARAMETER, index); | 1442 var->AllocateTo(VariableLocation::PARAMETER, index); |
| 1418 } | 1443 } |
| 1419 } | 1444 } |
| 1445 } else { |
| 1446 DCHECK(!var->IsGlobalSlot()); |
| 1420 } | 1447 } |
| 1421 } | 1448 } |
| 1422 | 1449 |
| 1423 | 1450 |
| 1424 void Scope::AllocateReceiver() { | 1451 void Scope::AllocateReceiver() { |
| 1425 DCHECK_NOT_NULL(receiver()); | 1452 DCHECK_NOT_NULL(receiver()); |
| 1426 DCHECK_EQ(receiver()->scope(), this); | 1453 DCHECK_EQ(receiver()->scope(), this); |
| 1427 | 1454 |
| 1428 if (has_forced_context_allocation()) { | 1455 if (has_forced_context_allocation()) { |
| 1429 // Force context allocation of the receiver. | 1456 // Force context allocation of the receiver. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1440 if (var->IsUnallocated() && MustAllocate(var)) { | 1467 if (var->IsUnallocated() && MustAllocate(var)) { |
| 1441 if (MustAllocateInContext(var)) { | 1468 if (MustAllocateInContext(var)) { |
| 1442 AllocateHeapSlot(var); | 1469 AllocateHeapSlot(var); |
| 1443 } else { | 1470 } else { |
| 1444 AllocateStackSlot(var); | 1471 AllocateStackSlot(var); |
| 1445 } | 1472 } |
| 1446 } | 1473 } |
| 1447 } | 1474 } |
| 1448 | 1475 |
| 1449 | 1476 |
| 1450 void Scope::AllocateNonParameterLocals(Isolate* isolate) { | 1477 void Scope::AllocateDeclaredGlobal(Isolate* isolate, Variable* var) { |
| 1478 DCHECK(var->scope() == this); |
| 1479 DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) || |
| 1480 !var->IsStackLocal()); |
| 1481 if (var->IsUnallocated() && var->IsStaticGlobalObjectProperty()) { |
| 1482 DCHECK_EQ(-1, var->index()); |
| 1483 DCHECK(var->name()->IsString()); |
| 1484 var->AllocateTo(VariableLocation::GLOBAL, num_heap_slots_); |
| 1485 num_global_slots_++; |
| 1486 // Each global variable occupies two slots in the context: for reads |
| 1487 // and writes. |
| 1488 num_heap_slots_ += 2; |
| 1489 } |
| 1490 } |
| 1491 |
| 1492 |
| 1493 void Scope::AllocateNonParameterLocalsAndDeclaredGlobals(Isolate* isolate) { |
| 1451 // All variables that have no rewrite yet are non-parameter locals. | 1494 // All variables that have no rewrite yet are non-parameter locals. |
| 1452 for (int i = 0; i < temps_.length(); i++) { | 1495 for (int i = 0; i < temps_.length(); i++) { |
| 1453 AllocateNonParameterLocal(isolate, temps_[i]); | 1496 AllocateNonParameterLocal(isolate, temps_[i]); |
| 1454 } | 1497 } |
| 1455 | 1498 |
| 1456 for (int i = 0; i < internals_.length(); i++) { | 1499 for (int i = 0; i < internals_.length(); i++) { |
| 1457 AllocateNonParameterLocal(isolate, internals_[i]); | 1500 AllocateNonParameterLocal(isolate, internals_[i]); |
| 1458 } | 1501 } |
| 1459 | 1502 |
| 1460 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); | 1503 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); |
| 1461 for (VariableMap::Entry* p = variables_.Start(); | 1504 for (VariableMap::Entry* p = variables_.Start(); |
| 1462 p != NULL; | 1505 p != NULL; |
| 1463 p = variables_.Next(p)) { | 1506 p = variables_.Next(p)) { |
| 1464 Variable* var = reinterpret_cast<Variable*>(p->value); | 1507 Variable* var = reinterpret_cast<Variable*>(p->value); |
| 1465 vars.Add(VarAndOrder(var, p->order), zone()); | 1508 vars.Add(VarAndOrder(var, p->order), zone()); |
| 1466 } | 1509 } |
| 1467 vars.Sort(VarAndOrder::Compare); | 1510 vars.Sort(VarAndOrder::Compare); |
| 1468 int var_count = vars.length(); | 1511 int var_count = vars.length(); |
| 1469 for (int i = 0; i < var_count; i++) { | 1512 for (int i = 0; i < var_count; i++) { |
| 1470 AllocateNonParameterLocal(isolate, vars[i].var()); | 1513 AllocateNonParameterLocal(isolate, vars[i].var()); |
| 1471 } | 1514 } |
| 1472 | 1515 |
| 1516 if (enable_context_globals) { |
| 1517 for (int i = 0; i < var_count; i++) { |
| 1518 AllocateDeclaredGlobal(isolate, vars[i].var()); |
| 1519 } |
| 1520 } |
| 1521 |
| 1473 // For now, function_ must be allocated at the very end. If it gets | 1522 // For now, function_ must be allocated at the very end. If it gets |
| 1474 // allocated in the context, it must be the last slot in the context, | 1523 // allocated in the context, it must be the last slot in the context, |
| 1475 // because of the current ScopeInfo implementation (see | 1524 // because of the current ScopeInfo implementation (see |
| 1476 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). | 1525 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). |
| 1477 if (function_ != nullptr) { | 1526 if (function_ != nullptr) { |
| 1478 AllocateNonParameterLocal(isolate, function_->proxy()->var()); | 1527 AllocateNonParameterLocal(isolate, function_->proxy()->var()); |
| 1479 } | 1528 } |
| 1480 | 1529 |
| 1481 if (rest_parameter_ != nullptr) { | 1530 if (rest_parameter_ != nullptr) { |
| 1482 AllocateNonParameterLocal(isolate, rest_parameter_); | 1531 AllocateNonParameterLocal(isolate, rest_parameter_); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1508 // If scope is already resolved, we still need to allocate | 1557 // If scope is already resolved, we still need to allocate |
| 1509 // variables in inner scopes which might not had been resolved yet. | 1558 // variables in inner scopes which might not had been resolved yet. |
| 1510 if (already_resolved()) return; | 1559 if (already_resolved()) return; |
| 1511 // The number of slots required for variables. | 1560 // The number of slots required for variables. |
| 1512 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; | 1561 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |
| 1513 | 1562 |
| 1514 // Allocate variables for this scope. | 1563 // Allocate variables for this scope. |
| 1515 // Parameters must be allocated first, if any. | 1564 // Parameters must be allocated first, if any. |
| 1516 if (is_function_scope()) AllocateParameterLocals(isolate); | 1565 if (is_function_scope()) AllocateParameterLocals(isolate); |
| 1517 if (has_this_declaration()) AllocateReceiver(); | 1566 if (has_this_declaration()) AllocateReceiver(); |
| 1518 AllocateNonParameterLocals(isolate); | 1567 AllocateNonParameterLocalsAndDeclaredGlobals(isolate); |
| 1519 | 1568 |
| 1520 // Force allocation of a context for this scope if necessary. For a 'with' | 1569 // Force allocation of a context for this scope if necessary. For a 'with' |
| 1521 // scope and for a function scope that makes an 'eval' call we need a context, | 1570 // scope and for a function scope that makes an 'eval' call we need a context, |
| 1522 // even if no local variables were statically allocated in the scope. | 1571 // even if no local variables were statically allocated in the scope. |
| 1523 // Likewise for modules. | 1572 // Likewise for modules. |
| 1524 bool must_have_context = is_with_scope() || is_module_scope() || | 1573 bool must_have_context = is_with_scope() || is_module_scope() || |
| 1525 (is_function_scope() && calls_sloppy_eval()); | 1574 (is_function_scope() && calls_sloppy_eval()); |
| 1526 | 1575 |
| 1527 // If we didn't allocate any locals in the local context, then we only | 1576 // If we didn't allocate any locals in the local context, then we only |
| 1528 // need the minimal number of slots if we must have a context. | 1577 // need the minimal number of slots if we must have a context. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1552 | 1601 |
| 1553 | 1602 |
| 1554 int Scope::StackLocalCount() const { | 1603 int Scope::StackLocalCount() const { |
| 1555 return num_stack_slots() - | 1604 return num_stack_slots() - |
| 1556 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); | 1605 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); |
| 1557 } | 1606 } |
| 1558 | 1607 |
| 1559 | 1608 |
| 1560 int Scope::ContextLocalCount() const { | 1609 int Scope::ContextLocalCount() const { |
| 1561 if (num_heap_slots() == 0) return 0; | 1610 if (num_heap_slots() == 0) return 0; |
| 1611 bool is_function_var_in_context = |
| 1612 function_ != NULL && function_->proxy()->var()->IsContextSlot(); |
| 1562 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1613 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
| 1563 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 1614 2 * num_global_slots() - (is_function_var_in_context ? 1 : 0); |
| 1564 } | 1615 } |
| 1616 |
| 1617 |
| 1618 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
| 1565 } // namespace internal | 1619 } // namespace internal |
| 1566 } // namespace v8 | 1620 } // namespace v8 |
| OLD | NEW |