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 |