Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/scopes.cc

Issue 5753005: Make closures optimizable by Crankshaft compiler. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 arguments_shadow_(NULL), 128 arguments_shadow_(NULL),
129 illegal_redecl_(NULL), 129 illegal_redecl_(NULL),
130 scope_inside_with_(false), 130 scope_inside_with_(false),
131 scope_contains_with_(false), 131 scope_contains_with_(false),
132 scope_calls_eval_(false), 132 scope_calls_eval_(false),
133 outer_scope_calls_eval_(false), 133 outer_scope_calls_eval_(false),
134 inner_scope_calls_eval_(false), 134 inner_scope_calls_eval_(false),
135 outer_scope_is_eval_scope_(false), 135 outer_scope_is_eval_scope_(false),
136 force_eager_compilation_(false), 136 force_eager_compilation_(false),
137 num_stack_slots_(0), 137 num_stack_slots_(0),
138 num_heap_slots_(0) { 138 num_heap_slots_(0),
139 resolved_(false) {
139 } 140 }
140 141
141 142
142 Scope::Scope(Scope* outer_scope, Type type) 143 Scope::Scope(Scope* outer_scope, Type type)
143 : outer_scope_(outer_scope), 144 : outer_scope_(outer_scope),
144 inner_scopes_(4), 145 inner_scopes_(4),
145 type_(type), 146 type_(type),
146 scope_name_(Factory::empty_symbol()), 147 scope_name_(Factory::empty_symbol()),
147 temps_(4), 148 temps_(4),
148 params_(4), 149 params_(4),
149 dynamics_(NULL), 150 dynamics_(NULL),
150 unresolved_(16), 151 unresolved_(16),
151 decls_(4), 152 decls_(4),
152 receiver_(NULL), 153 receiver_(NULL),
153 function_(NULL), 154 function_(NULL),
154 arguments_(NULL), 155 arguments_(NULL),
155 arguments_shadow_(NULL), 156 arguments_shadow_(NULL),
156 illegal_redecl_(NULL), 157 illegal_redecl_(NULL),
157 scope_inside_with_(false), 158 scope_inside_with_(false),
158 scope_contains_with_(false), 159 scope_contains_with_(false),
159 scope_calls_eval_(false), 160 scope_calls_eval_(false),
160 outer_scope_calls_eval_(false), 161 outer_scope_calls_eval_(false),
161 inner_scope_calls_eval_(false), 162 inner_scope_calls_eval_(false),
162 outer_scope_is_eval_scope_(false), 163 outer_scope_is_eval_scope_(false),
163 force_eager_compilation_(false), 164 force_eager_compilation_(false),
164 num_stack_slots_(0), 165 num_stack_slots_(0),
165 num_heap_slots_(0) { 166 num_heap_slots_(0),
167 resolved_(false) {
166 // At some point we might want to provide outer scopes to 168 // At some point we might want to provide outer scopes to
167 // eval scopes (by walking the stack and reading the scope info). 169 // eval scopes (by walking the stack and reading the scope info).
168 // In that case, the ASSERT below needs to be adjusted. 170 // In that case, the ASSERT below needs to be adjusted.
169 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL)); 171 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL));
170 ASSERT(!HasIllegalRedeclaration()); 172 ASSERT(!HasIllegalRedeclaration());
171 } 173 }
172 174
173 175
174 bool Scope::Analyze(CompilationInfo* info) { 176 bool Scope::Analyze(CompilationInfo* info) {
175 ASSERT(info->function() != NULL); 177 ASSERT(info->function() != NULL);
(...skipping 27 matching lines...) Expand all
203 // Declare and allocate receiver (even for the global scope, and even 205 // Declare and allocate receiver (even for the global scope, and even
204 // if naccesses_ == 0). 206 // if naccesses_ == 0).
205 // NOTE: When loading parameters in the global scope, we must take 207 // NOTE: When loading parameters in the global scope, we must take
206 // care not to access them as properties of the global object, but 208 // care not to access them as properties of the global object, but
207 // instead load them directly from the stack. Currently, the only 209 // instead load them directly from the stack. Currently, the only
208 // such parameter is 'this' which is passed on the stack when 210 // such parameter is 'this' which is passed on the stack when
209 // invoking scripts 211 // invoking scripts
210 Variable* var = 212 Variable* var =
211 variables_.Declare(this, Factory::this_symbol(), Variable::VAR, 213 variables_.Declare(this, Factory::this_symbol(), Variable::VAR,
212 false, Variable::THIS); 214 false, Variable::THIS);
213 var->rewrite_ = new Slot(var, Slot::PARAMETER, -1); 215 var->set_rewrite(new Slot(var, Slot::PARAMETER, -1));
214 receiver_ = var; 216 receiver_ = var;
215 217
216 if (is_function_scope()) { 218 if (is_function_scope()) {
217 // Declare 'arguments' variable which exists in all functions. 219 // Declare 'arguments' variable which exists in all functions.
218 // Note that it might never be accessed, in which case it won't be 220 // Note that it might never be accessed, in which case it won't be
219 // allocated during variable allocation. 221 // allocated during variable allocation.
220 variables_.Declare(this, Factory::arguments_symbol(), Variable::VAR, 222 variables_.Declare(this, Factory::arguments_symbol(), Variable::VAR,
221 true, Variable::ARGUMENTS); 223 true, Variable::ARGUMENTS);
222 } 224 }
223 } 225 }
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 545
544 546
545 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { 547 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) {
546 if (dynamics_ == NULL) dynamics_ = new DynamicScopePart(); 548 if (dynamics_ == NULL) dynamics_ = new DynamicScopePart();
547 VariableMap* map = dynamics_->GetMap(mode); 549 VariableMap* map = dynamics_->GetMap(mode);
548 Variable* var = map->Lookup(name); 550 Variable* var = map->Lookup(name);
549 if (var == NULL) { 551 if (var == NULL) {
550 // Declare a new non-local. 552 // Declare a new non-local.
551 var = map->Declare(NULL, name, mode, true, Variable::NORMAL); 553 var = map->Declare(NULL, name, mode, true, Variable::NORMAL);
552 // Allocate it by giving it a dynamic lookup. 554 // Allocate it by giving it a dynamic lookup.
553 var->rewrite_ = new Slot(var, Slot::LOOKUP, -1); 555 var->set_rewrite(new Slot(var, Slot::LOOKUP, -1));
554 } 556 }
555 return var; 557 return var;
556 } 558 }
557 559
558 560
559 // Lookup a variable starting with this scope. The result is either 561 // Lookup a variable starting with this scope. The result is either
560 // the statically resolved variable belonging to an outer scope, or 562 // the statically resolved variable belonging to an outer scope, or
561 // NULL. It may be NULL because a) we couldn't find a variable, or b) 563 // NULL. It may be NULL because a) we couldn't find a variable, or b)
562 // because the variable is just a guess (and may be shadowed by 564 // because the variable is just a guess (and may be shadowed by
563 // another variable that is introduced dynamically via an 'eval' call 565 // another variable that is introduced dynamically via an 'eval' call
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 } 607 }
606 608
607 // If we did not find a variable, we are done. 609 // If we did not find a variable, we are done.
608 if (var == NULL) 610 if (var == NULL)
609 return NULL; 611 return NULL;
610 } 612 }
611 613
612 ASSERT(var != NULL); 614 ASSERT(var != NULL);
613 615
614 // If this is a lookup from an inner scope, mark the variable. 616 // If this is a lookup from an inner scope, mark the variable.
615 if (inner_lookup) 617 if (inner_lookup) {
616 var->is_accessed_from_inner_scope_ = true; 618 var->MarkAsAccessedFromInnerScope();
619 }
617 620
618 // If the variable we have found is just a guess, invalidate the 621 // If the variable we have found is just a guess, invalidate the
619 // result. If the found variable is local, record that fact so we 622 // result. If the found variable is local, record that fact so we
620 // can generate fast code to get it if it is not shadowed by eval. 623 // can generate fast code to get it if it is not shadowed by eval.
621 if (guess) { 624 if (guess) {
622 if (!var->is_global()) *invalidated_local = var; 625 if (!var->is_global()) *invalidated_local = var;
623 var = NULL; 626 var = NULL;
624 } 627 }
625 628
626 return var; 629 return var;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 749
747 return scope_calls_eval_ || inner_scope_calls_eval_; 750 return scope_calls_eval_ || inner_scope_calls_eval_;
748 } 751 }
749 752
750 753
751 bool Scope::MustAllocate(Variable* var) { 754 bool Scope::MustAllocate(Variable* var) {
752 // Give var a read/write use if there is a chance it might be accessed 755 // Give var a read/write use if there is a chance it might be accessed
753 // via an eval() call. This is only possible if the variable has a 756 // via an eval() call. This is only possible if the variable has a
754 // visible name. 757 // visible name.
755 if ((var->is_this() || var->name()->length() > 0) && 758 if ((var->is_this() || var->name()->length() > 0) &&
756 (var->is_accessed_from_inner_scope_ || 759 (var->is_accessed_from_inner_scope() ||
757 scope_calls_eval_ || inner_scope_calls_eval_ || 760 scope_calls_eval_ || inner_scope_calls_eval_ ||
758 scope_contains_with_)) { 761 scope_contains_with_)) {
759 var->set_is_used(true); 762 var->set_is_used(true);
760 } 763 }
761 // Global variables do not need to be allocated. 764 // Global variables do not need to be allocated.
762 return !var->is_global() && var->is_used(); 765 return !var->is_global() && var->is_used();
763 } 766 }
764 767
765 768
766 bool Scope::MustAllocateInContext(Variable* var) { 769 bool Scope::MustAllocateInContext(Variable* var) {
767 // If var is accessed from an inner scope, or if there is a 770 // If var is accessed from an inner scope, or if there is a
768 // possibility that it might be accessed from the current or an inner 771 // possibility that it might be accessed from the current or an inner
769 // scope (through an eval() call), it must be allocated in the 772 // scope (through an eval() call), it must be allocated in the
770 // context. Exception: temporary variables are not allocated in the 773 // context. Exception: temporary variables are not allocated in the
771 // context. 774 // context.
772 return 775 return
773 var->mode() != Variable::TEMPORARY && 776 var->mode() != Variable::TEMPORARY &&
774 (var->is_accessed_from_inner_scope_ || 777 (var->is_accessed_from_inner_scope() ||
775 scope_calls_eval_ || inner_scope_calls_eval_ || 778 scope_calls_eval_ || inner_scope_calls_eval_ ||
776 scope_contains_with_ || var->is_global()); 779 scope_contains_with_ || var->is_global());
777 } 780 }
778 781
779 782
780 bool Scope::HasArgumentsParameter() { 783 bool Scope::HasArgumentsParameter() {
781 for (int i = 0; i < params_.length(); i++) { 784 for (int i = 0; i < params_.length(); i++) {
782 if (params_[i]->name().is_identical_to(Factory::arguments_symbol())) 785 if (params_[i]->name().is_identical_to(Factory::arguments_symbol()))
783 return true; 786 return true;
784 } 787 }
785 return false; 788 return false;
786 } 789 }
787 790
788 791
789 void Scope::AllocateStackSlot(Variable* var) { 792 void Scope::AllocateStackSlot(Variable* var) {
790 var->rewrite_ = new Slot(var, Slot::LOCAL, num_stack_slots_++); 793 var->set_rewrite(new Slot(var, Slot::LOCAL, num_stack_slots_++));
791 } 794 }
792 795
793 796
794 void Scope::AllocateHeapSlot(Variable* var) { 797 void Scope::AllocateHeapSlot(Variable* var) {
795 var->rewrite_ = new Slot(var, Slot::CONTEXT, num_heap_slots_++); 798 var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++));
796 } 799 }
797 800
798 801
799 void Scope::AllocateParameterLocals() { 802 void Scope::AllocateParameterLocals() {
800 ASSERT(is_function_scope()); 803 ASSERT(is_function_scope());
801 Variable* arguments = LocalLookup(Factory::arguments_symbol()); 804 Variable* arguments = LocalLookup(Factory::arguments_symbol());
802 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly 805 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly
803 if (MustAllocate(arguments) && !HasArgumentsParameter()) { 806 if (MustAllocate(arguments) && !HasArgumentsParameter()) {
804 // 'arguments' is used. Unless there is also a parameter called 807 // 'arguments' is used. Unless there is also a parameter called
805 // 'arguments', we must be conservative and access all parameters via 808 // 'arguments', we must be conservative and access all parameters via
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
850 853
851 // Allocate the parameters by rewriting them into '.arguments[i]' accesses. 854 // Allocate the parameters by rewriting them into '.arguments[i]' accesses.
852 for (int i = 0; i < params_.length(); i++) { 855 for (int i = 0; i < params_.length(); i++) {
853 Variable* var = params_[i]; 856 Variable* var = params_[i];
854 ASSERT(var->scope() == this); 857 ASSERT(var->scope() == this);
855 if (MustAllocate(var)) { 858 if (MustAllocate(var)) {
856 if (MustAllocateInContext(var)) { 859 if (MustAllocateInContext(var)) {
857 // It is ok to set this only now, because arguments is a local 860 // It is ok to set this only now, because arguments is a local
858 // variable that is allocated after the parameters have been 861 // variable that is allocated after the parameters have been
859 // allocated. 862 // allocated.
860 arguments_shadow_->is_accessed_from_inner_scope_ = true; 863 arguments_shadow_->MarkAsAccessedFromInnerScope();
861 } 864 }
862 Property* rewrite = 865 Property* rewrite =
863 new Property(new VariableProxy(arguments_shadow_), 866 new Property(new VariableProxy(arguments_shadow_),
864 new Literal(Handle<Object>(Smi::FromInt(i))), 867 new Literal(Handle<Object>(Smi::FromInt(i))),
865 RelocInfo::kNoPosition, 868 RelocInfo::kNoPosition,
866 Property::SYNTHETIC); 869 Property::SYNTHETIC);
867 rewrite->set_is_arguments_access(true); 870 rewrite->set_is_arguments_access(true);
868 var->rewrite_ = rewrite; 871 var->set_rewrite(rewrite);
869 } 872 }
870 } 873 }
871 874
872 } else { 875 } else {
873 // The arguments object is not used, so we can access parameters directly. 876 // The arguments object is not used, so we can access parameters directly.
874 // The same parameter may occur multiple times in the parameters_ list. 877 // The same parameter may occur multiple times in the parameters_ list.
875 // If it does, and if it is not copied into the context object, it must 878 // If it does, and if it is not copied into the context object, it must
876 // receive the highest parameter index for that parameter; thus iteration 879 // receive the highest parameter index for that parameter; thus iteration
877 // order is relevant! 880 // order is relevant!
878 for (int i = 0; i < params_.length(); i++) { 881 for (int i = 0; i < params_.length(); i++) {
879 Variable* var = params_[i]; 882 Variable* var = params_[i];
880 ASSERT(var->scope() == this); 883 ASSERT(var->scope() == this);
881 if (MustAllocate(var)) { 884 if (MustAllocate(var)) {
882 if (MustAllocateInContext(var)) { 885 if (MustAllocateInContext(var)) {
883 ASSERT(var->rewrite_ == NULL || 886 ASSERT(var->rewrite() == NULL ||
884 (var->AsSlot() != NULL && 887 (var->AsSlot() != NULL &&
885 var->AsSlot()->type() == Slot::CONTEXT)); 888 var->AsSlot()->type() == Slot::CONTEXT));
886 if (var->rewrite_ == NULL) { 889 if (var->rewrite() == NULL) {
887 // Only set the heap allocation if the parameter has not 890 // Only set the heap allocation if the parameter has not
888 // been allocated yet. 891 // been allocated yet.
889 AllocateHeapSlot(var); 892 AllocateHeapSlot(var);
890 } 893 }
891 } else { 894 } else {
892 ASSERT(var->rewrite_ == NULL || 895 ASSERT(var->rewrite() == NULL ||
893 (var->AsSlot() != NULL && 896 (var->AsSlot() != NULL &&
894 var->AsSlot()->type() == Slot::PARAMETER)); 897 var->AsSlot()->type() == Slot::PARAMETER));
895 // Set the parameter index always, even if the parameter 898 // Set the parameter index always, even if the parameter
896 // was seen before! (We need to access the actual parameter 899 // was seen before! (We need to access the actual parameter
897 // supplied for the last occurrence of a multiply declared 900 // supplied for the last occurrence of a multiply declared
898 // parameter.) 901 // parameter.)
899 var->rewrite_ = new Slot(var, Slot::PARAMETER, i); 902 var->set_rewrite(new Slot(var, Slot::PARAMETER, i));
900 } 903 }
901 } 904 }
902 } 905 }
903 } 906 }
904 } 907 }
905 908
906 909
907 void Scope::AllocateNonParameterLocal(Variable* var) { 910 void Scope::AllocateNonParameterLocal(Variable* var) {
908 ASSERT(var->scope() == this); 911 ASSERT(var->scope() == this);
909 ASSERT(var->rewrite_ == NULL || 912 ASSERT(var->rewrite() == NULL ||
910 (!var->IsVariable(Factory::result_symbol())) || 913 (!var->IsVariable(Factory::result_symbol())) ||
911 (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL)); 914 (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL));
912 if (var->rewrite_ == NULL && MustAllocate(var)) { 915 if (var->rewrite() == NULL && MustAllocate(var)) {
913 if (MustAllocateInContext(var)) { 916 if (MustAllocateInContext(var)) {
914 AllocateHeapSlot(var); 917 AllocateHeapSlot(var);
915 } else { 918 } else {
916 AllocateStackSlot(var); 919 AllocateStackSlot(var);
917 } 920 }
918 } 921 }
919 } 922 }
920 923
921 924
922 void Scope::AllocateNonParameterLocals() { 925 void Scope::AllocateNonParameterLocals() {
(...skipping 13 matching lines...) Expand all
936 // allocated in the context, it must be the last slot in the context, 939 // allocated in the context, it must be the last slot in the context,
937 // because of the current ScopeInfo implementation (see 940 // because of the current ScopeInfo implementation (see
938 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). 941 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
939 if (function_ != NULL) { 942 if (function_ != NULL) {
940 AllocateNonParameterLocal(function_); 943 AllocateNonParameterLocal(function_);
941 } 944 }
942 } 945 }
943 946
944 947
945 void Scope::AllocateVariablesRecursively() { 948 void Scope::AllocateVariablesRecursively() {
946 // The number of slots required for variables.
947 num_stack_slots_ = 0;
948 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
949
950 // Allocate variables for inner scopes. 949 // Allocate variables for inner scopes.
951 for (int i = 0; i < inner_scopes_.length(); i++) { 950 for (int i = 0; i < inner_scopes_.length(); i++) {
952 inner_scopes_[i]->AllocateVariablesRecursively(); 951 inner_scopes_[i]->AllocateVariablesRecursively();
953 } 952 }
954 953
954 // If scope is already resolved, we still need to allocate
955 // variables in inner scopes which might not had been resolved yet.
956 if (resolved_) return;
957 // The number of slots required for variables.
958 num_stack_slots_ = 0;
959 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
960
955 // Allocate variables for this scope. 961 // Allocate variables for this scope.
956 // Parameters must be allocated first, if any. 962 // Parameters must be allocated first, if any.
957 if (is_function_scope()) AllocateParameterLocals(); 963 if (is_function_scope()) AllocateParameterLocals();
958 AllocateNonParameterLocals(); 964 AllocateNonParameterLocals();
959 965
960 // Allocate context if necessary. 966 // Allocate context if necessary.
961 bool must_have_local_context = false; 967 bool must_have_local_context = false;
962 if (scope_calls_eval_ || scope_contains_with_) { 968 if (scope_calls_eval_ || scope_contains_with_) {
963 // The context for the eval() call or 'with' statement in this scope. 969 // The context for the eval() call or 'with' statement in this scope.
964 // Unless we are in the global or an eval scope, we need a local 970 // Unless we are in the global or an eval scope, we need a local
965 // context even if we didn't statically allocate any locals in it, 971 // context even if we didn't statically allocate any locals in it,
966 // and the compiler will access the context variable. If we are 972 // and the compiler will access the context variable. If we are
967 // not in an inner scope, the scope is provided from the outside. 973 // not in an inner scope, the scope is provided from the outside.
968 must_have_local_context = is_function_scope(); 974 must_have_local_context = is_function_scope();
969 } 975 }
970 976
971 // If we didn't allocate any locals in the local context, then we only 977 // If we didn't allocate any locals in the local context, then we only
972 // need the minimal number of slots if we must have a local context. 978 // need the minimal number of slots if we must have a local context.
973 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && 979 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
974 !must_have_local_context) { 980 !must_have_local_context) {
975 num_heap_slots_ = 0; 981 num_heap_slots_ = 0;
976 } 982 }
977 983
978 // Allocation done. 984 // Allocation done.
979 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); 985 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
980 } 986 }
981 987
982 } } // namespace v8::internal 988 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698