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