| 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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 return NULL; | 107 return NULL; |
| 108 } | 108 } |
| 109 | 109 |
| 110 | 110 |
| 111 // ---------------------------------------------------------------------------- | 111 // ---------------------------------------------------------------------------- |
| 112 // Implementation of Scope | 112 // Implementation of Scope |
| 113 | 113 |
| 114 | 114 |
| 115 // Dummy constructor | 115 // Dummy constructor |
| 116 Scope::Scope(Type type) | 116 Scope::Scope(Type type) |
| 117 : outer_scope_(NULL), | 117 : inner_scopes_(0), |
| 118 inner_scopes_(0), | |
| 119 type_(type), | |
| 120 scope_name_(FACTORY->empty_symbol()), | |
| 121 variables_(false), | 118 variables_(false), |
| 122 temps_(0), | 119 temps_(0), |
| 123 params_(0), | 120 params_(0), |
| 124 dynamics_(NULL), | |
| 125 unresolved_(0), | 121 unresolved_(0), |
| 126 decls_(0), | 122 decls_(0) { |
| 127 receiver_(NULL), | 123 SetDefaults(type, NULL, NULL); |
| 128 function_(NULL), | 124 ASSERT(!resolved()); |
| 129 arguments_(NULL), | |
| 130 arguments_shadow_(NULL), | |
| 131 illegal_redecl_(NULL), | |
| 132 scope_inside_with_(false), | |
| 133 scope_contains_with_(false), | |
| 134 scope_calls_eval_(false), | |
| 135 outer_scope_calls_eval_(false), | |
| 136 inner_scope_calls_eval_(false), | |
| 137 outer_scope_is_eval_scope_(false), | |
| 138 force_eager_compilation_(false), | |
| 139 num_stack_slots_(0), | |
| 140 num_heap_slots_(0) { | |
| 141 } | 125 } |
| 142 | 126 |
| 143 | 127 |
| 144 Scope::Scope(Scope* outer_scope, Type type) | 128 Scope::Scope(Scope* outer_scope, Type type) |
| 145 : outer_scope_(outer_scope), | 129 : inner_scopes_(4), |
| 146 inner_scopes_(4), | 130 variables_(), |
| 147 type_(type), | |
| 148 scope_name_(FACTORY->empty_symbol()), | |
| 149 temps_(4), | 131 temps_(4), |
| 150 params_(4), | 132 params_(4), |
| 151 dynamics_(NULL), | |
| 152 unresolved_(16), | 133 unresolved_(16), |
| 153 decls_(4), | 134 decls_(4) { |
| 154 receiver_(NULL), | 135 SetDefaults(type, outer_scope, NULL); |
| 155 function_(NULL), | |
| 156 arguments_(NULL), | |
| 157 arguments_shadow_(NULL), | |
| 158 illegal_redecl_(NULL), | |
| 159 scope_inside_with_(false), | |
| 160 scope_contains_with_(false), | |
| 161 scope_calls_eval_(false), | |
| 162 outer_scope_calls_eval_(false), | |
| 163 inner_scope_calls_eval_(false), | |
| 164 outer_scope_is_eval_scope_(false), | |
| 165 force_eager_compilation_(false), | |
| 166 num_stack_slots_(0), | |
| 167 num_heap_slots_(0) { | |
| 168 // At some point we might want to provide outer scopes to | 136 // At some point we might want to provide outer scopes to |
| 169 // eval scopes (by walking the stack and reading the scope info). | 137 // eval scopes (by walking the stack and reading the scope info). |
| 170 // In that case, the ASSERT below needs to be adjusted. | 138 // In that case, the ASSERT below needs to be adjusted. |
| 171 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL)); | 139 ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL)); |
| 172 ASSERT(!HasIllegalRedeclaration()); | 140 ASSERT(!HasIllegalRedeclaration()); |
| 141 ASSERT(!resolved()); |
| 173 } | 142 } |
| 174 | 143 |
| 175 | 144 |
| 145 Scope::Scope(Scope* inner_scope, SerializedScopeInfo* scope_info) |
| 146 : inner_scopes_(4), |
| 147 variables_(), |
| 148 temps_(4), |
| 149 params_(4), |
| 150 unresolved_(16), |
| 151 decls_(4) { |
| 152 ASSERT(scope_info != NULL); |
| 153 SetDefaults(FUNCTION_SCOPE, inner_scope->outer_scope(), scope_info); |
| 154 ASSERT(resolved()); |
| 155 InsertAfterScope(inner_scope); |
| 156 if (scope_info->HasHeapAllocatedLocals()) { |
| 157 num_heap_slots_ = scope_info_->NumberOfContextSlots(); |
| 158 } |
| 159 |
| 160 // This scope's arguments shadow (if present) is context-allocated if an inner |
| 161 // scope accesses this one's parameters. Allocate the arguments_shadow_ |
| 162 // variable if necessary. |
| 163 Isolate* isolate = Isolate::Current(); |
| 164 Variable::Mode mode; |
| 165 int arguments_shadow_index = |
| 166 scope_info_->ContextSlotIndex( |
| 167 isolate->heap()->arguments_shadow_symbol(), &mode); |
| 168 if (arguments_shadow_index >= 0) { |
| 169 ASSERT(mode == Variable::INTERNAL); |
| 170 arguments_shadow_ = new Variable( |
| 171 this, |
| 172 isolate->factory()->arguments_shadow_symbol(), |
| 173 Variable::INTERNAL, |
| 174 true, |
| 175 Variable::ARGUMENTS); |
| 176 arguments_shadow_->set_rewrite( |
| 177 new Slot(arguments_shadow_, Slot::CONTEXT, arguments_shadow_index)); |
| 178 arguments_shadow_->set_is_used(true); |
| 179 } |
| 180 } |
| 181 |
| 182 |
| 183 |
| 176 bool Scope::Analyze(CompilationInfo* info) { | 184 bool Scope::Analyze(CompilationInfo* info) { |
| 177 ASSERT(info->function() != NULL); | 185 ASSERT(info->function() != NULL); |
| 178 Scope* top = info->function()->scope(); | 186 Scope* top = info->function()->scope(); |
| 187 |
| 188 // If we have a serialized scope info, reuse it. |
| 189 if (!info->closure().is_null()) { |
| 190 SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info(); |
| 191 if (scope_info != SerializedScopeInfo::Empty()) { |
| 192 Scope* scope = top; |
| 193 JSFunction* current = *info->closure(); |
| 194 do { |
| 195 current = current->context()->closure(); |
| 196 SerializedScopeInfo* scope_info = current->shared()->scope_info(); |
| 197 if (scope_info != SerializedScopeInfo::Empty()) { |
| 198 scope = new Scope(scope, scope_info); |
| 199 } else { |
| 200 ASSERT(current->context()->IsGlobalContext()); |
| 201 } |
| 202 } while (!current->context()->IsGlobalContext()); |
| 203 } |
| 204 } |
| 205 |
| 179 while (top->outer_scope() != NULL) top = top->outer_scope(); | 206 while (top->outer_scope() != NULL) top = top->outer_scope(); |
| 180 top->AllocateVariables(info->calling_context()); | 207 top->AllocateVariables(info->calling_context()); |
| 181 | 208 |
| 182 #ifdef DEBUG | 209 #ifdef DEBUG |
| 183 if (info->isolate()->bootstrapper()->IsActive() | 210 if (info->isolate()->bootstrapper()->IsActive() |
| 184 ? FLAG_print_builtin_scopes | 211 ? FLAG_print_builtin_scopes |
| 185 : FLAG_print_scopes) { | 212 : FLAG_print_scopes) { |
| 186 info->function()->scope()->Print(); | 213 info->function()->scope()->Print(); |
| 187 } | 214 } |
| 188 #endif | 215 #endif |
| 189 | 216 |
| 190 info->SetScope(info->function()->scope()); | 217 info->SetScope(info->function()->scope()); |
| 191 return true; // Can not fail. | 218 return true; // Can not fail. |
| 192 } | 219 } |
| 193 | 220 |
| 194 | 221 |
| 195 void Scope::Initialize(bool inside_with) { | 222 void Scope::Initialize(bool inside_with) { |
| 223 ASSERT(!resolved()); |
| 224 |
| 196 // Add this scope as a new inner scope of the outer scope. | 225 // Add this scope as a new inner scope of the outer scope. |
| 197 if (outer_scope_ != NULL) { | 226 if (outer_scope_ != NULL) { |
| 198 outer_scope_->inner_scopes_.Add(this); | 227 outer_scope_->inner_scopes_.Add(this); |
| 199 scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with; | 228 scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with; |
| 200 } else { | 229 } else { |
| 201 scope_inside_with_ = inside_with; | 230 scope_inside_with_ = inside_with; |
| 202 } | 231 } |
| 203 | 232 |
| 204 // Declare convenience variables. | 233 // Declare convenience variables. |
| 205 // Declare and allocate receiver (even for the global scope, and even | 234 // Declare and allocate receiver (even for the global scope, and even |
| 206 // if naccesses_ == 0). | 235 // if naccesses_ == 0). |
| 207 // NOTE: When loading parameters in the global scope, we must take | 236 // NOTE: When loading parameters in the global scope, we must take |
| 208 // care not to access them as properties of the global object, but | 237 // care not to access them as properties of the global object, but |
| 209 // instead load them directly from the stack. Currently, the only | 238 // instead load them directly from the stack. Currently, the only |
| 210 // such parameter is 'this' which is passed on the stack when | 239 // such parameter is 'this' which is passed on the stack when |
| 211 // invoking scripts | 240 // invoking scripts |
| 212 Variable* var = | 241 Variable* var = |
| 213 variables_.Declare(this, FACTORY->this_symbol(), Variable::VAR, | 242 variables_.Declare(this, FACTORY->this_symbol(), Variable::VAR, |
| 214 false, Variable::THIS); | 243 false, Variable::THIS); |
| 215 var->rewrite_ = new Slot(var, Slot::PARAMETER, -1); | 244 var->set_rewrite(new Slot(var, Slot::PARAMETER, -1)); |
| 216 receiver_ = var; | 245 receiver_ = var; |
| 217 | 246 |
| 218 if (is_function_scope()) { | 247 if (is_function_scope()) { |
| 219 // Declare 'arguments' variable which exists in all functions. | 248 // Declare 'arguments' variable which exists in all functions. |
| 220 // Note that it might never be accessed, in which case it won't be | 249 // Note that it might never be accessed, in which case it won't be |
| 221 // allocated during variable allocation. | 250 // allocated during variable allocation. |
| 222 variables_.Declare(this, FACTORY->arguments_symbol(), Variable::VAR, | 251 variables_.Declare(this, FACTORY->arguments_symbol(), Variable::VAR, |
| 223 true, Variable::ARGUMENTS); | 252 true, Variable::ARGUMENTS); |
| 224 } | 253 } |
| 225 } | 254 } |
| 226 | 255 |
| 227 | 256 |
| 228 Variable* Scope::LocalLookup(Handle<String> name) { | 257 Variable* Scope::LocalLookup(Handle<String> name) { |
| 229 return variables_.Lookup(name); | 258 Variable* result = variables_.Lookup(name); |
| 259 if (result != NULL || !resolved()) { |
| 260 return result; |
| 261 } |
| 262 // If the scope is resolved, we can find a variable in serialized scope info. |
| 263 |
| 264 // We should never lookup 'arguments' in this scope |
| 265 // as it is implicitly present in any scope. |
| 266 ASSERT(*name != *FACTORY->arguments_symbol()); |
| 267 |
| 268 // Assert that there is no local slot with the given name. |
| 269 ASSERT(scope_info_->StackSlotIndex(*name) < 0); |
| 270 |
| 271 // Check context slot lookup. |
| 272 Variable::Mode mode; |
| 273 int index = scope_info_->ContextSlotIndex(*name, &mode); |
| 274 if (index >= 0) { |
| 275 Variable* var = |
| 276 variables_.Declare(this, name, mode, true, Variable::NORMAL); |
| 277 var->set_rewrite(new Slot(var, Slot::CONTEXT, index)); |
| 278 return var; |
| 279 } |
| 280 |
| 281 index = scope_info_->ParameterIndex(*name); |
| 282 if (index >= 0) { |
| 283 // ".arguments" must be present in context slots. |
| 284 ASSERT(arguments_shadow_ != NULL); |
| 285 Variable* var = |
| 286 variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL); |
| 287 Property* rewrite = |
| 288 new Property(new VariableProxy(arguments_shadow_), |
| 289 new Literal(Handle<Object>(Smi::FromInt(index))), |
| 290 RelocInfo::kNoPosition, |
| 291 Property::SYNTHETIC); |
| 292 rewrite->set_is_arguments_access(true); |
| 293 var->set_rewrite(rewrite); |
| 294 return var; |
| 295 } |
| 296 |
| 297 index = scope_info_->FunctionContextSlotIndex(*name); |
| 298 if (index >= 0) { |
| 299 // Check that there is no local slot with the given name. |
| 300 ASSERT(scope_info_->StackSlotIndex(*name) < 0); |
| 301 Variable* var = |
| 302 variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL); |
| 303 var->set_rewrite(new Slot(var, Slot::CONTEXT, index)); |
| 304 return var; |
| 305 } |
| 306 |
| 307 return NULL; |
| 230 } | 308 } |
| 231 | 309 |
| 232 | 310 |
| 233 Variable* Scope::Lookup(Handle<String> name) { | 311 Variable* Scope::Lookup(Handle<String> name) { |
| 234 for (Scope* scope = this; | 312 for (Scope* scope = this; |
| 235 scope != NULL; | 313 scope != NULL; |
| 236 scope = scope->outer_scope()) { | 314 scope = scope->outer_scope()) { |
| 237 Variable* var = scope->LocalLookup(name); | 315 Variable* var = scope->LocalLookup(name); |
| 238 if (var != NULL) return var; | 316 if (var != NULL) return var; |
| 239 } | 317 } |
| 240 return NULL; | 318 return NULL; |
| 241 } | 319 } |
| 242 | 320 |
| 243 | 321 |
| 244 Variable* Scope::DeclareFunctionVar(Handle<String> name) { | 322 Variable* Scope::DeclareFunctionVar(Handle<String> name) { |
| 245 ASSERT(is_function_scope() && function_ == NULL); | 323 ASSERT(is_function_scope() && function_ == NULL); |
| 246 function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL); | 324 function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL); |
| 247 return function_; | 325 return function_; |
| 248 } | 326 } |
| 249 | 327 |
| 250 | 328 |
| 251 Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) { | 329 Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) { |
| 252 // DYNAMIC variables are introduces during variable allocation, | 330 // DYNAMIC variables are introduces during variable allocation, |
| 253 // INTERNAL variables are allocated explicitly, and TEMPORARY | 331 // INTERNAL variables are allocated explicitly, and TEMPORARY |
| 254 // variables are allocated via NewTemporary(). | 332 // variables are allocated via NewTemporary(). |
| 333 ASSERT(!resolved()); |
| 255 ASSERT(mode == Variable::VAR || mode == Variable::CONST); | 334 ASSERT(mode == Variable::VAR || mode == Variable::CONST); |
| 256 return variables_.Declare(this, name, mode, true, Variable::NORMAL); | 335 return variables_.Declare(this, name, mode, true, Variable::NORMAL); |
| 257 } | 336 } |
| 258 | 337 |
| 259 | 338 |
| 260 Variable* Scope::DeclareGlobal(Handle<String> name) { | 339 Variable* Scope::DeclareGlobal(Handle<String> name) { |
| 261 ASSERT(is_global_scope()); | 340 ASSERT(is_global_scope()); |
| 262 return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true, | 341 return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true, |
| 263 Variable::NORMAL); | 342 Variable::NORMAL); |
| 264 } | 343 } |
| 265 | 344 |
| 266 | 345 |
| 267 void Scope::AddParameter(Variable* var) { | 346 void Scope::AddParameter(Variable* var) { |
| 268 ASSERT(is_function_scope()); | 347 ASSERT(is_function_scope()); |
| 269 ASSERT(LocalLookup(var->name()) == var); | 348 ASSERT(LocalLookup(var->name()) == var); |
| 270 params_.Add(var); | 349 params_.Add(var); |
| 271 } | 350 } |
| 272 | 351 |
| 273 | 352 |
| 274 VariableProxy* Scope::NewUnresolved(Handle<String> name, bool inside_with) { | 353 VariableProxy* Scope::NewUnresolved(Handle<String> name, bool inside_with) { |
| 275 // Note that we must not share the unresolved variables with | 354 // Note that we must not share the unresolved variables with |
| 276 // the same name because they may be removed selectively via | 355 // the same name because they may be removed selectively via |
| 277 // RemoveUnresolved(). | 356 // RemoveUnresolved(). |
| 357 ASSERT(!resolved()); |
| 278 VariableProxy* proxy = new VariableProxy(name, false, inside_with); | 358 VariableProxy* proxy = new VariableProxy(name, false, inside_with); |
| 279 unresolved_.Add(proxy); | 359 unresolved_.Add(proxy); |
| 280 return proxy; | 360 return proxy; |
| 281 } | 361 } |
| 282 | 362 |
| 283 | 363 |
| 284 void Scope::RemoveUnresolved(VariableProxy* var) { | 364 void Scope::RemoveUnresolved(VariableProxy* var) { |
| 285 // Most likely (always?) any variable we want to remove | 365 // Most likely (always?) any variable we want to remove |
| 286 // was just added before, so we search backwards. | 366 // was just added before, so we search backwards. |
| 287 for (int i = unresolved_.length(); i-- > 0;) { | 367 for (int i = unresolved_.length(); i-- > 0;) { |
| 288 if (unresolved_[i] == var) { | 368 if (unresolved_[i] == var) { |
| 289 unresolved_.Remove(i); | 369 unresolved_.Remove(i); |
| 290 return; | 370 return; |
| 291 } | 371 } |
| 292 } | 372 } |
| 293 } | 373 } |
| 294 | 374 |
| 295 | 375 |
| 296 Variable* Scope::NewTemporary(Handle<String> name) { | 376 Variable* Scope::NewTemporary(Handle<String> name) { |
| 377 ASSERT(!resolved()); |
| 297 Variable* var = | 378 Variable* var = |
| 298 new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL); | 379 new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL); |
| 299 temps_.Add(var); | 380 temps_.Add(var); |
| 300 return var; | 381 return var; |
| 301 } | 382 } |
| 302 | 383 |
| 303 | 384 |
| 304 void Scope::AddDeclaration(Declaration* declaration) { | 385 void Scope::AddDeclaration(Declaration* declaration) { |
| 305 decls_.Add(declaration); | 386 decls_.Add(declaration); |
| 306 } | 387 } |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 | 626 |
| 546 | 627 |
| 547 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { | 628 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { |
| 548 if (dynamics_ == NULL) dynamics_ = new DynamicScopePart(); | 629 if (dynamics_ == NULL) dynamics_ = new DynamicScopePart(); |
| 549 VariableMap* map = dynamics_->GetMap(mode); | 630 VariableMap* map = dynamics_->GetMap(mode); |
| 550 Variable* var = map->Lookup(name); | 631 Variable* var = map->Lookup(name); |
| 551 if (var == NULL) { | 632 if (var == NULL) { |
| 552 // Declare a new non-local. | 633 // Declare a new non-local. |
| 553 var = map->Declare(NULL, name, mode, true, Variable::NORMAL); | 634 var = map->Declare(NULL, name, mode, true, Variable::NORMAL); |
| 554 // Allocate it by giving it a dynamic lookup. | 635 // Allocate it by giving it a dynamic lookup. |
| 555 var->rewrite_ = new Slot(var, Slot::LOOKUP, -1); | 636 var->set_rewrite(new Slot(var, Slot::LOOKUP, -1)); |
| 556 } | 637 } |
| 557 return var; | 638 return var; |
| 558 } | 639 } |
| 559 | 640 |
| 560 | 641 |
| 561 // Lookup a variable starting with this scope. The result is either | 642 // Lookup a variable starting with this scope. The result is either |
| 562 // the statically resolved variable belonging to an outer scope, or | 643 // the statically resolved variable belonging to an outer scope, or |
| 563 // NULL. It may be NULL because a) we couldn't find a variable, or b) | 644 // NULL. It may be NULL because a) we couldn't find a variable, or b) |
| 564 // because the variable is just a guess (and may be shadowed by | 645 // because the variable is just a guess (and may be shadowed by |
| 565 // another variable that is introduced dynamically via an 'eval' call | 646 // another variable that is introduced dynamically via an 'eval' call |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 } | 688 } |
| 608 | 689 |
| 609 // If we did not find a variable, we are done. | 690 // If we did not find a variable, we are done. |
| 610 if (var == NULL) | 691 if (var == NULL) |
| 611 return NULL; | 692 return NULL; |
| 612 } | 693 } |
| 613 | 694 |
| 614 ASSERT(var != NULL); | 695 ASSERT(var != NULL); |
| 615 | 696 |
| 616 // If this is a lookup from an inner scope, mark the variable. | 697 // If this is a lookup from an inner scope, mark the variable. |
| 617 if (inner_lookup) | 698 if (inner_lookup) { |
| 618 var->is_accessed_from_inner_scope_ = true; | 699 var->MarkAsAccessedFromInnerScope(); |
| 700 } |
| 619 | 701 |
| 620 // If the variable we have found is just a guess, invalidate the | 702 // If the variable we have found is just a guess, invalidate the |
| 621 // result. If the found variable is local, record that fact so we | 703 // result. If the found variable is local, record that fact so we |
| 622 // can generate fast code to get it if it is not shadowed by eval. | 704 // can generate fast code to get it if it is not shadowed by eval. |
| 623 if (guess) { | 705 if (guess) { |
| 624 if (!var->is_global()) *invalidated_local = var; | 706 if (!var->is_global()) *invalidated_local = var; |
| 625 var = NULL; | 707 var = NULL; |
| 626 } | 708 } |
| 627 | 709 |
| 628 return var; | 710 return var; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 | 830 |
| 749 return scope_calls_eval_ || inner_scope_calls_eval_; | 831 return scope_calls_eval_ || inner_scope_calls_eval_; |
| 750 } | 832 } |
| 751 | 833 |
| 752 | 834 |
| 753 bool Scope::MustAllocate(Variable* var) { | 835 bool Scope::MustAllocate(Variable* var) { |
| 754 // Give var a read/write use if there is a chance it might be accessed | 836 // Give var a read/write use if there is a chance it might be accessed |
| 755 // via an eval() call. This is only possible if the variable has a | 837 // via an eval() call. This is only possible if the variable has a |
| 756 // visible name. | 838 // visible name. |
| 757 if ((var->is_this() || var->name()->length() > 0) && | 839 if ((var->is_this() || var->name()->length() > 0) && |
| 758 (var->is_accessed_from_inner_scope_ || | 840 (var->is_accessed_from_inner_scope() || |
| 759 scope_calls_eval_ || inner_scope_calls_eval_ || | 841 scope_calls_eval_ || inner_scope_calls_eval_ || |
| 760 scope_contains_with_)) { | 842 scope_contains_with_)) { |
| 761 var->set_is_used(true); | 843 var->set_is_used(true); |
| 762 } | 844 } |
| 763 // Global variables do not need to be allocated. | 845 // Global variables do not need to be allocated. |
| 764 return !var->is_global() && var->is_used(); | 846 return !var->is_global() && var->is_used(); |
| 765 } | 847 } |
| 766 | 848 |
| 767 | 849 |
| 768 bool Scope::MustAllocateInContext(Variable* var) { | 850 bool Scope::MustAllocateInContext(Variable* var) { |
| 769 // If var is accessed from an inner scope, or if there is a | 851 // If var is accessed from an inner scope, or if there is a |
| 770 // possibility that it might be accessed from the current or an inner | 852 // possibility that it might be accessed from the current or an inner |
| 771 // scope (through an eval() call), it must be allocated in the | 853 // scope (through an eval() call), it must be allocated in the |
| 772 // context. Exception: temporary variables are not allocated in the | 854 // context. Exception: temporary variables are not allocated in the |
| 773 // context. | 855 // context. |
| 774 return | 856 return |
| 775 var->mode() != Variable::TEMPORARY && | 857 var->mode() != Variable::TEMPORARY && |
| 776 (var->is_accessed_from_inner_scope_ || | 858 (var->is_accessed_from_inner_scope() || |
| 777 scope_calls_eval_ || inner_scope_calls_eval_ || | 859 scope_calls_eval_ || inner_scope_calls_eval_ || |
| 778 scope_contains_with_ || var->is_global()); | 860 scope_contains_with_ || var->is_global()); |
| 779 } | 861 } |
| 780 | 862 |
| 781 | 863 |
| 782 bool Scope::HasArgumentsParameter() { | 864 bool Scope::HasArgumentsParameter() { |
| 783 for (int i = 0; i < params_.length(); i++) { | 865 for (int i = 0; i < params_.length(); i++) { |
| 784 if (params_[i]->name().is_identical_to(FACTORY->arguments_symbol())) | 866 if (params_[i]->name().is_identical_to(FACTORY->arguments_symbol())) |
| 785 return true; | 867 return true; |
| 786 } | 868 } |
| 787 return false; | 869 return false; |
| 788 } | 870 } |
| 789 | 871 |
| 790 | 872 |
| 791 void Scope::AllocateStackSlot(Variable* var) { | 873 void Scope::AllocateStackSlot(Variable* var) { |
| 792 var->rewrite_ = new Slot(var, Slot::LOCAL, num_stack_slots_++); | 874 var->set_rewrite(new Slot(var, Slot::LOCAL, num_stack_slots_++)); |
| 793 } | 875 } |
| 794 | 876 |
| 795 | 877 |
| 796 void Scope::AllocateHeapSlot(Variable* var) { | 878 void Scope::AllocateHeapSlot(Variable* var) { |
| 797 var->rewrite_ = new Slot(var, Slot::CONTEXT, num_heap_slots_++); | 879 var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++)); |
| 798 } | 880 } |
| 799 | 881 |
| 800 | 882 |
| 801 void Scope::AllocateParameterLocals() { | 883 void Scope::AllocateParameterLocals() { |
| 802 ASSERT(is_function_scope()); | 884 ASSERT(is_function_scope()); |
| 803 Variable* arguments = LocalLookup(FACTORY->arguments_symbol()); | 885 Variable* arguments = LocalLookup(FACTORY->arguments_symbol()); |
| 804 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly | 886 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly |
| 805 if (MustAllocate(arguments) && !HasArgumentsParameter()) { | 887 if (MustAllocate(arguments) && !HasArgumentsParameter()) { |
| 806 // 'arguments' is used. Unless there is also a parameter called | 888 // 'arguments' is used. Unless there is also a parameter called |
| 807 // 'arguments', we must be conservative and access all parameters via | 889 // 'arguments', we must be conservative and access all parameters via |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 | 934 |
| 853 // Allocate the parameters by rewriting them into '.arguments[i]' accesses. | 935 // Allocate the parameters by rewriting them into '.arguments[i]' accesses. |
| 854 for (int i = 0; i < params_.length(); i++) { | 936 for (int i = 0; i < params_.length(); i++) { |
| 855 Variable* var = params_[i]; | 937 Variable* var = params_[i]; |
| 856 ASSERT(var->scope() == this); | 938 ASSERT(var->scope() == this); |
| 857 if (MustAllocate(var)) { | 939 if (MustAllocate(var)) { |
| 858 if (MustAllocateInContext(var)) { | 940 if (MustAllocateInContext(var)) { |
| 859 // It is ok to set this only now, because arguments is a local | 941 // It is ok to set this only now, because arguments is a local |
| 860 // variable that is allocated after the parameters have been | 942 // variable that is allocated after the parameters have been |
| 861 // allocated. | 943 // allocated. |
| 862 arguments_shadow_->is_accessed_from_inner_scope_ = true; | 944 arguments_shadow_->MarkAsAccessedFromInnerScope(); |
| 863 } | 945 } |
| 864 Property* rewrite = | 946 Property* rewrite = |
| 865 new Property(new VariableProxy(arguments_shadow_), | 947 new Property(new VariableProxy(arguments_shadow_), |
| 866 new Literal(Handle<Object>(Smi::FromInt(i))), | 948 new Literal(Handle<Object>(Smi::FromInt(i))), |
| 867 RelocInfo::kNoPosition, | 949 RelocInfo::kNoPosition, |
| 868 Property::SYNTHETIC); | 950 Property::SYNTHETIC); |
| 869 rewrite->set_is_arguments_access(true); | 951 rewrite->set_is_arguments_access(true); |
| 870 var->rewrite_ = rewrite; | 952 var->set_rewrite(rewrite); |
| 871 } | 953 } |
| 872 } | 954 } |
| 873 | 955 |
| 874 } else { | 956 } else { |
| 875 // The arguments object is not used, so we can access parameters directly. | 957 // The arguments object is not used, so we can access parameters directly. |
| 876 // The same parameter may occur multiple times in the parameters_ list. | 958 // The same parameter may occur multiple times in the parameters_ list. |
| 877 // If it does, and if it is not copied into the context object, it must | 959 // If it does, and if it is not copied into the context object, it must |
| 878 // receive the highest parameter index for that parameter; thus iteration | 960 // receive the highest parameter index for that parameter; thus iteration |
| 879 // order is relevant! | 961 // order is relevant! |
| 880 for (int i = 0; i < params_.length(); i++) { | 962 for (int i = 0; i < params_.length(); i++) { |
| 881 Variable* var = params_[i]; | 963 Variable* var = params_[i]; |
| 882 ASSERT(var->scope() == this); | 964 ASSERT(var->scope() == this); |
| 883 if (MustAllocate(var)) { | 965 if (MustAllocate(var)) { |
| 884 if (MustAllocateInContext(var)) { | 966 if (MustAllocateInContext(var)) { |
| 885 ASSERT(var->rewrite_ == NULL || | 967 ASSERT(var->rewrite() == NULL || |
| 886 (var->AsSlot() != NULL && | 968 (var->AsSlot() != NULL && |
| 887 var->AsSlot()->type() == Slot::CONTEXT)); | 969 var->AsSlot()->type() == Slot::CONTEXT)); |
| 888 if (var->rewrite_ == NULL) { | 970 if (var->rewrite() == NULL) { |
| 889 // Only set the heap allocation if the parameter has not | 971 // Only set the heap allocation if the parameter has not |
| 890 // been allocated yet. | 972 // been allocated yet. |
| 891 AllocateHeapSlot(var); | 973 AllocateHeapSlot(var); |
| 892 } | 974 } |
| 893 } else { | 975 } else { |
| 894 ASSERT(var->rewrite_ == NULL || | 976 ASSERT(var->rewrite() == NULL || |
| 895 (var->AsSlot() != NULL && | 977 (var->AsSlot() != NULL && |
| 896 var->AsSlot()->type() == Slot::PARAMETER)); | 978 var->AsSlot()->type() == Slot::PARAMETER)); |
| 897 // Set the parameter index always, even if the parameter | 979 // Set the parameter index always, even if the parameter |
| 898 // was seen before! (We need to access the actual parameter | 980 // was seen before! (We need to access the actual parameter |
| 899 // supplied for the last occurrence of a multiply declared | 981 // supplied for the last occurrence of a multiply declared |
| 900 // parameter.) | 982 // parameter.) |
| 901 var->rewrite_ = new Slot(var, Slot::PARAMETER, i); | 983 var->set_rewrite(new Slot(var, Slot::PARAMETER, i)); |
| 902 } | 984 } |
| 903 } | 985 } |
| 904 } | 986 } |
| 905 } | 987 } |
| 906 } | 988 } |
| 907 | 989 |
| 908 | 990 |
| 909 void Scope::AllocateNonParameterLocal(Variable* var) { | 991 void Scope::AllocateNonParameterLocal(Variable* var) { |
| 910 ASSERT(var->scope() == this); | 992 ASSERT(var->scope() == this); |
| 911 ASSERT(var->rewrite_ == NULL || | 993 ASSERT(var->rewrite() == NULL || |
| 912 (!var->IsVariable(FACTORY->result_symbol())) || | 994 (!var->IsVariable(FACTORY->result_symbol())) || |
| 913 (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL)); | 995 (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL)); |
| 914 if (var->rewrite_ == NULL && MustAllocate(var)) { | 996 if (var->rewrite() == NULL && MustAllocate(var)) { |
| 915 if (MustAllocateInContext(var)) { | 997 if (MustAllocateInContext(var)) { |
| 916 AllocateHeapSlot(var); | 998 AllocateHeapSlot(var); |
| 917 } else { | 999 } else { |
| 918 AllocateStackSlot(var); | 1000 AllocateStackSlot(var); |
| 919 } | 1001 } |
| 920 } | 1002 } |
| 921 } | 1003 } |
| 922 | 1004 |
| 923 | 1005 |
| 924 void Scope::AllocateNonParameterLocals() { | 1006 void Scope::AllocateNonParameterLocals() { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 938 // allocated in the context, it must be the last slot in the context, | 1020 // allocated in the context, it must be the last slot in the context, |
| 939 // because of the current ScopeInfo implementation (see | 1021 // because of the current ScopeInfo implementation (see |
| 940 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). | 1022 // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor). |
| 941 if (function_ != NULL) { | 1023 if (function_ != NULL) { |
| 942 AllocateNonParameterLocal(function_); | 1024 AllocateNonParameterLocal(function_); |
| 943 } | 1025 } |
| 944 } | 1026 } |
| 945 | 1027 |
| 946 | 1028 |
| 947 void Scope::AllocateVariablesRecursively() { | 1029 void Scope::AllocateVariablesRecursively() { |
| 948 // The number of slots required for variables. | |
| 949 num_stack_slots_ = 0; | |
| 950 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; | |
| 951 | |
| 952 // Allocate variables for inner scopes. | 1030 // Allocate variables for inner scopes. |
| 953 for (int i = 0; i < inner_scopes_.length(); i++) { | 1031 for (int i = 0; i < inner_scopes_.length(); i++) { |
| 954 inner_scopes_[i]->AllocateVariablesRecursively(); | 1032 inner_scopes_[i]->AllocateVariablesRecursively(); |
| 955 } | 1033 } |
| 956 | 1034 |
| 1035 // If scope is already resolved, we still need to allocate |
| 1036 // variables in inner scopes which might not had been resolved yet. |
| 1037 if (resolved()) return; |
| 1038 // The number of slots required for variables. |
| 1039 num_stack_slots_ = 0; |
| 1040 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |
| 1041 |
| 957 // Allocate variables for this scope. | 1042 // Allocate variables for this scope. |
| 958 // Parameters must be allocated first, if any. | 1043 // Parameters must be allocated first, if any. |
| 959 if (is_function_scope()) AllocateParameterLocals(); | 1044 if (is_function_scope()) AllocateParameterLocals(); |
| 960 AllocateNonParameterLocals(); | 1045 AllocateNonParameterLocals(); |
| 961 | 1046 |
| 962 // Allocate context if necessary. | 1047 // Allocate context if necessary. |
| 963 bool must_have_local_context = false; | 1048 bool must_have_local_context = false; |
| 964 if (scope_calls_eval_ || scope_contains_with_) { | 1049 if (scope_calls_eval_ || scope_contains_with_) { |
| 965 // The context for the eval() call or 'with' statement in this scope. | 1050 // The context for the eval() call or 'with' statement in this scope. |
| 966 // Unless we are in the global or an eval scope, we need a local | 1051 // Unless we are in the global or an eval scope, we need a local |
| 967 // context even if we didn't statically allocate any locals in it, | 1052 // context even if we didn't statically allocate any locals in it, |
| 968 // and the compiler will access the context variable. If we are | 1053 // and the compiler will access the context variable. If we are |
| 969 // not in an inner scope, the scope is provided from the outside. | 1054 // not in an inner scope, the scope is provided from the outside. |
| 970 must_have_local_context = is_function_scope(); | 1055 must_have_local_context = is_function_scope(); |
| 971 } | 1056 } |
| 972 | 1057 |
| 973 // If we didn't allocate any locals in the local context, then we only | 1058 // If we didn't allocate any locals in the local context, then we only |
| 974 // need the minimal number of slots if we must have a local context. | 1059 // need the minimal number of slots if we must have a local context. |
| 975 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 1060 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && |
| 976 !must_have_local_context) { | 1061 !must_have_local_context) { |
| 977 num_heap_slots_ = 0; | 1062 num_heap_slots_ = 0; |
| 978 } | 1063 } |
| 979 | 1064 |
| 980 // Allocation done. | 1065 // Allocation done. |
| 981 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 1066 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
| 982 } | 1067 } |
| 983 | 1068 |
| 984 } } // namespace v8::internal | 1069 } } // namespace v8::internal |
| OLD | NEW |