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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 language_mode_ = outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY; | 175 language_mode_ = outer_scope != NULL ? outer_scope->language_mode_ : SLOPPY; |
173 outer_scope_calls_sloppy_eval_ = false; | 176 outer_scope_calls_sloppy_eval_ = false; |
174 inner_scope_calls_eval_ = false; | 177 inner_scope_calls_eval_ = false; |
175 inner_scope_uses_arguments_ = false; | 178 inner_scope_uses_arguments_ = false; |
176 force_eager_compilation_ = false; | 179 force_eager_compilation_ = false; |
177 force_context_allocation_ = (outer_scope != NULL && !is_function_scope()) | 180 force_context_allocation_ = (outer_scope != NULL && !is_function_scope()) |
178 ? outer_scope->has_forced_context_allocation() : false; | 181 ? outer_scope->has_forced_context_allocation() : false; |
179 num_var_or_const_ = 0; | 182 num_var_or_const_ = 0; |
180 num_stack_slots_ = 0; | 183 num_stack_slots_ = 0; |
181 num_heap_slots_ = 0; | 184 num_heap_slots_ = 0; |
| 185 num_global_slots_ = 0; |
182 num_modules_ = 0; | 186 num_modules_ = 0; |
183 module_var_ = NULL, | 187 module_var_ = NULL, |
184 rest_parameter_ = NULL; | 188 rest_parameter_ = NULL; |
185 rest_index_ = -1; | 189 rest_index_ = -1; |
186 scope_info_ = scope_info; | 190 scope_info_ = scope_info; |
187 start_position_ = RelocInfo::kNoPosition; | 191 start_position_ = RelocInfo::kNoPosition; |
188 end_position_ = RelocInfo::kNoPosition; | 192 end_position_ = RelocInfo::kNoPosition; |
189 if (!scope_info.is_null()) { | 193 if (!scope_info.is_null()) { |
190 scope_calls_eval_ = scope_info->CallsEval(); | 194 scope_calls_eval_ = scope_info->CallsEval(); |
191 language_mode_ = scope_info->language_mode(); | 195 language_mode_ = scope_info->language_mode(); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 Handle<String> name_handle = name->string(); | 387 Handle<String> name_handle = name->string(); |
384 // The Scope is backed up by ScopeInfo. This means it cannot operate in a | 388 // The Scope is backed up by ScopeInfo. This means it cannot operate in a |
385 // heap-independent mode, and all strings must be internalized immediately. So | 389 // heap-independent mode, and all strings must be internalized immediately. So |
386 // it's ok to get the Handle<String> here. | 390 // it's ok to get the Handle<String> here. |
387 // If we have a serialized scope info, we might find the variable there. | 391 // If we have a serialized scope info, we might find the variable there. |
388 // There should be no local slot with the given name. | 392 // There should be no local slot with the given name. |
389 DCHECK(scope_info_->StackSlotIndex(*name_handle) < 0 || is_block_scope()); | 393 DCHECK(scope_info_->StackSlotIndex(*name_handle) < 0 || is_block_scope()); |
390 | 394 |
391 // Check context slot lookup. | 395 // Check context slot lookup. |
392 VariableMode mode; | 396 VariableMode mode; |
| 397 ContextSlotKindFlag slot_kind; |
393 Variable::Location location = Variable::CONTEXT; | 398 Variable::Location location = Variable::CONTEXT; |
394 InitializationFlag init_flag; | 399 InitializationFlag init_flag; |
395 MaybeAssignedFlag maybe_assigned_flag; | 400 MaybeAssignedFlag maybe_assigned_flag; |
396 int index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, | 401 int index = |
397 &init_flag, &maybe_assigned_flag); | 402 ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, &slot_kind, |
| 403 &init_flag, &maybe_assigned_flag); |
398 if (index < 0) { | 404 if (index < 0) { |
399 // Check parameters. | 405 // Check parameters. |
400 index = scope_info_->ParameterIndex(*name_handle); | 406 index = scope_info_->ParameterIndex(*name_handle); |
401 if (index < 0) return NULL; | 407 if (index < 0) return NULL; |
402 | 408 |
403 mode = DYNAMIC; | 409 mode = DYNAMIC; |
404 location = Variable::LOOKUP; | 410 location = Variable::LOOKUP; |
405 init_flag = kCreatedInitialized; | 411 init_flag = kCreatedInitialized; |
406 // Be conservative and flag parameters as maybe assigned. Better information | 412 // Be conservative and flag parameters as maybe assigned. Better information |
407 // would require ScopeInfo to serialize the maybe_assigned bit also for | 413 // would require ScopeInfo to serialize the maybe_assigned bit also for |
408 // parameters. | 414 // parameters. |
409 maybe_assigned_flag = kMaybeAssigned; | 415 maybe_assigned_flag = kMaybeAssigned; |
| 416 |
| 417 } else if (slot_kind == ContextSlotKindFlag::kGlobal) { |
| 418 DCHECK(is_script_scope()); |
| 419 DCHECK(IsDeclaredVariableMode(mode) && !IsLexicalVariableMode(mode)); |
| 420 location = Variable::UNALLOCATED; |
410 } | 421 } |
411 | 422 |
412 Variable::Kind kind = Variable::NORMAL; | 423 Variable::Kind kind = Variable::NORMAL; |
413 if (location == Variable::CONTEXT && | 424 if (location == Variable::CONTEXT && |
414 index == scope_info_->ReceiverContextSlotIndex()) { | 425 index == scope_info_->ReceiverContextSlotIndex()) { |
415 kind = Variable::THIS; | 426 kind = Variable::THIS; |
416 } | 427 } |
417 // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and | 428 // TODO(marja, rossberg): Correctly declare FUNCTION, CLASS, NEW_TARGET, and |
418 // ARGUMENTS bindings as their corresponding Variable::Kind. | 429 // ARGUMENTS bindings as their corresponding Variable::Kind. |
419 | 430 |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 } | 609 } |
599 | 610 |
600 private: | 611 private: |
601 Variable* var_; | 612 Variable* var_; |
602 int order_; | 613 int order_; |
603 }; | 614 }; |
604 | 615 |
605 | 616 |
606 void Scope::CollectStackAndContextLocals( | 617 void Scope::CollectStackAndContextLocals( |
607 ZoneList<Variable*>* stack_locals, ZoneList<Variable*>* context_locals, | 618 ZoneList<Variable*>* stack_locals, ZoneList<Variable*>* context_locals, |
| 619 ZoneList<Variable*>* context_globals, |
608 ZoneList<Variable*>* strong_mode_free_variables) { | 620 ZoneList<Variable*>* strong_mode_free_variables) { |
609 DCHECK(stack_locals != NULL); | 621 DCHECK(stack_locals != NULL); |
610 DCHECK(context_locals != NULL); | 622 DCHECK(context_locals != NULL); |
| 623 DCHECK(context_globals != NULL); |
611 | 624 |
612 // Collect internals which are always allocated on the heap. | 625 // Collect internals which are always allocated on the heap. |
613 for (int i = 0; i < internals_.length(); i++) { | 626 for (int i = 0; i < internals_.length(); i++) { |
614 Variable* var = internals_[i]; | 627 Variable* var = internals_[i]; |
615 if (var->is_used()) { | 628 if (var->is_used()) { |
616 DCHECK(var->IsContextSlot()); | 629 DCHECK(var->IsContextSlot()); |
617 context_locals->Add(var, zone()); | 630 context_locals->Add(var, zone()); |
618 } | 631 } |
619 } | 632 } |
620 | 633 |
(...skipping 28 matching lines...) Expand all Loading... |
649 } | 662 } |
650 } | 663 } |
651 vars.Sort(VarAndOrder::Compare); | 664 vars.Sort(VarAndOrder::Compare); |
652 int var_count = vars.length(); | 665 int var_count = vars.length(); |
653 for (int i = 0; i < var_count; i++) { | 666 for (int i = 0; i < var_count; i++) { |
654 Variable* var = vars[i].var(); | 667 Variable* var = vars[i].var(); |
655 if (var->IsStackLocal()) { | 668 if (var->IsStackLocal()) { |
656 stack_locals->Add(var, zone()); | 669 stack_locals->Add(var, zone()); |
657 } else if (var->IsContextSlot()) { | 670 } else if (var->IsContextSlot()) { |
658 context_locals->Add(var, zone()); | 671 context_locals->Add(var, zone()); |
| 672 } else if (enable_context_globals && var->IsStaticGlobalObjectProperty()) { |
| 673 context_globals->Add(var, zone()); |
659 } | 674 } |
660 } | 675 } |
661 } | 676 } |
662 | 677 |
663 | 678 |
664 bool Scope::AllocateVariables(ParseInfo* info, AstNodeFactory* factory) { | 679 bool Scope::AllocateVariables(ParseInfo* info, AstNodeFactory* factory) { |
665 // 1) Propagate scope information. | 680 // 1) Propagate scope information. |
666 bool outer_scope_calls_sloppy_eval = false; | 681 bool outer_scope_calls_sloppy_eval = false; |
667 if (outer_scope_ != NULL) { | 682 if (outer_scope_ != NULL) { |
668 outer_scope_calls_sloppy_eval = | 683 outer_scope_calls_sloppy_eval = |
(...skipping 19 matching lines...) Expand all Loading... |
688 | 703 |
689 | 704 |
690 bool Scope::HasTrivialContext() const { | 705 bool Scope::HasTrivialContext() const { |
691 // A function scope has a trivial context if it always is the global | 706 // A function scope has a trivial context if it always is the global |
692 // context. We iteratively scan out the context chain to see if | 707 // context. We iteratively scan out the context chain to see if |
693 // there is anything that makes this scope non-trivial; otherwise we | 708 // there is anything that makes this scope non-trivial; otherwise we |
694 // return true. | 709 // return true. |
695 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) { | 710 for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) { |
696 if (scope->is_eval_scope()) return false; | 711 if (scope->is_eval_scope()) return false; |
697 if (scope->scope_inside_with_) return false; | 712 if (scope->scope_inside_with_) return false; |
698 if (scope->num_heap_slots_ > 0) return false; | 713 if (scope->ContextLocalCount() > 0) return false; |
699 } | 714 } |
700 return true; | 715 return true; |
701 } | 716 } |
702 | 717 |
703 | 718 |
704 bool Scope::HasTrivialOuterContext() const { | 719 bool Scope::HasTrivialOuterContext() const { |
705 Scope* outer = outer_scope_; | 720 Scope* outer = outer_scope_; |
706 if (outer == NULL) return true; | 721 if (outer == NULL) return true; |
707 // Note that the outer context may be trivial in general, but the current | 722 // Note that the outer context may be trivial in general, but the current |
708 // scope may be inside a 'with' statement in which case the outer context | 723 // scope may be inside a 'with' statement in which case the outer context |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
824 | 839 |
825 | 840 |
826 static void PrintName(const AstRawString* name) { | 841 static void PrintName(const AstRawString* name) { |
827 PrintF("%.*s", name->length(), name->raw_data()); | 842 PrintF("%.*s", name->length(), name->raw_data()); |
828 } | 843 } |
829 | 844 |
830 | 845 |
831 static void PrintLocation(Variable* var) { | 846 static void PrintLocation(Variable* var) { |
832 switch (var->location()) { | 847 switch (var->location()) { |
833 case Variable::UNALLOCATED: | 848 case Variable::UNALLOCATED: |
| 849 if (var->IsStaticGlobalObjectProperty()) { |
| 850 PrintF("global[%d]", var->index()); |
| 851 } |
834 break; | 852 break; |
835 case Variable::PARAMETER: | 853 case Variable::PARAMETER: |
836 PrintF("parameter[%d]", var->index()); | 854 PrintF("parameter[%d]", var->index()); |
837 break; | 855 break; |
838 case Variable::LOCAL: | 856 case Variable::LOCAL: |
839 PrintF("local[%d]", var->index()); | 857 PrintF("local[%d]", var->index()); |
840 break; | 858 break; |
841 case Variable::CONTEXT: | 859 case Variable::CONTEXT: |
842 PrintF("context[%d]", var->index()); | 860 PrintF("context[%d]", var->index()); |
843 break; | 861 break; |
844 case Variable::LOOKUP: | 862 case Variable::LOOKUP: |
845 PrintF("lookup"); | 863 PrintF("lookup"); |
846 break; | 864 break; |
847 } | 865 } |
848 } | 866 } |
849 | 867 |
850 | 868 |
851 static void PrintVar(int indent, Variable* var) { | 869 static void PrintVar(int indent, Variable* var) { |
852 if (var->is_used() || !var->IsUnallocated()) { | 870 if (var->is_used() || !var->IsUnallocated() || |
| 871 var->IsStaticGlobalObjectProperty()) { |
853 Indent(indent, Variable::Mode2String(var->mode())); | 872 Indent(indent, Variable::Mode2String(var->mode())); |
854 PrintF(" "); | 873 PrintF(" "); |
855 PrintName(var->raw_name()); | 874 PrintName(var->raw_name()); |
856 PrintF("; // "); | 875 PrintF("; // "); |
857 PrintLocation(var); | 876 PrintLocation(var); |
858 bool comma = !var->IsUnallocated(); | 877 bool comma = !var->IsUnallocated() || var->IsStaticGlobalObjectProperty(); |
859 if (var->has_forced_context_allocation()) { | 878 if (var->has_forced_context_allocation()) { |
860 if (comma) PrintF(", "); | 879 if (comma) PrintF(", "); |
861 PrintF("forced context allocation"); | 880 PrintF("forced context allocation"); |
862 comma = true; | 881 comma = true; |
863 } | 882 } |
864 if (var->maybe_assigned() == kMaybeAssigned) { | 883 if (var->maybe_assigned() == kMaybeAssigned) { |
865 if (comma) PrintF(", "); | 884 if (comma) PrintF(", "); |
866 PrintF("maybe assigned"); | 885 PrintF("maybe assigned"); |
867 } | 886 } |
868 PrintF("\n"); | 887 PrintF("\n"); |
869 } | 888 } |
870 } | 889 } |
871 | 890 |
872 | 891 |
873 static void PrintMap(int indent, VariableMap* map) { | 892 static void PrintMap(int indent, VariableMap* map) { |
874 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { | 893 for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { |
875 Variable* var = reinterpret_cast<Variable*>(p->value); | 894 Variable* var = reinterpret_cast<Variable*>(p->value); |
876 PrintVar(indent, var); | 895 if (var == NULL) { |
| 896 Indent(indent, "<?>\n"); |
| 897 } else { |
| 898 PrintVar(indent, var); |
| 899 } |
877 } | 900 } |
878 } | 901 } |
879 | 902 |
880 | 903 |
881 void Scope::Print(int n) { | 904 void Scope::Print(int n) { |
882 int n0 = (n > 0 ? n : 0); | 905 int n0 = (n > 0 ? n : 0); |
883 int n1 = n0 + 2; // indentation | 906 int n1 = n0 + 2; // indentation |
884 | 907 |
885 // Print header. | 908 // Print header. |
886 Indent(n0, Header(scope_type_)); | 909 Indent(n0, Header(scope_type_)); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
923 if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n"); | 946 if (scope_uses_arguments_) Indent(n1, "// scope uses 'arguments'\n"); |
924 if (scope_uses_super_property_) | 947 if (scope_uses_super_property_) |
925 Indent(n1, "// scope uses 'super' property\n"); | 948 Indent(n1, "// scope uses 'super' property\n"); |
926 if (inner_scope_uses_arguments_) { | 949 if (inner_scope_uses_arguments_) { |
927 Indent(n1, "// inner scope uses 'arguments'\n"); | 950 Indent(n1, "// inner scope uses 'arguments'\n"); |
928 } | 951 } |
929 if (outer_scope_calls_sloppy_eval_) { | 952 if (outer_scope_calls_sloppy_eval_) { |
930 Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); | 953 Indent(n1, "// outer scope calls 'eval' in sloppy context\n"); |
931 } | 954 } |
932 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); | 955 if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); |
933 if (num_stack_slots_ > 0) { Indent(n1, "// "); | 956 if (num_stack_slots_ > 0) { |
934 PrintF("%d stack slots\n", num_stack_slots_); } | 957 Indent(n1, "// "); |
935 if (num_heap_slots_ > 0) { Indent(n1, "// "); | 958 PrintF("%d stack slots\n", num_stack_slots_); |
936 PrintF("%d heap slots\n", num_heap_slots_); } | 959 } |
| 960 if (num_heap_slots_ > 0) { |
| 961 Indent(n1, "// "); |
| 962 PrintF("%d heap slots (including %d global slots)\n", num_heap_slots_, |
| 963 num_global_slots_); |
| 964 } |
937 | 965 |
938 // Print locals. | 966 // Print locals. |
939 if (function_ != NULL) { | 967 if (function_ != NULL) { |
940 Indent(n1, "// function var:\n"); | 968 Indent(n1, "// function var:\n"); |
941 PrintVar(n1, function_->proxy()->var()); | 969 PrintVar(n1, function_->proxy()->var()); |
942 } | 970 } |
943 | 971 |
944 if (temps_.length() > 0) { | 972 if (temps_.length() > 0) { |
945 Indent(n1, "// temporary vars:\n"); | 973 Indent(n1, "// temporary vars:\n"); |
946 for (int i = 0; i < temps_.length(); i++) { | 974 for (int i = 0; i < temps_.length(); i++) { |
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1413 DCHECK(var->IsUnallocated() || var->IsContextSlot()); | 1441 DCHECK(var->IsUnallocated() || var->IsContextSlot()); |
1414 if (var->IsUnallocated()) { | 1442 if (var->IsUnallocated()) { |
1415 AllocateHeapSlot(var); | 1443 AllocateHeapSlot(var); |
1416 } | 1444 } |
1417 } else { | 1445 } else { |
1418 DCHECK(var->IsUnallocated() || var->IsParameter()); | 1446 DCHECK(var->IsUnallocated() || var->IsParameter()); |
1419 if (var->IsUnallocated()) { | 1447 if (var->IsUnallocated()) { |
1420 var->AllocateTo(Variable::PARAMETER, index); | 1448 var->AllocateTo(Variable::PARAMETER, index); |
1421 } | 1449 } |
1422 } | 1450 } |
| 1451 } else { |
| 1452 DCHECK(!var->IsStaticGlobalObjectProperty()); |
1423 } | 1453 } |
1424 } | 1454 } |
1425 | 1455 |
1426 | 1456 |
1427 void Scope::AllocateReceiver() { | 1457 void Scope::AllocateReceiver() { |
1428 DCHECK_NOT_NULL(receiver()); | 1458 DCHECK_NOT_NULL(receiver()); |
1429 DCHECK_EQ(receiver()->scope(), this); | 1459 DCHECK_EQ(receiver()->scope(), this); |
1430 | 1460 |
1431 if (has_forced_context_allocation()) { | 1461 if (has_forced_context_allocation()) { |
1432 // Force context allocation of the receiver. | 1462 // Force context allocation of the receiver. |
(...skipping 10 matching lines...) Expand all Loading... |
1443 if (var->IsUnallocated() && MustAllocate(var)) { | 1473 if (var->IsUnallocated() && MustAllocate(var)) { |
1444 if (MustAllocateInContext(var)) { | 1474 if (MustAllocateInContext(var)) { |
1445 AllocateHeapSlot(var); | 1475 AllocateHeapSlot(var); |
1446 } else { | 1476 } else { |
1447 AllocateStackSlot(var); | 1477 AllocateStackSlot(var); |
1448 } | 1478 } |
1449 } | 1479 } |
1450 } | 1480 } |
1451 | 1481 |
1452 | 1482 |
1453 void Scope::AllocateNonParameterLocals(Isolate* isolate) { | 1483 void Scope::AllocateDeclaredGlobal(Isolate* isolate, Variable* var) { |
| 1484 DCHECK(var->scope() == this); |
| 1485 DCHECK(!var->IsVariable(isolate->factory()->dot_result_string()) || |
| 1486 !var->IsStackLocal()); |
| 1487 if (var->IsUnallocated() && var->IsStaticGlobalObjectProperty()) { |
| 1488 DCHECK_EQ(-1, var->index()); |
| 1489 DCHECK(var->name()->IsString()); |
| 1490 var->AllocateTo(Variable::UNALLOCATED, num_heap_slots_); |
| 1491 num_global_slots_++; |
| 1492 // Each global variable occupies two slots in the context: for reads |
| 1493 // and writes. |
| 1494 num_heap_slots_ += 2; |
| 1495 } |
| 1496 } |
| 1497 |
| 1498 |
| 1499 void Scope::AllocateNonParameterLocalsAndDeclaredGlobals(Isolate* isolate) { |
1454 // All variables that have no rewrite yet are non-parameter locals. | 1500 // All variables that have no rewrite yet are non-parameter locals. |
1455 for (int i = 0; i < temps_.length(); i++) { | 1501 for (int i = 0; i < temps_.length(); i++) { |
1456 AllocateNonParameterLocal(isolate, temps_[i]); | 1502 AllocateNonParameterLocal(isolate, temps_[i]); |
1457 } | 1503 } |
1458 | 1504 |
1459 for (int i = 0; i < internals_.length(); i++) { | 1505 for (int i = 0; i < internals_.length(); i++) { |
1460 AllocateNonParameterLocal(isolate, internals_[i]); | 1506 AllocateNonParameterLocal(isolate, internals_[i]); |
1461 } | 1507 } |
1462 | 1508 |
1463 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); | 1509 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); |
1464 for (VariableMap::Entry* p = variables_.Start(); | 1510 for (VariableMap::Entry* p = variables_.Start(); |
1465 p != NULL; | 1511 p != NULL; |
1466 p = variables_.Next(p)) { | 1512 p = variables_.Next(p)) { |
1467 Variable* var = reinterpret_cast<Variable*>(p->value); | 1513 Variable* var = reinterpret_cast<Variable*>(p->value); |
1468 vars.Add(VarAndOrder(var, p->order), zone()); | 1514 vars.Add(VarAndOrder(var, p->order), zone()); |
1469 } | 1515 } |
1470 vars.Sort(VarAndOrder::Compare); | 1516 vars.Sort(VarAndOrder::Compare); |
1471 int var_count = vars.length(); | 1517 int var_count = vars.length(); |
1472 for (int i = 0; i < var_count; i++) { | 1518 for (int i = 0; i < var_count; i++) { |
1473 AllocateNonParameterLocal(isolate, vars[i].var()); | 1519 AllocateNonParameterLocal(isolate, vars[i].var()); |
1474 } | 1520 } |
1475 | 1521 |
| 1522 if (enable_context_globals) { |
| 1523 for (int i = 0; i < var_count; i++) { |
| 1524 AllocateDeclaredGlobal(isolate, vars[i].var()); |
| 1525 } |
| 1526 } |
| 1527 |
1476 // For now, function_ must be allocated at the very end. If it gets | 1528 // For now, function_ must be allocated at the very end. If it gets |
1477 // allocated in the context, it must be the last slot in the context, | 1529 // allocated in the context, it must be the last slot in the context, |
1478 // because of the current ScopeInfo implementation (see | 1530 // because of the current ScopeInfo implementation (see |
1479 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). | 1531 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). |
1480 if (function_ != nullptr) { | 1532 if (function_ != nullptr) { |
1481 AllocateNonParameterLocal(isolate, function_->proxy()->var()); | 1533 AllocateNonParameterLocal(isolate, function_->proxy()->var()); |
1482 } | 1534 } |
1483 | 1535 |
1484 if (rest_parameter_ != nullptr) { | 1536 if (rest_parameter_ != nullptr) { |
1485 AllocateNonParameterLocal(isolate, rest_parameter_); | 1537 AllocateNonParameterLocal(isolate, rest_parameter_); |
(...skipping 25 matching lines...) Expand all Loading... |
1511 // If scope is already resolved, we still need to allocate | 1563 // If scope is already resolved, we still need to allocate |
1512 // variables in inner scopes which might not had been resolved yet. | 1564 // variables in inner scopes which might not had been resolved yet. |
1513 if (already_resolved()) return; | 1565 if (already_resolved()) return; |
1514 // The number of slots required for variables. | 1566 // The number of slots required for variables. |
1515 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; | 1567 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |
1516 | 1568 |
1517 // Allocate variables for this scope. | 1569 // Allocate variables for this scope. |
1518 // Parameters must be allocated first, if any. | 1570 // Parameters must be allocated first, if any. |
1519 if (is_function_scope()) AllocateParameterLocals(isolate); | 1571 if (is_function_scope()) AllocateParameterLocals(isolate); |
1520 if (has_this_declaration()) AllocateReceiver(); | 1572 if (has_this_declaration()) AllocateReceiver(); |
1521 AllocateNonParameterLocals(isolate); | 1573 AllocateNonParameterLocalsAndDeclaredGlobals(isolate); |
1522 | 1574 |
1523 // Force allocation of a context for this scope if necessary. For a 'with' | 1575 // Force allocation of a context for this scope if necessary. For a 'with' |
1524 // scope and for a function scope that makes an 'eval' call we need a context, | 1576 // scope and for a function scope that makes an 'eval' call we need a context, |
1525 // even if no local variables were statically allocated in the scope. | 1577 // even if no local variables were statically allocated in the scope. |
1526 // Likewise for modules. | 1578 // Likewise for modules. |
1527 bool must_have_context = is_with_scope() || is_module_scope() || | 1579 bool must_have_context = is_with_scope() || is_module_scope() || |
1528 (is_function_scope() && calls_sloppy_eval()); | 1580 (is_function_scope() && calls_sloppy_eval()); |
1529 | 1581 |
1530 // If we didn't allocate any locals in the local context, then we only | 1582 // If we didn't allocate any locals in the local context, then we only |
1531 // need the minimal number of slots if we must have a context. | 1583 // need the minimal number of slots if we must have a context. |
(...skipping 23 matching lines...) Expand all Loading... |
1555 | 1607 |
1556 | 1608 |
1557 int Scope::StackLocalCount() const { | 1609 int Scope::StackLocalCount() const { |
1558 return num_stack_slots() - | 1610 return num_stack_slots() - |
1559 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); | 1611 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); |
1560 } | 1612 } |
1561 | 1613 |
1562 | 1614 |
1563 int Scope::ContextLocalCount() const { | 1615 int Scope::ContextLocalCount() const { |
1564 if (num_heap_slots() == 0) return 0; | 1616 if (num_heap_slots() == 0) return 0; |
| 1617 bool is_function_var_in_context = |
| 1618 function_ != NULL && function_->proxy()->var()->IsContextSlot(); |
1565 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1619 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
1566 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 1620 2 * num_global_slots() - (is_function_var_in_context ? 1 : 0); |
1567 } | 1621 } |
| 1622 |
| 1623 |
| 1624 int Scope::ContextGlobalCount() const { return num_global_slots(); } |
1568 } // namespace internal | 1625 } // namespace internal |
1569 } // namespace v8 | 1626 } // namespace v8 |
OLD | NEW |