| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |