| 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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 return NULL; | 105 return NULL; |
| 106 } | 106 } |
| 107 | 107 |
| 108 | 108 |
| 109 // ---------------------------------------------------------------------------- | 109 // ---------------------------------------------------------------------------- |
| 110 // Implementation of Scope | 110 // Implementation of Scope |
| 111 | 111 |
| 112 | 112 |
| 113 // Dummy constructor | 113 // Dummy constructor |
| 114 Scope::Scope(Type type) | 114 Scope::Scope(Type type) |
| 115 : outer_scope_(NULL), | 115 : inner_scopes_(0), |
| 116 inner_scopes_(0), | |
| 117 type_(type), | |
| 118 scope_name_(Factory::empty_symbol()), | |
| 119 variables_(false), | 116 variables_(false), |
| 120 temps_(0), | 117 temps_(0), |
| 121 params_(0), | 118 params_(0), |
| 122 dynamics_(NULL), | |
| 123 unresolved_(0), | 119 unresolved_(0), |
| 124 decls_(0), | 120 decls_(0) { |
| 125 receiver_(NULL), | 121 SetDefaults(type, NULL, NULL); |
| 126 function_(NULL), | 122 ASSERT(!resolved()); |
| 127 arguments_(NULL), | |
| 128 arguments_shadow_(NULL), | |
| 129 illegal_redecl_(NULL), | |
| 130 scope_inside_with_(false), | |
| 131 scope_contains_with_(false), | |
| 132 scope_calls_eval_(false), | |
| 133 outer_scope_calls_eval_(false), | |
| 134 inner_scope_calls_eval_(false), | |
| 135 outer_scope_is_eval_scope_(false), | |
| 136 force_eager_compilation_(false), | |
| 137 num_stack_slots_(0), | |
| 138 num_heap_slots_(0) { | |
| 139 } | 123 } |
| 140 | 124 |
| 141 | 125 |
| 142 Scope::Scope(Scope* outer_scope, Type type) | 126 Scope::Scope(Scope* outer_scope, Type type) |
| 143 : outer_scope_(outer_scope), | 127 : inner_scopes_(4), |
| 144 inner_scopes_(4), | 128 variables_(), |
| 145 type_(type), | |
| 146 scope_name_(Factory::empty_symbol()), | |
| 147 temps_(4), | 129 temps_(4), |
| 148 params_(4), | 130 params_(4), |
| 149 dynamics_(NULL), | |
| 150 unresolved_(16), | 131 unresolved_(16), |
| 151 decls_(4), | 132 decls_(4) { |
| 152 receiver_(NULL), | |
| 153 function_(NULL), | |
| 154 arguments_(NULL), | |
| 155 arguments_shadow_(NULL), | |
| 156 illegal_redecl_(NULL), | |
| 157 scope_inside_with_(false), | |
| 158 scope_contains_with_(false), | |
| 159 scope_calls_eval_(false), | |
| 160 outer_scope_calls_eval_(false), | |
| 161 inner_scope_calls_eval_(false), | |
| 162 outer_scope_is_eval_scope_(false), | |
| 163 force_eager_compilation_(false), | |
| 164 num_stack_slots_(0), | |
| 165 num_heap_slots_(0) { | |
| 166 // At some point we might want to provide outer scopes to | 133 // At some point we might want to provide outer scopes to |
| 167 // eval scopes (by walking the stack and reading the scope info). | 134 // eval scopes (by walking the stack and reading the scope info). |
| 168 // In that case, the ASSERT below needs to be adjusted. | 135 // In that case, the ASSERT below needs to be adjusted. |
| 136 SetDefaults(type, outer_scope, NULL); |
| 169 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL)); | 137 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL)); |
| 170 ASSERT(!HasIllegalRedeclaration()); | 138 ASSERT(!HasIllegalRedeclaration()); |
| 139 ASSERT(!resolved()); |
| 171 } | 140 } |
| 172 | 141 |
| 173 | 142 |
| 143 Scope::Scope(Scope* inner_scope, SerializedScopeInfo* scope_info) |
| 144 : inner_scopes_(4), |
| 145 variables_(), |
| 146 temps_(4), |
| 147 params_(4), |
| 148 unresolved_(16), |
| 149 decls_(4) { |
| 150 ASSERT(scope_info != NULL); |
| 151 SetDefaults(FUNCTION_SCOPE, inner_scope->outer_scope(), scope_info); |
| 152 ASSERT(resolved()); |
| 153 InsertAfterScope(inner_scope); |
| 154 if (scope_info->HasHeapAllocatedLocals()) { |
| 155 num_heap_slots_ = scope_info_->NumberOfContextSlots(); |
| 156 } |
| 157 } |
| 158 |
| 159 |
| 160 |
| 174 bool Scope::Analyze(CompilationInfo* info) { | 161 bool Scope::Analyze(CompilationInfo* info) { |
| 175 ASSERT(info->function() != NULL); | 162 ASSERT(info->function() != NULL); |
| 176 Scope* top = info->function()->scope(); | 163 Scope* top = info->function()->scope(); |
| 164 |
| 165 // If we have a serialized scope info, reuse it. |
| 166 if (!info->closure().is_null()) { |
| 167 SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info(); |
| 168 if (scope_info != SerializedScopeInfo::Empty()) { |
| 169 Scope* scope = top; |
| 170 JSFunction* current = *info->closure(); |
| 171 do { |
| 172 current = current->context()->closure(); |
| 173 SerializedScopeInfo* scope_info = current->shared()->scope_info(); |
| 174 if (scope_info != SerializedScopeInfo::Empty()) { |
| 175 scope = new Scope(scope, scope_info); |
| 176 } else { |
| 177 ASSERT(current->context()->IsGlobalContext()); |
| 178 } |
| 179 } while (!current->context()->IsGlobalContext()); |
| 180 } |
| 181 } |
| 182 |
| 177 while (top->outer_scope() != NULL) top = top->outer_scope(); | 183 while (top->outer_scope() != NULL) top = top->outer_scope(); |
| 178 top->AllocateVariables(info->calling_context()); | 184 top->AllocateVariables(info->calling_context()); |
| 179 | 185 |
| 180 #ifdef DEBUG | 186 #ifdef DEBUG |
| 181 if (Bootstrapper::IsActive() | 187 if (Bootstrapper::IsActive() |
| 182 ? FLAG_print_builtin_scopes | 188 ? FLAG_print_builtin_scopes |
| 183 : FLAG_print_scopes) { | 189 : FLAG_print_scopes) { |
| 184 info->function()->scope()->Print(); | 190 info->function()->scope()->Print(); |
| 185 } | 191 } |
| 186 #endif | 192 #endif |
| 187 | 193 |
| 188 info->SetScope(info->function()->scope()); | 194 info->SetScope(info->function()->scope()); |
| 189 return true; // Can not fail. | 195 return true; // Can not fail. |
| 190 } | 196 } |
| 191 | 197 |
| 192 | 198 |
| 193 void Scope::Initialize(bool inside_with) { | 199 void Scope::Initialize(bool inside_with) { |
| 200 ASSERT(!resolved()); |
| 201 |
| 194 // Add this scope as a new inner scope of the outer scope. | 202 // Add this scope as a new inner scope of the outer scope. |
| 195 if (outer_scope_ != NULL) { | 203 if (outer_scope_ != NULL) { |
| 196 outer_scope_->inner_scopes_.Add(this); | 204 outer_scope_->inner_scopes_.Add(this); |
| 197 scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with; | 205 scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with; |
| 198 } else { | 206 } else { |
| 199 scope_inside_with_ = inside_with; | 207 scope_inside_with_ = inside_with; |
| 200 } | 208 } |
| 201 | 209 |
| 202 // Declare convenience variables. | 210 // Declare convenience variables. |
| 203 // Declare and allocate receiver (even for the global scope, and even | 211 // Declare and allocate receiver (even for the global scope, and even |
| 204 // if naccesses_ == 0). | 212 // if naccesses_ == 0). |
| 205 // NOTE: When loading parameters in the global scope, we must take | 213 // NOTE: When loading parameters in the global scope, we must take |
| 206 // care not to access them as properties of the global object, but | 214 // care not to access them as properties of the global object, but |
| 207 // instead load them directly from the stack. Currently, the only | 215 // instead load them directly from the stack. Currently, the only |
| 208 // such parameter is 'this' which is passed on the stack when | 216 // such parameter is 'this' which is passed on the stack when |
| 209 // invoking scripts | 217 // invoking scripts |
| 210 Variable* var = | 218 Variable* var = |
| 211 variables_.Declare(this, Factory::this_symbol(), Variable::VAR, | 219 variables_.Declare(this, Factory::this_symbol(), Variable::VAR, |
| 212 false, Variable::THIS); | 220 false, Variable::THIS); |
| 213 var->rewrite_ = new Slot(var, Slot::PARAMETER, -1); | 221 var->set_rewrite(new Slot(var, Slot::PARAMETER, -1)); |
| 214 receiver_ = var; | 222 receiver_ = var; |
| 215 | 223 |
| 216 if (is_function_scope()) { | 224 if (is_function_scope()) { |
| 217 // Declare 'arguments' variable which exists in all functions. | 225 // Declare 'arguments' variable which exists in all functions. |
| 218 // Note that it might never be accessed, in which case it won't be | 226 // Note that it might never be accessed, in which case it won't be |
| 219 // allocated during variable allocation. | 227 // allocated during variable allocation. |
| 220 variables_.Declare(this, Factory::arguments_symbol(), Variable::VAR, | 228 variables_.Declare(this, Factory::arguments_symbol(), Variable::VAR, |
| 221 true, Variable::ARGUMENTS); | 229 true, Variable::ARGUMENTS); |
| 222 } | 230 } |
| 223 } | 231 } |
| 224 | 232 |
| 225 | 233 |
| 226 Variable* Scope::LocalLookup(Handle<String> name) { | 234 Variable* Scope::LocalLookup(Handle<String> name) { |
| 227 return variables_.Lookup(name); | 235 if (!resolved()) { |
| 236 return variables_.Lookup(name); |
| 237 } |
| 238 |
| 239 // Check arguments object lookup. |
| 240 if (*name == *Factory::arguments_symbol()) { |
| 241 return new Variable(this, name, Variable::VAR, true, Variable::ARGUMENTS); |
| 242 } |
| 243 |
| 244 // Check context slot lookup. |
| 245 Variable::Mode mode; |
| 246 int index = scope_info_->ContextSlotIndex(*name, &mode); |
| 247 if (index < 0) { |
| 248 return NULL; |
| 249 } |
| 250 |
| 251 Variable* var = new Variable(this, name, mode, true, Variable::NORMAL); |
| 252 var->set_rewrite(new Slot(var, Slot::CONTEXT, index)); |
| 253 return var; |
| 228 } | 254 } |
| 229 | 255 |
| 230 | 256 |
| 231 Variable* Scope::Lookup(Handle<String> name) { | 257 Variable* Scope::Lookup(Handle<String> name) { |
| 232 for (Scope* scope = this; | 258 for (Scope* scope = this; |
| 233 scope != NULL; | 259 scope != NULL; |
| 234 scope = scope->outer_scope()) { | 260 scope = scope->outer_scope()) { |
| 235 Variable* var = scope->LocalLookup(name); | 261 Variable* var = scope->LocalLookup(name); |
| 236 if (var != NULL) return var; | 262 if (var != NULL) return var; |
| 237 } | 263 } |
| 238 return NULL; | 264 return NULL; |
| 239 } | 265 } |
| 240 | 266 |
| 241 | 267 |
| 242 Variable* Scope::DeclareFunctionVar(Handle<String> name) { | 268 Variable* Scope::DeclareFunctionVar(Handle<String> name) { |
| 243 ASSERT(is_function_scope() && function_ == NULL); | 269 ASSERT(is_function_scope() && function_ == NULL); |
| 244 function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL); | 270 function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL); |
| 245 return function_; | 271 return function_; |
| 246 } | 272 } |
| 247 | 273 |
| 248 | 274 |
| 249 Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) { | 275 Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) { |
| 250 // DYNAMIC variables are introduces during variable allocation, | 276 // DYNAMIC variables are introduces during variable allocation, |
| 251 // INTERNAL variables are allocated explicitly, and TEMPORARY | 277 // INTERNAL variables are allocated explicitly, and TEMPORARY |
| 252 // variables are allocated via NewTemporary(). | 278 // variables are allocated via NewTemporary(). |
| 279 ASSERT(!resolved()); |
| 253 ASSERT(mode == Variable::VAR || mode == Variable::CONST); | 280 ASSERT(mode == Variable::VAR || mode == Variable::CONST); |
| 254 return variables_.Declare(this, name, mode, true, Variable::NORMAL); | 281 return variables_.Declare(this, name, mode, true, Variable::NORMAL); |
| 255 } | 282 } |
| 256 | 283 |
| 257 | 284 |
| 258 Variable* Scope::DeclareGlobal(Handle<String> name) { | 285 Variable* Scope::DeclareGlobal(Handle<String> name) { |
| 259 ASSERT(is_global_scope()); | 286 ASSERT(is_global_scope()); |
| 260 return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true, | 287 return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true, |
| 261 Variable::NORMAL); | 288 Variable::NORMAL); |
| 262 } | 289 } |
| 263 | 290 |
| 264 | 291 |
| 265 void Scope::AddParameter(Variable* var) { | 292 void Scope::AddParameter(Variable* var) { |
| 266 ASSERT(is_function_scope()); | 293 ASSERT(is_function_scope()); |
| 267 ASSERT(LocalLookup(var->name()) == var); | 294 ASSERT(LocalLookup(var->name()) == var); |
| 268 params_.Add(var); | 295 params_.Add(var); |
| 269 } | 296 } |
| 270 | 297 |
| 271 | 298 |
| 272 VariableProxy* Scope::NewUnresolved(Handle<String> name, bool inside_with) { | 299 VariableProxy* Scope::NewUnresolved(Handle<String> name, bool inside_with) { |
| 273 // Note that we must not share the unresolved variables with | 300 // Note that we must not share the unresolved variables with |
| 274 // the same name because they may be removed selectively via | 301 // the same name because they may be removed selectively via |
| 275 // RemoveUnresolved(). | 302 // RemoveUnresolved(). |
| 303 ASSERT(!resolved()); |
| 276 VariableProxy* proxy = new VariableProxy(name, false, inside_with); | 304 VariableProxy* proxy = new VariableProxy(name, false, inside_with); |
| 277 unresolved_.Add(proxy); | 305 unresolved_.Add(proxy); |
| 278 return proxy; | 306 return proxy; |
| 279 } | 307 } |
| 280 | 308 |
| 281 | 309 |
| 282 void Scope::RemoveUnresolved(VariableProxy* var) { | 310 void Scope::RemoveUnresolved(VariableProxy* var) { |
| 283 // Most likely (always?) any variable we want to remove | 311 // Most likely (always?) any variable we want to remove |
| 284 // was just added before, so we search backwards. | 312 // was just added before, so we search backwards. |
| 285 for (int i = unresolved_.length(); i-- > 0;) { | 313 for (int i = unresolved_.length(); i-- > 0;) { |
| 286 if (unresolved_[i] == var) { | 314 if (unresolved_[i] == var) { |
| 287 unresolved_.Remove(i); | 315 unresolved_.Remove(i); |
| 288 return; | 316 return; |
| 289 } | 317 } |
| 290 } | 318 } |
| 291 } | 319 } |
| 292 | 320 |
| 293 | 321 |
| 294 Variable* Scope::NewTemporary(Handle<String> name) { | 322 Variable* Scope::NewTemporary(Handle<String> name) { |
| 323 ASSERT(!resolved()); |
| 295 Variable* var = | 324 Variable* var = |
| 296 new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL); | 325 new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL); |
| 297 temps_.Add(var); | 326 temps_.Add(var); |
| 298 return var; | 327 return var; |
| 299 } | 328 } |
| 300 | 329 |
| 301 | 330 |
| 302 void Scope::AddDeclaration(Declaration* declaration) { | 331 void Scope::AddDeclaration(Declaration* declaration) { |
| 303 decls_.Add(declaration); | 332 decls_.Add(declaration); |
| 304 } | 333 } |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 | 572 |
| 544 | 573 |
| 545 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { | 574 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { |
| 546 if (dynamics_ == NULL) dynamics_ = new DynamicScopePart(); | 575 if (dynamics_ == NULL) dynamics_ = new DynamicScopePart(); |
| 547 VariableMap* map = dynamics_->GetMap(mode); | 576 VariableMap* map = dynamics_->GetMap(mode); |
| 548 Variable* var = map->Lookup(name); | 577 Variable* var = map->Lookup(name); |
| 549 if (var == NULL) { | 578 if (var == NULL) { |
| 550 // Declare a new non-local. | 579 // Declare a new non-local. |
| 551 var = map->Declare(NULL, name, mode, true, Variable::NORMAL); | 580 var = map->Declare(NULL, name, mode, true, Variable::NORMAL); |
| 552 // Allocate it by giving it a dynamic lookup. | 581 // Allocate it by giving it a dynamic lookup. |
| 553 var->rewrite_ = new Slot(var, Slot::LOOKUP, -1); | 582 var->set_rewrite(new Slot(var, Slot::LOOKUP, -1)); |
| 554 } | 583 } |
| 555 return var; | 584 return var; |
| 556 } | 585 } |
| 557 | 586 |
| 558 | 587 |
| 559 // Lookup a variable starting with this scope. The result is either | 588 // Lookup a variable starting with this scope. The result is either |
| 560 // the statically resolved variable belonging to an outer scope, or | 589 // 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) | 590 // 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 | 591 // because the variable is just a guess (and may be shadowed by |
| 563 // another variable that is introduced dynamically via an 'eval' call | 592 // another variable that is introduced dynamically via an 'eval' call |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 } | 634 } |
| 606 | 635 |
| 607 // If we did not find a variable, we are done. | 636 // If we did not find a variable, we are done. |
| 608 if (var == NULL) | 637 if (var == NULL) |
| 609 return NULL; | 638 return NULL; |
| 610 } | 639 } |
| 611 | 640 |
| 612 ASSERT(var != NULL); | 641 ASSERT(var != NULL); |
| 613 | 642 |
| 614 // If this is a lookup from an inner scope, mark the variable. | 643 // If this is a lookup from an inner scope, mark the variable. |
| 615 if (inner_lookup) | 644 if (inner_lookup) { |
| 616 var->is_accessed_from_inner_scope_ = true; | 645 var->MarkAsAccessedFromInnerScope(); |
| 646 } |
| 617 | 647 |
| 618 // If the variable we have found is just a guess, invalidate the | 648 // 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 | 649 // 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. | 650 // can generate fast code to get it if it is not shadowed by eval. |
| 621 if (guess) { | 651 if (guess) { |
| 622 if (!var->is_global()) *invalidated_local = var; | 652 if (!var->is_global()) *invalidated_local = var; |
| 623 var = NULL; | 653 var = NULL; |
| 624 } | 654 } |
| 625 | 655 |
| 626 return var; | 656 return var; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 746 | 776 |
| 747 return scope_calls_eval_ || inner_scope_calls_eval_; | 777 return scope_calls_eval_ || inner_scope_calls_eval_; |
| 748 } | 778 } |
| 749 | 779 |
| 750 | 780 |
| 751 bool Scope::MustAllocate(Variable* var) { | 781 bool Scope::MustAllocate(Variable* var) { |
| 752 // Give var a read/write use if there is a chance it might be accessed | 782 // 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 | 783 // via an eval() call. This is only possible if the variable has a |
| 754 // visible name. | 784 // visible name. |
| 755 if ((var->is_this() || var->name()->length() > 0) && | 785 if ((var->is_this() || var->name()->length() > 0) && |
| 756 (var->is_accessed_from_inner_scope_ || | 786 (var->is_accessed_from_inner_scope() || |
| 757 scope_calls_eval_ || inner_scope_calls_eval_ || | 787 scope_calls_eval_ || inner_scope_calls_eval_ || |
| 758 scope_contains_with_)) { | 788 scope_contains_with_)) { |
| 759 var->set_is_used(true); | 789 var->set_is_used(true); |
| 760 } | 790 } |
| 761 // Global variables do not need to be allocated. | 791 // Global variables do not need to be allocated. |
| 762 return !var->is_global() && var->is_used(); | 792 return !var->is_global() && var->is_used(); |
| 763 } | 793 } |
| 764 | 794 |
| 765 | 795 |
| 766 bool Scope::MustAllocateInContext(Variable* var) { | 796 bool Scope::MustAllocateInContext(Variable* var) { |
| 767 // If var is accessed from an inner scope, or if there is a | 797 // 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 | 798 // possibility that it might be accessed from the current or an inner |
| 769 // scope (through an eval() call), it must be allocated in the | 799 // scope (through an eval() call), it must be allocated in the |
| 770 // context. Exception: temporary variables are not allocated in the | 800 // context. Exception: temporary variables are not allocated in the |
| 771 // context. | 801 // context. |
| 772 return | 802 return |
| 773 var->mode() != Variable::TEMPORARY && | 803 var->mode() != Variable::TEMPORARY && |
| 774 (var->is_accessed_from_inner_scope_ || | 804 (var->is_accessed_from_inner_scope() || |
| 775 scope_calls_eval_ || inner_scope_calls_eval_ || | 805 scope_calls_eval_ || inner_scope_calls_eval_ || |
| 776 scope_contains_with_ || var->is_global()); | 806 scope_contains_with_ || var->is_global()); |
| 777 } | 807 } |
| 778 | 808 |
| 779 | 809 |
| 780 bool Scope::HasArgumentsParameter() { | 810 bool Scope::HasArgumentsParameter() { |
| 781 for (int i = 0; i < params_.length(); i++) { | 811 for (int i = 0; i < params_.length(); i++) { |
| 782 if (params_[i]->name().is_identical_to(Factory::arguments_symbol())) | 812 if (params_[i]->name().is_identical_to(Factory::arguments_symbol())) |
| 783 return true; | 813 return true; |
| 784 } | 814 } |
| 785 return false; | 815 return false; |
| 786 } | 816 } |
| 787 | 817 |
| 788 | 818 |
| 789 void Scope::AllocateStackSlot(Variable* var) { | 819 void Scope::AllocateStackSlot(Variable* var) { |
| 790 var->rewrite_ = new Slot(var, Slot::LOCAL, num_stack_slots_++); | 820 var->set_rewrite(new Slot(var, Slot::LOCAL, num_stack_slots_++)); |
| 791 } | 821 } |
| 792 | 822 |
| 793 | 823 |
| 794 void Scope::AllocateHeapSlot(Variable* var) { | 824 void Scope::AllocateHeapSlot(Variable* var) { |
| 795 var->rewrite_ = new Slot(var, Slot::CONTEXT, num_heap_slots_++); | 825 var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++)); |
| 796 } | 826 } |
| 797 | 827 |
| 798 | 828 |
| 799 void Scope::AllocateParameterLocals() { | 829 void Scope::AllocateParameterLocals() { |
| 800 ASSERT(is_function_scope()); | 830 ASSERT(is_function_scope()); |
| 801 Variable* arguments = LocalLookup(Factory::arguments_symbol()); | 831 Variable* arguments = LocalLookup(Factory::arguments_symbol()); |
| 802 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly | 832 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly |
| 803 if (MustAllocate(arguments) && !HasArgumentsParameter()) { | 833 if (MustAllocate(arguments) && !HasArgumentsParameter()) { |
| 804 // 'arguments' is used. Unless there is also a parameter called | 834 // 'arguments' is used. Unless there is also a parameter called |
| 805 // 'arguments', we must be conservative and access all parameters via | 835 // 'arguments', we must be conservative and access all parameters via |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 | 880 |
| 851 // Allocate the parameters by rewriting them into '.arguments[i]' accesses. | 881 // Allocate the parameters by rewriting them into '.arguments[i]' accesses. |
| 852 for (int i = 0; i < params_.length(); i++) { | 882 for (int i = 0; i < params_.length(); i++) { |
| 853 Variable* var = params_[i]; | 883 Variable* var = params_[i]; |
| 854 ASSERT(var->scope() == this); | 884 ASSERT(var->scope() == this); |
| 855 if (MustAllocate(var)) { | 885 if (MustAllocate(var)) { |
| 856 if (MustAllocateInContext(var)) { | 886 if (MustAllocateInContext(var)) { |
| 857 // It is ok to set this only now, because arguments is a local | 887 // It is ok to set this only now, because arguments is a local |
| 858 // variable that is allocated after the parameters have been | 888 // variable that is allocated after the parameters have been |
| 859 // allocated. | 889 // allocated. |
| 860 arguments_shadow_->is_accessed_from_inner_scope_ = true; | 890 arguments_shadow_->MarkAsAccessedFromInnerScope(); |
| 861 } | 891 } |
| 862 Property* rewrite = | 892 Property* rewrite = |
| 863 new Property(new VariableProxy(arguments_shadow_), | 893 new Property(new VariableProxy(arguments_shadow_), |
| 864 new Literal(Handle<Object>(Smi::FromInt(i))), | 894 new Literal(Handle<Object>(Smi::FromInt(i))), |
| 865 RelocInfo::kNoPosition, | 895 RelocInfo::kNoPosition, |
| 866 Property::SYNTHETIC); | 896 Property::SYNTHETIC); |
| 867 rewrite->set_is_arguments_access(true); | 897 rewrite->set_is_arguments_access(true); |
| 868 var->rewrite_ = rewrite; | 898 var->set_rewrite(rewrite); |
| 869 } | 899 } |
| 870 } | 900 } |
| 871 | 901 |
| 872 } else { | 902 } else { |
| 873 // The arguments object is not used, so we can access parameters directly. | 903 // The arguments object is not used, so we can access parameters directly. |
| 874 // The same parameter may occur multiple times in the parameters_ list. | 904 // 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 | 905 // 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 | 906 // receive the highest parameter index for that parameter; thus iteration |
| 877 // order is relevant! | 907 // order is relevant! |
| 878 for (int i = 0; i < params_.length(); i++) { | 908 for (int i = 0; i < params_.length(); i++) { |
| 879 Variable* var = params_[i]; | 909 Variable* var = params_[i]; |
| 880 ASSERT(var->scope() == this); | 910 ASSERT(var->scope() == this); |
| 881 if (MustAllocate(var)) { | 911 if (MustAllocate(var)) { |
| 882 if (MustAllocateInContext(var)) { | 912 if (MustAllocateInContext(var)) { |
| 883 ASSERT(var->rewrite_ == NULL || | 913 ASSERT(var->rewrite() == NULL || |
| 884 (var->AsSlot() != NULL && | 914 (var->AsSlot() != NULL && |
| 885 var->AsSlot()->type() == Slot::CONTEXT)); | 915 var->AsSlot()->type() == Slot::CONTEXT)); |
| 886 if (var->rewrite_ == NULL) { | 916 if (var->rewrite() == NULL) { |
| 887 // Only set the heap allocation if the parameter has not | 917 // Only set the heap allocation if the parameter has not |
| 888 // been allocated yet. | 918 // been allocated yet. |
| 889 AllocateHeapSlot(var); | 919 AllocateHeapSlot(var); |
| 890 } | 920 } |
| 891 } else { | 921 } else { |
| 892 ASSERT(var->rewrite_ == NULL || | 922 ASSERT(var->rewrite() == NULL || |
| 893 (var->AsSlot() != NULL && | 923 (var->AsSlot() != NULL && |
| 894 var->AsSlot()->type() == Slot::PARAMETER)); | 924 var->AsSlot()->type() == Slot::PARAMETER)); |
| 895 // Set the parameter index always, even if the parameter | 925 // Set the parameter index always, even if the parameter |
| 896 // was seen before! (We need to access the actual parameter | 926 // was seen before! (We need to access the actual parameter |
| 897 // supplied for the last occurrence of a multiply declared | 927 // supplied for the last occurrence of a multiply declared |
| 898 // parameter.) | 928 // parameter.) |
| 899 var->rewrite_ = new Slot(var, Slot::PARAMETER, i); | 929 var->set_rewrite(new Slot(var, Slot::PARAMETER, i)); |
| 900 } | 930 } |
| 901 } | 931 } |
| 902 } | 932 } |
| 903 } | 933 } |
| 904 } | 934 } |
| 905 | 935 |
| 906 | 936 |
| 907 void Scope::AllocateNonParameterLocal(Variable* var) { | 937 void Scope::AllocateNonParameterLocal(Variable* var) { |
| 908 ASSERT(var->scope() == this); | 938 ASSERT(var->scope() == this); |
| 909 ASSERT(var->rewrite_ == NULL || | 939 ASSERT(var->rewrite() == NULL || |
| 910 (!var->IsVariable(Factory::result_symbol())) || | 940 (!var->IsVariable(Factory::result_symbol())) || |
| 911 (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL)); | 941 (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL)); |
| 912 if (var->rewrite_ == NULL && MustAllocate(var)) { | 942 if (var->rewrite() == NULL && MustAllocate(var)) { |
| 913 if (MustAllocateInContext(var)) { | 943 if (MustAllocateInContext(var)) { |
| 914 AllocateHeapSlot(var); | 944 AllocateHeapSlot(var); |
| 915 } else { | 945 } else { |
| 916 AllocateStackSlot(var); | 946 AllocateStackSlot(var); |
| 917 } | 947 } |
| 918 } | 948 } |
| 919 } | 949 } |
| 920 | 950 |
| 921 | 951 |
| 922 void Scope::AllocateNonParameterLocals() { | 952 void Scope::AllocateNonParameterLocals() { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 936 // allocated in the context, it must be the last slot in the context, | 966 // allocated in the context, it must be the last slot in the context, |
| 937 // because of the current ScopeInfo implementation (see | 967 // because of the current ScopeInfo implementation (see |
| 938 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). | 968 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). |
| 939 if (function_ != NULL) { | 969 if (function_ != NULL) { |
| 940 AllocateNonParameterLocal(function_); | 970 AllocateNonParameterLocal(function_); |
| 941 } | 971 } |
| 942 } | 972 } |
| 943 | 973 |
| 944 | 974 |
| 945 void Scope::AllocateVariablesRecursively() { | 975 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. | 976 // Allocate variables for inner scopes. |
| 951 for (int i = 0; i < inner_scopes_.length(); i++) { | 977 for (int i = 0; i < inner_scopes_.length(); i++) { |
| 952 inner_scopes_[i]->AllocateVariablesRecursively(); | 978 inner_scopes_[i]->AllocateVariablesRecursively(); |
| 953 } | 979 } |
| 954 | 980 |
| 981 // If scope is already resolved, we still need to allocate |
| 982 // variables in inner scopes which might not had been resolved yet. |
| 983 if (resolved()) return; |
| 984 // The number of slots required for variables. |
| 985 num_stack_slots_ = 0; |
| 986 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |
| 987 |
| 955 // Allocate variables for this scope. | 988 // Allocate variables for this scope. |
| 956 // Parameters must be allocated first, if any. | 989 // Parameters must be allocated first, if any. |
| 957 if (is_function_scope()) AllocateParameterLocals(); | 990 if (is_function_scope()) AllocateParameterLocals(); |
| 958 AllocateNonParameterLocals(); | 991 AllocateNonParameterLocals(); |
| 959 | 992 |
| 960 // Allocate context if necessary. | 993 // Allocate context if necessary. |
| 961 bool must_have_local_context = false; | 994 bool must_have_local_context = false; |
| 962 if (scope_calls_eval_ || scope_contains_with_) { | 995 if (scope_calls_eval_ || scope_contains_with_) { |
| 963 // The context for the eval() call or 'with' statement in this scope. | 996 // 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 | 997 // 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, | 998 // context even if we didn't statically allocate any locals in it, |
| 966 // and the compiler will access the context variable. If we are | 999 // and the compiler will access the context variable. If we are |
| 967 // not in an inner scope, the scope is provided from the outside. | 1000 // not in an inner scope, the scope is provided from the outside. |
| 968 must_have_local_context = is_function_scope(); | 1001 must_have_local_context = is_function_scope(); |
| 969 } | 1002 } |
| 970 | 1003 |
| 971 // If we didn't allocate any locals in the local context, then we only | 1004 // 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. | 1005 // need the minimal number of slots if we must have a local context. |
| 973 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 1006 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && |
| 974 !must_have_local_context) { | 1007 !must_have_local_context) { |
| 975 num_heap_slots_ = 0; | 1008 num_heap_slots_ = 0; |
| 976 } | 1009 } |
| 977 | 1010 |
| 978 // Allocation done. | 1011 // Allocation done. |
| 979 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 1012 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
| 980 } | 1013 } |
| 981 | 1014 |
| 982 } } // namespace v8::internal | 1015 } } // namespace v8::internal |
| OLD | NEW |