| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/scopes.h" | 7 #include "src/scopes.h" |
| 8 | 8 |
| 9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 InitializationFlag initialization_flag, | 36 InitializationFlag initialization_flag, |
| 37 MaybeAssignedFlag maybe_assigned_flag, | 37 MaybeAssignedFlag maybe_assigned_flag, |
| 38 Interface* interface) { | 38 Interface* interface) { |
| 39 // AstRawStrings are unambiguous, i.e., the same string is always represented | 39 // AstRawStrings are unambiguous, i.e., the same string is always represented |
| 40 // by the same AstRawString*. | 40 // by the same AstRawString*. |
| 41 // FIXME(marja): fix the type of Lookup. | 41 // FIXME(marja): fix the type of Lookup. |
| 42 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), | 42 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), |
| 43 true, ZoneAllocationPolicy(zone())); | 43 true, ZoneAllocationPolicy(zone())); |
| 44 if (p->value == NULL) { | 44 if (p->value == NULL) { |
| 45 // The variable has not been declared yet -> insert it. | 45 // The variable has not been declared yet -> insert it. |
| 46 ASSERT(p->key == name); | 46 DCHECK(p->key == name); |
| 47 p->value = new (zone()) | 47 p->value = new (zone()) |
| 48 Variable(scope, name, mode, is_valid_lhs, kind, initialization_flag, | 48 Variable(scope, name, mode, is_valid_lhs, kind, initialization_flag, |
| 49 maybe_assigned_flag, interface); | 49 maybe_assigned_flag, interface); |
| 50 } | 50 } |
| 51 return reinterpret_cast<Variable*>(p->value); | 51 return reinterpret_cast<Variable*>(p->value); |
| 52 } | 52 } |
| 53 | 53 |
| 54 | 54 |
| 55 Variable* VariableMap::Lookup(const AstRawString* name) { | 55 Variable* VariableMap::Lookup(const AstRawString* name) { |
| 56 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), | 56 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), |
| 57 false, ZoneAllocationPolicy(NULL)); | 57 false, ZoneAllocationPolicy(NULL)); |
| 58 if (p != NULL) { | 58 if (p != NULL) { |
| 59 ASSERT(reinterpret_cast<const AstRawString*>(p->key) == name); | 59 DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name); |
| 60 ASSERT(p->value != NULL); | 60 DCHECK(p->value != NULL); |
| 61 return reinterpret_cast<Variable*>(p->value); | 61 return reinterpret_cast<Variable*>(p->value); |
| 62 } | 62 } |
| 63 return NULL; | 63 return NULL; |
| 64 } | 64 } |
| 65 | 65 |
| 66 | 66 |
| 67 // ---------------------------------------------------------------------------- | 67 // ---------------------------------------------------------------------------- |
| 68 // Implementation of Scope | 68 // Implementation of Scope |
| 69 | 69 |
| 70 Scope::Scope(Scope* outer_scope, ScopeType scope_type, | 70 Scope::Scope(Scope* outer_scope, ScopeType scope_type, |
| 71 AstValueFactory* ast_value_factory, Zone* zone) | 71 AstValueFactory* ast_value_factory, Zone* zone) |
| 72 : isolate_(zone->isolate()), | 72 : isolate_(zone->isolate()), |
| 73 inner_scopes_(4, zone), | 73 inner_scopes_(4, zone), |
| 74 variables_(zone), | 74 variables_(zone), |
| 75 internals_(4, zone), | 75 internals_(4, zone), |
| 76 temps_(4, zone), | 76 temps_(4, zone), |
| 77 params_(4, zone), | 77 params_(4, zone), |
| 78 unresolved_(16, zone), | 78 unresolved_(16, zone), |
| 79 decls_(4, zone), | 79 decls_(4, zone), |
| 80 interface_(FLAG_harmony_modules && | 80 interface_(FLAG_harmony_modules && |
| 81 (scope_type == MODULE_SCOPE || scope_type == GLOBAL_SCOPE) | 81 (scope_type == MODULE_SCOPE || scope_type == GLOBAL_SCOPE) |
| 82 ? Interface::NewModule(zone) : NULL), | 82 ? Interface::NewModule(zone) : NULL), |
| 83 already_resolved_(false), | 83 already_resolved_(false), |
| 84 ast_value_factory_(ast_value_factory), | 84 ast_value_factory_(ast_value_factory), |
| 85 zone_(zone) { | 85 zone_(zone) { |
| 86 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null()); | 86 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null()); |
| 87 // The outermost scope must be a global scope. | 87 // The outermost scope must be a global scope. |
| 88 ASSERT(scope_type == GLOBAL_SCOPE || outer_scope != NULL); | 88 DCHECK(scope_type == GLOBAL_SCOPE || outer_scope != NULL); |
| 89 ASSERT(!HasIllegalRedeclaration()); | 89 DCHECK(!HasIllegalRedeclaration()); |
| 90 } | 90 } |
| 91 | 91 |
| 92 | 92 |
| 93 Scope::Scope(Scope* inner_scope, | 93 Scope::Scope(Scope* inner_scope, |
| 94 ScopeType scope_type, | 94 ScopeType scope_type, |
| 95 Handle<ScopeInfo> scope_info, | 95 Handle<ScopeInfo> scope_info, |
| 96 AstValueFactory* value_factory, | 96 AstValueFactory* value_factory, |
| 97 Zone* zone) | 97 Zone* zone) |
| 98 : isolate_(zone->isolate()), | 98 : isolate_(zone->isolate()), |
| 99 inner_scopes_(4, zone), | 99 inner_scopes_(4, zone), |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 global_scope->ast_value_factory_, | 223 global_scope->ast_value_factory_, |
| 224 zone); | 224 zone); |
| 225 } else if (context->IsBlockContext()) { | 225 } else if (context->IsBlockContext()) { |
| 226 ScopeInfo* scope_info = ScopeInfo::cast(context->extension()); | 226 ScopeInfo* scope_info = ScopeInfo::cast(context->extension()); |
| 227 current_scope = new(zone) Scope(current_scope, | 227 current_scope = new(zone) Scope(current_scope, |
| 228 BLOCK_SCOPE, | 228 BLOCK_SCOPE, |
| 229 Handle<ScopeInfo>(scope_info), | 229 Handle<ScopeInfo>(scope_info), |
| 230 global_scope->ast_value_factory_, | 230 global_scope->ast_value_factory_, |
| 231 zone); | 231 zone); |
| 232 } else { | 232 } else { |
| 233 ASSERT(context->IsCatchContext()); | 233 DCHECK(context->IsCatchContext()); |
| 234 String* name = String::cast(context->extension()); | 234 String* name = String::cast(context->extension()); |
| 235 current_scope = new (zone) Scope( | 235 current_scope = new (zone) Scope( |
| 236 current_scope, | 236 current_scope, |
| 237 global_scope->ast_value_factory_->GetString(Handle<String>(name)), | 237 global_scope->ast_value_factory_->GetString(Handle<String>(name)), |
| 238 global_scope->ast_value_factory_, zone); | 238 global_scope->ast_value_factory_, zone); |
| 239 } | 239 } |
| 240 if (contains_with) current_scope->RecordWithStatement(); | 240 if (contains_with) current_scope->RecordWithStatement(); |
| 241 if (innermost_scope == NULL) innermost_scope = current_scope; | 241 if (innermost_scope == NULL) innermost_scope = current_scope; |
| 242 | 242 |
| 243 // Forget about a with when we move to a context for a different function. | 243 // Forget about a with when we move to a context for a different function. |
| 244 if (context->previous()->closure() != context->closure()) { | 244 if (context->previous()->closure() != context->closure()) { |
| 245 contains_with = false; | 245 contains_with = false; |
| 246 } | 246 } |
| 247 context = context->previous(); | 247 context = context->previous(); |
| 248 } | 248 } |
| 249 | 249 |
| 250 global_scope->AddInnerScope(current_scope); | 250 global_scope->AddInnerScope(current_scope); |
| 251 global_scope->PropagateScopeInfo(false); | 251 global_scope->PropagateScopeInfo(false); |
| 252 return (innermost_scope == NULL) ? global_scope : innermost_scope; | 252 return (innermost_scope == NULL) ? global_scope : innermost_scope; |
| 253 } | 253 } |
| 254 | 254 |
| 255 | 255 |
| 256 bool Scope::Analyze(CompilationInfo* info) { | 256 bool Scope::Analyze(CompilationInfo* info) { |
| 257 ASSERT(info->function() != NULL); | 257 DCHECK(info->function() != NULL); |
| 258 Scope* scope = info->function()->scope(); | 258 Scope* scope = info->function()->scope(); |
| 259 Scope* top = scope; | 259 Scope* top = scope; |
| 260 | 260 |
| 261 // Traverse the scope tree up to the first unresolved scope or the global | 261 // Traverse the scope tree up to the first unresolved scope or the global |
| 262 // scope and start scope resolution and variable allocation from that scope. | 262 // scope and start scope resolution and variable allocation from that scope. |
| 263 while (!top->is_global_scope() && | 263 while (!top->is_global_scope() && |
| 264 !top->outer_scope()->already_resolved()) { | 264 !top->outer_scope()->already_resolved()) { |
| 265 top = top->outer_scope(); | 265 top = top->outer_scope(); |
| 266 } | 266 } |
| 267 | 267 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 285 top->interface()->Print(); | 285 top->interface()->Print(); |
| 286 } | 286 } |
| 287 #endif | 287 #endif |
| 288 | 288 |
| 289 info->PrepareForCompilation(scope); | 289 info->PrepareForCompilation(scope); |
| 290 return true; | 290 return true; |
| 291 } | 291 } |
| 292 | 292 |
| 293 | 293 |
| 294 void Scope::Initialize() { | 294 void Scope::Initialize() { |
| 295 ASSERT(!already_resolved()); | 295 DCHECK(!already_resolved()); |
| 296 | 296 |
| 297 // Add this scope as a new inner scope of the outer scope. | 297 // Add this scope as a new inner scope of the outer scope. |
| 298 if (outer_scope_ != NULL) { | 298 if (outer_scope_ != NULL) { |
| 299 outer_scope_->inner_scopes_.Add(this, zone()); | 299 outer_scope_->inner_scopes_.Add(this, zone()); |
| 300 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope(); | 300 scope_inside_with_ = outer_scope_->scope_inside_with_ || is_with_scope(); |
| 301 } else { | 301 } else { |
| 302 scope_inside_with_ = is_with_scope(); | 302 scope_inside_with_ = is_with_scope(); |
| 303 } | 303 } |
| 304 | 304 |
| 305 // Declare convenience variables. | 305 // Declare convenience variables. |
| 306 // Declare and allocate receiver (even for the global scope, and even | 306 // Declare and allocate receiver (even for the global scope, and even |
| 307 // if naccesses_ == 0). | 307 // if naccesses_ == 0). |
| 308 // NOTE: When loading parameters in the global scope, we must take | 308 // NOTE: When loading parameters in the global scope, we must take |
| 309 // care not to access them as properties of the global object, but | 309 // care not to access them as properties of the global object, but |
| 310 // instead load them directly from the stack. Currently, the only | 310 // instead load them directly from the stack. Currently, the only |
| 311 // such parameter is 'this' which is passed on the stack when | 311 // such parameter is 'this' which is passed on the stack when |
| 312 // invoking scripts | 312 // invoking scripts |
| 313 if (is_declaration_scope()) { | 313 if (is_declaration_scope()) { |
| 314 Variable* var = | 314 Variable* var = |
| 315 variables_.Declare(this, | 315 variables_.Declare(this, |
| 316 ast_value_factory_->this_string(), | 316 ast_value_factory_->this_string(), |
| 317 VAR, | 317 VAR, |
| 318 false, | 318 false, |
| 319 Variable::THIS, | 319 Variable::THIS, |
| 320 kCreatedInitialized); | 320 kCreatedInitialized); |
| 321 var->AllocateTo(Variable::PARAMETER, -1); | 321 var->AllocateTo(Variable::PARAMETER, -1); |
| 322 receiver_ = var; | 322 receiver_ = var; |
| 323 } else { | 323 } else { |
| 324 ASSERT(outer_scope() != NULL); | 324 DCHECK(outer_scope() != NULL); |
| 325 receiver_ = outer_scope()->receiver(); | 325 receiver_ = outer_scope()->receiver(); |
| 326 } | 326 } |
| 327 | 327 |
| 328 if (is_function_scope()) { | 328 if (is_function_scope()) { |
| 329 // Declare 'arguments' variable which exists in all functions. | 329 // Declare 'arguments' variable which exists in all functions. |
| 330 // Note that it might never be accessed, in which case it won't be | 330 // Note that it might never be accessed, in which case it won't be |
| 331 // allocated during variable allocation. | 331 // allocated during variable allocation. |
| 332 variables_.Declare(this, | 332 variables_.Declare(this, |
| 333 ast_value_factory_->arguments_string(), | 333 ast_value_factory_->arguments_string(), |
| 334 VAR, | 334 VAR, |
| 335 true, | 335 true, |
| 336 Variable::ARGUMENTS, | 336 Variable::ARGUMENTS, |
| 337 kCreatedInitialized); | 337 kCreatedInitialized); |
| 338 } | 338 } |
| 339 } | 339 } |
| 340 | 340 |
| 341 | 341 |
| 342 Scope* Scope::FinalizeBlockScope() { | 342 Scope* Scope::FinalizeBlockScope() { |
| 343 ASSERT(is_block_scope()); | 343 DCHECK(is_block_scope()); |
| 344 ASSERT(internals_.is_empty()); | 344 DCHECK(internals_.is_empty()); |
| 345 ASSERT(temps_.is_empty()); | 345 DCHECK(temps_.is_empty()); |
| 346 ASSERT(params_.is_empty()); | 346 DCHECK(params_.is_empty()); |
| 347 | 347 |
| 348 if (num_var_or_const() > 0) return this; | 348 if (num_var_or_const() > 0) return this; |
| 349 | 349 |
| 350 // Remove this scope from outer scope. | 350 // Remove this scope from outer scope. |
| 351 for (int i = 0; i < outer_scope_->inner_scopes_.length(); i++) { | 351 for (int i = 0; i < outer_scope_->inner_scopes_.length(); i++) { |
| 352 if (outer_scope_->inner_scopes_[i] == this) { | 352 if (outer_scope_->inner_scopes_[i] == this) { |
| 353 outer_scope_->inner_scopes_.Remove(i); | 353 outer_scope_->inner_scopes_.Remove(i); |
| 354 break; | 354 break; |
| 355 } | 355 } |
| 356 } | 356 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 373 Variable* result = variables_.Lookup(name); | 373 Variable* result = variables_.Lookup(name); |
| 374 if (result != NULL || scope_info_.is_null()) { | 374 if (result != NULL || scope_info_.is_null()) { |
| 375 return result; | 375 return result; |
| 376 } | 376 } |
| 377 // The Scope is backed up by ScopeInfo. This means it cannot operate in a | 377 // The Scope is backed up by ScopeInfo. This means it cannot operate in a |
| 378 // heap-independent mode, and all strings must be internalized immediately. So | 378 // heap-independent mode, and all strings must be internalized immediately. So |
| 379 // it's ok to get the Handle<String> here. | 379 // it's ok to get the Handle<String> here. |
| 380 Handle<String> name_handle = name->string(); | 380 Handle<String> name_handle = name->string(); |
| 381 // If we have a serialized scope info, we might find the variable there. | 381 // If we have a serialized scope info, we might find the variable there. |
| 382 // There should be no local slot with the given name. | 382 // There should be no local slot with the given name. |
| 383 ASSERT(scope_info_->StackSlotIndex(*name_handle) < 0); | 383 DCHECK(scope_info_->StackSlotIndex(*name_handle) < 0); |
| 384 | 384 |
| 385 // Check context slot lookup. | 385 // Check context slot lookup. |
| 386 VariableMode mode; | 386 VariableMode mode; |
| 387 Variable::Location location = Variable::CONTEXT; | 387 Variable::Location location = Variable::CONTEXT; |
| 388 InitializationFlag init_flag; | 388 InitializationFlag init_flag; |
| 389 MaybeAssignedFlag maybe_assigned_flag; | 389 MaybeAssignedFlag maybe_assigned_flag; |
| 390 int index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, | 390 int index = ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, |
| 391 &init_flag, &maybe_assigned_flag); | 391 &init_flag, &maybe_assigned_flag); |
| 392 if (index < 0) { | 392 if (index < 0) { |
| 393 // Check parameters. | 393 // Check parameters. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 scope != NULL; | 439 scope != NULL; |
| 440 scope = scope->outer_scope()) { | 440 scope = scope->outer_scope()) { |
| 441 Variable* var = scope->LookupLocal(name); | 441 Variable* var = scope->LookupLocal(name); |
| 442 if (var != NULL) return var; | 442 if (var != NULL) return var; |
| 443 } | 443 } |
| 444 return NULL; | 444 return NULL; |
| 445 } | 445 } |
| 446 | 446 |
| 447 | 447 |
| 448 Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode) { | 448 Variable* Scope::DeclareParameter(const AstRawString* name, VariableMode mode) { |
| 449 ASSERT(!already_resolved()); | 449 DCHECK(!already_resolved()); |
| 450 ASSERT(is_function_scope()); | 450 DCHECK(is_function_scope()); |
| 451 Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL, | 451 Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL, |
| 452 kCreatedInitialized); | 452 kCreatedInitialized); |
| 453 params_.Add(var, zone()); | 453 params_.Add(var, zone()); |
| 454 return var; | 454 return var; |
| 455 } | 455 } |
| 456 | 456 |
| 457 | 457 |
| 458 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, | 458 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, |
| 459 InitializationFlag init_flag, | 459 InitializationFlag init_flag, |
| 460 MaybeAssignedFlag maybe_assigned_flag, | 460 MaybeAssignedFlag maybe_assigned_flag, |
| 461 Interface* interface) { | 461 Interface* interface) { |
| 462 ASSERT(!already_resolved()); | 462 DCHECK(!already_resolved()); |
| 463 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are | 463 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are |
| 464 // introduces during variable allocation, INTERNAL variables are allocated | 464 // introduces during variable allocation, INTERNAL variables are allocated |
| 465 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). | 465 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). |
| 466 ASSERT(IsDeclaredVariableMode(mode)); | 466 DCHECK(IsDeclaredVariableMode(mode)); |
| 467 ++num_var_or_const_; | 467 ++num_var_or_const_; |
| 468 return variables_.Declare(this, name, mode, true, Variable::NORMAL, init_flag, | 468 return variables_.Declare(this, name, mode, true, Variable::NORMAL, init_flag, |
| 469 maybe_assigned_flag, interface); | 469 maybe_assigned_flag, interface); |
| 470 } | 470 } |
| 471 | 471 |
| 472 | 472 |
| 473 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { | 473 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { |
| 474 ASSERT(is_global_scope()); | 474 DCHECK(is_global_scope()); |
| 475 return variables_.Declare(this, | 475 return variables_.Declare(this, |
| 476 name, | 476 name, |
| 477 DYNAMIC_GLOBAL, | 477 DYNAMIC_GLOBAL, |
| 478 true, | 478 true, |
| 479 Variable::NORMAL, | 479 Variable::NORMAL, |
| 480 kCreatedInitialized); | 480 kCreatedInitialized); |
| 481 } | 481 } |
| 482 | 482 |
| 483 | 483 |
| 484 void Scope::RemoveUnresolved(VariableProxy* var) { | 484 void Scope::RemoveUnresolved(VariableProxy* var) { |
| 485 // Most likely (always?) any variable we want to remove | 485 // Most likely (always?) any variable we want to remove |
| 486 // was just added before, so we search backwards. | 486 // was just added before, so we search backwards. |
| 487 for (int i = unresolved_.length(); i-- > 0;) { | 487 for (int i = unresolved_.length(); i-- > 0;) { |
| 488 if (unresolved_[i] == var) { | 488 if (unresolved_[i] == var) { |
| 489 unresolved_.Remove(i); | 489 unresolved_.Remove(i); |
| 490 return; | 490 return; |
| 491 } | 491 } |
| 492 } | 492 } |
| 493 } | 493 } |
| 494 | 494 |
| 495 | 495 |
| 496 Variable* Scope::NewInternal(const AstRawString* name) { | 496 Variable* Scope::NewInternal(const AstRawString* name) { |
| 497 ASSERT(!already_resolved()); | 497 DCHECK(!already_resolved()); |
| 498 Variable* var = new(zone()) Variable(this, | 498 Variable* var = new(zone()) Variable(this, |
| 499 name, | 499 name, |
| 500 INTERNAL, | 500 INTERNAL, |
| 501 false, | 501 false, |
| 502 Variable::NORMAL, | 502 Variable::NORMAL, |
| 503 kCreatedInitialized); | 503 kCreatedInitialized); |
| 504 internals_.Add(var, zone()); | 504 internals_.Add(var, zone()); |
| 505 return var; | 505 return var; |
| 506 } | 506 } |
| 507 | 507 |
| 508 | 508 |
| 509 Variable* Scope::NewTemporary(const AstRawString* name) { | 509 Variable* Scope::NewTemporary(const AstRawString* name) { |
| 510 ASSERT(!already_resolved()); | 510 DCHECK(!already_resolved()); |
| 511 Variable* var = new(zone()) Variable(this, | 511 Variable* var = new(zone()) Variable(this, |
| 512 name, | 512 name, |
| 513 TEMPORARY, | 513 TEMPORARY, |
| 514 true, | 514 true, |
| 515 Variable::NORMAL, | 515 Variable::NORMAL, |
| 516 kCreatedInitialized); | 516 kCreatedInitialized); |
| 517 temps_.Add(var, zone()); | 517 temps_.Add(var, zone()); |
| 518 return var; | 518 return var; |
| 519 } | 519 } |
| 520 | 520 |
| 521 | 521 |
| 522 void Scope::AddDeclaration(Declaration* declaration) { | 522 void Scope::AddDeclaration(Declaration* declaration) { |
| 523 decls_.Add(declaration, zone()); | 523 decls_.Add(declaration, zone()); |
| 524 } | 524 } |
| 525 | 525 |
| 526 | 526 |
| 527 void Scope::SetIllegalRedeclaration(Expression* expression) { | 527 void Scope::SetIllegalRedeclaration(Expression* expression) { |
| 528 // Record only the first illegal redeclaration. | 528 // Record only the first illegal redeclaration. |
| 529 if (!HasIllegalRedeclaration()) { | 529 if (!HasIllegalRedeclaration()) { |
| 530 illegal_redecl_ = expression; | 530 illegal_redecl_ = expression; |
| 531 } | 531 } |
| 532 ASSERT(HasIllegalRedeclaration()); | 532 DCHECK(HasIllegalRedeclaration()); |
| 533 } | 533 } |
| 534 | 534 |
| 535 | 535 |
| 536 void Scope::VisitIllegalRedeclaration(AstVisitor* visitor) { | 536 void Scope::VisitIllegalRedeclaration(AstVisitor* visitor) { |
| 537 ASSERT(HasIllegalRedeclaration()); | 537 DCHECK(HasIllegalRedeclaration()); |
| 538 illegal_redecl_->Accept(visitor); | 538 illegal_redecl_->Accept(visitor); |
| 539 } | 539 } |
| 540 | 540 |
| 541 | 541 |
| 542 Declaration* Scope::CheckConflictingVarDeclarations() { | 542 Declaration* Scope::CheckConflictingVarDeclarations() { |
| 543 int length = decls_.length(); | 543 int length = decls_.length(); |
| 544 for (int i = 0; i < length; i++) { | 544 for (int i = 0; i < length; i++) { |
| 545 Declaration* decl = decls_[i]; | 545 Declaration* decl = decls_[i]; |
| 546 if (decl->mode() != VAR) continue; | 546 if (decl->mode() != VAR) continue; |
| 547 const AstRawString* name = decl->proxy()->raw_name(); | 547 const AstRawString* name = decl->proxy()->raw_name(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 573 } | 573 } |
| 574 | 574 |
| 575 private: | 575 private: |
| 576 Variable* var_; | 576 Variable* var_; |
| 577 int order_; | 577 int order_; |
| 578 }; | 578 }; |
| 579 | 579 |
| 580 | 580 |
| 581 void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals, | 581 void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals, |
| 582 ZoneList<Variable*>* context_locals) { | 582 ZoneList<Variable*>* context_locals) { |
| 583 ASSERT(stack_locals != NULL); | 583 DCHECK(stack_locals != NULL); |
| 584 ASSERT(context_locals != NULL); | 584 DCHECK(context_locals != NULL); |
| 585 | 585 |
| 586 // Collect internals which are always allocated on the heap. | 586 // Collect internals which are always allocated on the heap. |
| 587 for (int i = 0; i < internals_.length(); i++) { | 587 for (int i = 0; i < internals_.length(); i++) { |
| 588 Variable* var = internals_[i]; | 588 Variable* var = internals_[i]; |
| 589 if (var->is_used()) { | 589 if (var->is_used()) { |
| 590 ASSERT(var->IsContextSlot()); | 590 DCHECK(var->IsContextSlot()); |
| 591 context_locals->Add(var, zone()); | 591 context_locals->Add(var, zone()); |
| 592 } | 592 } |
| 593 } | 593 } |
| 594 | 594 |
| 595 // Collect temporaries which are always allocated on the stack, unless the | 595 // Collect temporaries which are always allocated on the stack, unless the |
| 596 // context as a whole has forced context allocation. | 596 // context as a whole has forced context allocation. |
| 597 for (int i = 0; i < temps_.length(); i++) { | 597 for (int i = 0; i < temps_.length(); i++) { |
| 598 Variable* var = temps_[i]; | 598 Variable* var = temps_[i]; |
| 599 if (var->is_used()) { | 599 if (var->is_used()) { |
| 600 if (var->IsContextSlot()) { | 600 if (var->IsContextSlot()) { |
| 601 ASSERT(has_forced_context_allocation()); | 601 DCHECK(has_forced_context_allocation()); |
| 602 context_locals->Add(var, zone()); | 602 context_locals->Add(var, zone()); |
| 603 } else { | 603 } else { |
| 604 ASSERT(var->IsStackLocal()); | 604 DCHECK(var->IsStackLocal()); |
| 605 stack_locals->Add(var, zone()); | 605 stack_locals->Add(var, zone()); |
| 606 } | 606 } |
| 607 } | 607 } |
| 608 } | 608 } |
| 609 | 609 |
| 610 // Collect declared local variables. | 610 // Collect declared local variables. |
| 611 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); | 611 ZoneList<VarAndOrder> vars(variables_.occupancy(), zone()); |
| 612 for (VariableMap::Entry* p = variables_.Start(); | 612 for (VariableMap::Entry* p = variables_.Start(); |
| 613 p != NULL; | 613 p != NULL; |
| 614 p = variables_.Next(p)) { | 614 p = variables_.Next(p)) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 636 bool outer_scope_calls_sloppy_eval = false; | 636 bool outer_scope_calls_sloppy_eval = false; |
| 637 if (outer_scope_ != NULL) { | 637 if (outer_scope_ != NULL) { |
| 638 outer_scope_calls_sloppy_eval = | 638 outer_scope_calls_sloppy_eval = |
| 639 outer_scope_->outer_scope_calls_sloppy_eval() | | 639 outer_scope_->outer_scope_calls_sloppy_eval() | |
| 640 outer_scope_->calls_sloppy_eval(); | 640 outer_scope_->calls_sloppy_eval(); |
| 641 } | 641 } |
| 642 PropagateScopeInfo(outer_scope_calls_sloppy_eval); | 642 PropagateScopeInfo(outer_scope_calls_sloppy_eval); |
| 643 | 643 |
| 644 // 2) Allocate module instances. | 644 // 2) Allocate module instances. |
| 645 if (FLAG_harmony_modules && (is_global_scope() || is_module_scope())) { | 645 if (FLAG_harmony_modules && (is_global_scope() || is_module_scope())) { |
| 646 ASSERT(num_modules_ == 0); | 646 DCHECK(num_modules_ == 0); |
| 647 AllocateModulesRecursively(this); | 647 AllocateModulesRecursively(this); |
| 648 } | 648 } |
| 649 | 649 |
| 650 // 3) Resolve variables. | 650 // 3) Resolve variables. |
| 651 if (!ResolveVariablesRecursively(info, factory)) return false; | 651 if (!ResolveVariablesRecursively(info, factory)) return false; |
| 652 | 652 |
| 653 // 4) Allocate variables. | 653 // 4) Allocate variables. |
| 654 AllocateVariablesRecursively(); | 654 AllocateVariablesRecursively(); |
| 655 | 655 |
| 656 return true; | 656 return true; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 705 | 705 |
| 706 | 706 |
| 707 bool Scope::AllowsLazyCompilationWithoutContext() const { | 707 bool Scope::AllowsLazyCompilationWithoutContext() const { |
| 708 return !force_eager_compilation_ && HasTrivialOuterContext(); | 708 return !force_eager_compilation_ && HasTrivialOuterContext(); |
| 709 } | 709 } |
| 710 | 710 |
| 711 | 711 |
| 712 int Scope::ContextChainLength(Scope* scope) { | 712 int Scope::ContextChainLength(Scope* scope) { |
| 713 int n = 0; | 713 int n = 0; |
| 714 for (Scope* s = this; s != scope; s = s->outer_scope_) { | 714 for (Scope* s = this; s != scope; s = s->outer_scope_) { |
| 715 ASSERT(s != NULL); // scope must be in the scope chain | 715 DCHECK(s != NULL); // scope must be in the scope chain |
| 716 if (s->is_with_scope() || s->num_heap_slots() > 0) n++; | 716 if (s->is_with_scope() || s->num_heap_slots() > 0) n++; |
| 717 // Catch and module scopes always have heap slots. | 717 // Catch and module scopes always have heap slots. |
| 718 ASSERT(!s->is_catch_scope() || s->num_heap_slots() > 0); | 718 DCHECK(!s->is_catch_scope() || s->num_heap_slots() > 0); |
| 719 ASSERT(!s->is_module_scope() || s->num_heap_slots() > 0); | 719 DCHECK(!s->is_module_scope() || s->num_heap_slots() > 0); |
| 720 } | 720 } |
| 721 return n; | 721 return n; |
| 722 } | 722 } |
| 723 | 723 |
| 724 | 724 |
| 725 Scope* Scope::GlobalScope() { | 725 Scope* Scope::GlobalScope() { |
| 726 Scope* scope = this; | 726 Scope* scope = this; |
| 727 while (!scope->is_global_scope()) { | 727 while (!scope->is_global_scope()) { |
| 728 scope = scope->outer_scope(); | 728 scope = scope->outer_scope(); |
| 729 } | 729 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 750 | 750 |
| 751 void Scope::GetNestedScopeChain( | 751 void Scope::GetNestedScopeChain( |
| 752 List<Handle<ScopeInfo> >* chain, | 752 List<Handle<ScopeInfo> >* chain, |
| 753 int position) { | 753 int position) { |
| 754 if (!is_eval_scope()) chain->Add(Handle<ScopeInfo>(GetScopeInfo())); | 754 if (!is_eval_scope()) chain->Add(Handle<ScopeInfo>(GetScopeInfo())); |
| 755 | 755 |
| 756 for (int i = 0; i < inner_scopes_.length(); i++) { | 756 for (int i = 0; i < inner_scopes_.length(); i++) { |
| 757 Scope* scope = inner_scopes_[i]; | 757 Scope* scope = inner_scopes_[i]; |
| 758 int beg_pos = scope->start_position(); | 758 int beg_pos = scope->start_position(); |
| 759 int end_pos = scope->end_position(); | 759 int end_pos = scope->end_position(); |
| 760 ASSERT(beg_pos >= 0 && end_pos >= 0); | 760 DCHECK(beg_pos >= 0 && end_pos >= 0); |
| 761 if (beg_pos <= position && position < end_pos) { | 761 if (beg_pos <= position && position < end_pos) { |
| 762 scope->GetNestedScopeChain(chain, position); | 762 scope->GetNestedScopeChain(chain, position); |
| 763 return; | 763 return; |
| 764 } | 764 } |
| 765 } | 765 } |
| 766 } | 766 } |
| 767 | 767 |
| 768 | 768 |
| 769 #ifdef DEBUG | 769 #ifdef DEBUG |
| 770 static const char* Header(ScopeType scope_type) { | 770 static const char* Header(ScopeType scope_type) { |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 953 // Allocate it by giving it a dynamic lookup. | 953 // Allocate it by giving it a dynamic lookup. |
| 954 var->AllocateTo(Variable::LOOKUP, -1); | 954 var->AllocateTo(Variable::LOOKUP, -1); |
| 955 } | 955 } |
| 956 return var; | 956 return var; |
| 957 } | 957 } |
| 958 | 958 |
| 959 | 959 |
| 960 Variable* Scope::LookupRecursive(VariableProxy* proxy, | 960 Variable* Scope::LookupRecursive(VariableProxy* proxy, |
| 961 BindingKind* binding_kind, | 961 BindingKind* binding_kind, |
| 962 AstNodeFactory<AstNullVisitor>* factory) { | 962 AstNodeFactory<AstNullVisitor>* factory) { |
| 963 ASSERT(binding_kind != NULL); | 963 DCHECK(binding_kind != NULL); |
| 964 if (already_resolved() && is_with_scope()) { | 964 if (already_resolved() && is_with_scope()) { |
| 965 // Short-cut: if the scope is deserialized from a scope info, variable | 965 // Short-cut: if the scope is deserialized from a scope info, variable |
| 966 // allocation is already fixed. We can simply return with dynamic lookup. | 966 // allocation is already fixed. We can simply return with dynamic lookup. |
| 967 *binding_kind = DYNAMIC_LOOKUP; | 967 *binding_kind = DYNAMIC_LOOKUP; |
| 968 return NULL; | 968 return NULL; |
| 969 } | 969 } |
| 970 | 970 |
| 971 // Try to find the variable in this scope. | 971 // Try to find the variable in this scope. |
| 972 Variable* var = LookupLocal(proxy->raw_name()); | 972 Variable* var = LookupLocal(proxy->raw_name()); |
| 973 | 973 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 985 *binding_kind = UNBOUND; | 985 *binding_kind = UNBOUND; |
| 986 var = LookupFunctionVar(proxy->raw_name(), factory); | 986 var = LookupFunctionVar(proxy->raw_name(), factory); |
| 987 if (var != NULL) { | 987 if (var != NULL) { |
| 988 *binding_kind = BOUND; | 988 *binding_kind = BOUND; |
| 989 } else if (outer_scope_ != NULL) { | 989 } else if (outer_scope_ != NULL) { |
| 990 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory); | 990 var = outer_scope_->LookupRecursive(proxy, binding_kind, factory); |
| 991 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { | 991 if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { |
| 992 var->ForceContextAllocation(); | 992 var->ForceContextAllocation(); |
| 993 } | 993 } |
| 994 } else { | 994 } else { |
| 995 ASSERT(is_global_scope()); | 995 DCHECK(is_global_scope()); |
| 996 } | 996 } |
| 997 | 997 |
| 998 if (is_with_scope()) { | 998 if (is_with_scope()) { |
| 999 ASSERT(!already_resolved()); | 999 DCHECK(!already_resolved()); |
| 1000 // The current scope is a with scope, so the variable binding can not be | 1000 // The current scope is a with scope, so the variable binding can not be |
| 1001 // statically resolved. However, note that it was necessary to do a lookup | 1001 // statically resolved. However, note that it was necessary to do a lookup |
| 1002 // in the outer scope anyway, because if a binding exists in an outer scope, | 1002 // in the outer scope anyway, because if a binding exists in an outer scope, |
| 1003 // the associated variable has to be marked as potentially being accessed | 1003 // the associated variable has to be marked as potentially being accessed |
| 1004 // from inside of an inner with scope (the property may not be in the 'with' | 1004 // from inside of an inner with scope (the property may not be in the 'with' |
| 1005 // object). | 1005 // object). |
| 1006 if (var != NULL && proxy->is_assigned()) var->set_maybe_assigned(); | 1006 if (var != NULL && proxy->is_assigned()) var->set_maybe_assigned(); |
| 1007 *binding_kind = DYNAMIC_LOOKUP; | 1007 *binding_kind = DYNAMIC_LOOKUP; |
| 1008 return NULL; | 1008 return NULL; |
| 1009 } else if (calls_sloppy_eval()) { | 1009 } else if (calls_sloppy_eval()) { |
| 1010 // A variable binding may have been found in an outer scope, but the current | 1010 // A variable binding may have been found in an outer scope, but the current |
| 1011 // scope makes a sloppy 'eval' call, so the found variable may not be | 1011 // scope makes a sloppy 'eval' call, so the found variable may not be |
| 1012 // the correct one (the 'eval' may introduce a binding with the same name). | 1012 // the correct one (the 'eval' may introduce a binding with the same name). |
| 1013 // In that case, change the lookup result to reflect this situation. | 1013 // In that case, change the lookup result to reflect this situation. |
| 1014 if (*binding_kind == BOUND) { | 1014 if (*binding_kind == BOUND) { |
| 1015 *binding_kind = BOUND_EVAL_SHADOWED; | 1015 *binding_kind = BOUND_EVAL_SHADOWED; |
| 1016 } else if (*binding_kind == UNBOUND) { | 1016 } else if (*binding_kind == UNBOUND) { |
| 1017 *binding_kind = UNBOUND_EVAL_SHADOWED; | 1017 *binding_kind = UNBOUND_EVAL_SHADOWED; |
| 1018 } | 1018 } |
| 1019 } | 1019 } |
| 1020 return var; | 1020 return var; |
| 1021 } | 1021 } |
| 1022 | 1022 |
| 1023 | 1023 |
| 1024 bool Scope::ResolveVariable(CompilationInfo* info, | 1024 bool Scope::ResolveVariable(CompilationInfo* info, |
| 1025 VariableProxy* proxy, | 1025 VariableProxy* proxy, |
| 1026 AstNodeFactory<AstNullVisitor>* factory) { | 1026 AstNodeFactory<AstNullVisitor>* factory) { |
| 1027 ASSERT(info->global_scope()->is_global_scope()); | 1027 DCHECK(info->global_scope()->is_global_scope()); |
| 1028 | 1028 |
| 1029 // If the proxy is already resolved there's nothing to do | 1029 // If the proxy is already resolved there's nothing to do |
| 1030 // (functions and consts may be resolved by the parser). | 1030 // (functions and consts may be resolved by the parser). |
| 1031 if (proxy->var() != NULL) return true; | 1031 if (proxy->var() != NULL) return true; |
| 1032 | 1032 |
| 1033 // Otherwise, try to resolve the variable. | 1033 // Otherwise, try to resolve the variable. |
| 1034 BindingKind binding_kind; | 1034 BindingKind binding_kind; |
| 1035 Variable* var = LookupRecursive(proxy, &binding_kind, factory); | 1035 Variable* var = LookupRecursive(proxy, &binding_kind, factory); |
| 1036 switch (binding_kind) { | 1036 switch (binding_kind) { |
| 1037 case BOUND: | 1037 case BOUND: |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1063 // No binding has been found. But some scope makes a sloppy 'eval' call. | 1063 // No binding has been found. But some scope makes a sloppy 'eval' call. |
| 1064 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); | 1064 var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); |
| 1065 break; | 1065 break; |
| 1066 | 1066 |
| 1067 case DYNAMIC_LOOKUP: | 1067 case DYNAMIC_LOOKUP: |
| 1068 // The variable could not be resolved statically. | 1068 // The variable could not be resolved statically. |
| 1069 var = NonLocal(proxy->raw_name(), DYNAMIC); | 1069 var = NonLocal(proxy->raw_name(), DYNAMIC); |
| 1070 break; | 1070 break; |
| 1071 } | 1071 } |
| 1072 | 1072 |
| 1073 ASSERT(var != NULL); | 1073 DCHECK(var != NULL); |
| 1074 if (proxy->is_assigned()) var->set_maybe_assigned(); | 1074 if (proxy->is_assigned()) var->set_maybe_assigned(); |
| 1075 | 1075 |
| 1076 if (FLAG_harmony_scoping && strict_mode() == STRICT && | 1076 if (FLAG_harmony_scoping && strict_mode() == STRICT && |
| 1077 var->is_const_mode() && proxy->is_assigned()) { | 1077 var->is_const_mode() && proxy->is_assigned()) { |
| 1078 // Assignment to const. Throw a syntax error. | 1078 // Assignment to const. Throw a syntax error. |
| 1079 MessageLocation location( | 1079 MessageLocation location( |
| 1080 info->script(), proxy->position(), proxy->position()); | 1080 info->script(), proxy->position(), proxy->position()); |
| 1081 Isolate* isolate = info->isolate(); | 1081 Isolate* isolate = info->isolate(); |
| 1082 Factory* factory = isolate->factory(); | 1082 Factory* factory = isolate->factory(); |
| 1083 Handle<JSArray> array = factory->NewJSArray(0); | 1083 Handle<JSArray> array = factory->NewJSArray(0); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1124 | 1124 |
| 1125 proxy->BindTo(var); | 1125 proxy->BindTo(var); |
| 1126 | 1126 |
| 1127 return true; | 1127 return true; |
| 1128 } | 1128 } |
| 1129 | 1129 |
| 1130 | 1130 |
| 1131 bool Scope::ResolveVariablesRecursively( | 1131 bool Scope::ResolveVariablesRecursively( |
| 1132 CompilationInfo* info, | 1132 CompilationInfo* info, |
| 1133 AstNodeFactory<AstNullVisitor>* factory) { | 1133 AstNodeFactory<AstNullVisitor>* factory) { |
| 1134 ASSERT(info->global_scope()->is_global_scope()); | 1134 DCHECK(info->global_scope()->is_global_scope()); |
| 1135 | 1135 |
| 1136 // Resolve unresolved variables for this scope. | 1136 // Resolve unresolved variables for this scope. |
| 1137 for (int i = 0; i < unresolved_.length(); i++) { | 1137 for (int i = 0; i < unresolved_.length(); i++) { |
| 1138 if (!ResolveVariable(info, unresolved_[i], factory)) return false; | 1138 if (!ResolveVariable(info, unresolved_[i], factory)) return false; |
| 1139 } | 1139 } |
| 1140 | 1140 |
| 1141 // Resolve unresolved variables for inner scopes. | 1141 // Resolve unresolved variables for inner scopes. |
| 1142 for (int i = 0; i < inner_scopes_.length(); i++) { | 1142 for (int i = 0; i < inner_scopes_.length(); i++) { |
| 1143 if (!inner_scopes_[i]->ResolveVariablesRecursively(info, factory)) | 1143 if (!inner_scopes_[i]->ResolveVariablesRecursively(info, factory)) |
| 1144 return false; | 1144 return false; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1226 var->AllocateTo(Variable::LOCAL, num_stack_slots_++); | 1226 var->AllocateTo(Variable::LOCAL, num_stack_slots_++); |
| 1227 } | 1227 } |
| 1228 | 1228 |
| 1229 | 1229 |
| 1230 void Scope::AllocateHeapSlot(Variable* var) { | 1230 void Scope::AllocateHeapSlot(Variable* var) { |
| 1231 var->AllocateTo(Variable::CONTEXT, num_heap_slots_++); | 1231 var->AllocateTo(Variable::CONTEXT, num_heap_slots_++); |
| 1232 } | 1232 } |
| 1233 | 1233 |
| 1234 | 1234 |
| 1235 void Scope::AllocateParameterLocals() { | 1235 void Scope::AllocateParameterLocals() { |
| 1236 ASSERT(is_function_scope()); | 1236 DCHECK(is_function_scope()); |
| 1237 Variable* arguments = LookupLocal(ast_value_factory_->arguments_string()); | 1237 Variable* arguments = LookupLocal(ast_value_factory_->arguments_string()); |
| 1238 ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly | 1238 DCHECK(arguments != NULL); // functions have 'arguments' declared implicitly |
| 1239 | 1239 |
| 1240 bool uses_sloppy_arguments = false; | 1240 bool uses_sloppy_arguments = false; |
| 1241 | 1241 |
| 1242 if (MustAllocate(arguments) && !HasArgumentsParameter()) { | 1242 if (MustAllocate(arguments) && !HasArgumentsParameter()) { |
| 1243 // 'arguments' is used. Unless there is also a parameter called | 1243 // 'arguments' is used. Unless there is also a parameter called |
| 1244 // 'arguments', we must be conservative and allocate all parameters to | 1244 // 'arguments', we must be conservative and allocate all parameters to |
| 1245 // the context assuming they will be captured by the arguments object. | 1245 // the context assuming they will be captured by the arguments object. |
| 1246 // If we have a parameter named 'arguments', a (new) value is always | 1246 // If we have a parameter named 'arguments', a (new) value is always |
| 1247 // assigned to it via the function invocation. Then 'arguments' denotes | 1247 // assigned to it via the function invocation. Then 'arguments' denotes |
| 1248 // that specific parameter value and cannot be used to access the | 1248 // that specific parameter value and cannot be used to access the |
| 1249 // parameters, which is why we don't need to allocate an arguments | 1249 // parameters, which is why we don't need to allocate an arguments |
| 1250 // object in that case. | 1250 // object in that case. |
| 1251 | 1251 |
| 1252 // We are using 'arguments'. Tell the code generator that is needs to | 1252 // We are using 'arguments'. Tell the code generator that is needs to |
| 1253 // allocate the arguments object by setting 'arguments_'. | 1253 // allocate the arguments object by setting 'arguments_'. |
| 1254 arguments_ = arguments; | 1254 arguments_ = arguments; |
| 1255 | 1255 |
| 1256 // In strict mode 'arguments' does not alias formal parameters. | 1256 // In strict mode 'arguments' does not alias formal parameters. |
| 1257 // Therefore in strict mode we allocate parameters as if 'arguments' | 1257 // Therefore in strict mode we allocate parameters as if 'arguments' |
| 1258 // were not used. | 1258 // were not used. |
| 1259 uses_sloppy_arguments = strict_mode() == SLOPPY; | 1259 uses_sloppy_arguments = strict_mode() == SLOPPY; |
| 1260 } | 1260 } |
| 1261 | 1261 |
| 1262 // The same parameter may occur multiple times in the parameters_ list. | 1262 // The same parameter may occur multiple times in the parameters_ list. |
| 1263 // If it does, and if it is not copied into the context object, it must | 1263 // If it does, and if it is not copied into the context object, it must |
| 1264 // receive the highest parameter index for that parameter; thus iteration | 1264 // receive the highest parameter index for that parameter; thus iteration |
| 1265 // order is relevant! | 1265 // order is relevant! |
| 1266 for (int i = params_.length() - 1; i >= 0; --i) { | 1266 for (int i = params_.length() - 1; i >= 0; --i) { |
| 1267 Variable* var = params_[i]; | 1267 Variable* var = params_[i]; |
| 1268 ASSERT(var->scope() == this); | 1268 DCHECK(var->scope() == this); |
| 1269 if (uses_sloppy_arguments || has_forced_context_allocation()) { | 1269 if (uses_sloppy_arguments || has_forced_context_allocation()) { |
| 1270 // Force context allocation of the parameter. | 1270 // Force context allocation of the parameter. |
| 1271 var->ForceContextAllocation(); | 1271 var->ForceContextAllocation(); |
| 1272 } | 1272 } |
| 1273 | 1273 |
| 1274 if (MustAllocate(var)) { | 1274 if (MustAllocate(var)) { |
| 1275 if (MustAllocateInContext(var)) { | 1275 if (MustAllocateInContext(var)) { |
| 1276 ASSERT(var->IsUnallocated() || var->IsContextSlot()); | 1276 DCHECK(var->IsUnallocated() || var->IsContextSlot()); |
| 1277 if (var->IsUnallocated()) { | 1277 if (var->IsUnallocated()) { |
| 1278 AllocateHeapSlot(var); | 1278 AllocateHeapSlot(var); |
| 1279 } | 1279 } |
| 1280 } else { | 1280 } else { |
| 1281 ASSERT(var->IsUnallocated() || var->IsParameter()); | 1281 DCHECK(var->IsUnallocated() || var->IsParameter()); |
| 1282 if (var->IsUnallocated()) { | 1282 if (var->IsUnallocated()) { |
| 1283 var->AllocateTo(Variable::PARAMETER, i); | 1283 var->AllocateTo(Variable::PARAMETER, i); |
| 1284 } | 1284 } |
| 1285 } | 1285 } |
| 1286 } | 1286 } |
| 1287 } | 1287 } |
| 1288 } | 1288 } |
| 1289 | 1289 |
| 1290 | 1290 |
| 1291 void Scope::AllocateNonParameterLocal(Variable* var) { | 1291 void Scope::AllocateNonParameterLocal(Variable* var) { |
| 1292 ASSERT(var->scope() == this); | 1292 DCHECK(var->scope() == this); |
| 1293 ASSERT(!var->IsVariable(isolate_->factory()->dot_result_string()) || | 1293 DCHECK(!var->IsVariable(isolate_->factory()->dot_result_string()) || |
| 1294 !var->IsStackLocal()); | 1294 !var->IsStackLocal()); |
| 1295 if (var->IsUnallocated() && MustAllocate(var)) { | 1295 if (var->IsUnallocated() && MustAllocate(var)) { |
| 1296 if (MustAllocateInContext(var)) { | 1296 if (MustAllocateInContext(var)) { |
| 1297 AllocateHeapSlot(var); | 1297 AllocateHeapSlot(var); |
| 1298 } else { | 1298 } else { |
| 1299 AllocateStackSlot(var); | 1299 AllocateStackSlot(var); |
| 1300 } | 1300 } |
| 1301 } | 1301 } |
| 1302 } | 1302 } |
| 1303 | 1303 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1360 bool must_have_context = is_with_scope() || is_module_scope() || | 1360 bool must_have_context = is_with_scope() || is_module_scope() || |
| 1361 (is_function_scope() && calls_eval()); | 1361 (is_function_scope() && calls_eval()); |
| 1362 | 1362 |
| 1363 // If we didn't allocate any locals in the local context, then we only | 1363 // If we didn't allocate any locals in the local context, then we only |
| 1364 // need the minimal number of slots if we must have a context. | 1364 // need the minimal number of slots if we must have a context. |
| 1365 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) { | 1365 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) { |
| 1366 num_heap_slots_ = 0; | 1366 num_heap_slots_ = 0; |
| 1367 } | 1367 } |
| 1368 | 1368 |
| 1369 // Allocation done. | 1369 // Allocation done. |
| 1370 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 1370 DCHECK(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
| 1371 } | 1371 } |
| 1372 | 1372 |
| 1373 | 1373 |
| 1374 void Scope::AllocateModulesRecursively(Scope* host_scope) { | 1374 void Scope::AllocateModulesRecursively(Scope* host_scope) { |
| 1375 if (already_resolved()) return; | 1375 if (already_resolved()) return; |
| 1376 if (is_module_scope()) { | 1376 if (is_module_scope()) { |
| 1377 ASSERT(interface_->IsFrozen()); | 1377 DCHECK(interface_->IsFrozen()); |
| 1378 ASSERT(module_var_ == NULL); | 1378 DCHECK(module_var_ == NULL); |
| 1379 module_var_ = | 1379 module_var_ = |
| 1380 host_scope->NewInternal(ast_value_factory_->dot_module_string()); | 1380 host_scope->NewInternal(ast_value_factory_->dot_module_string()); |
| 1381 ++host_scope->num_modules_; | 1381 ++host_scope->num_modules_; |
| 1382 } | 1382 } |
| 1383 | 1383 |
| 1384 for (int i = 0; i < inner_scopes_.length(); i++) { | 1384 for (int i = 0; i < inner_scopes_.length(); i++) { |
| 1385 Scope* inner_scope = inner_scopes_.at(i); | 1385 Scope* inner_scope = inner_scopes_.at(i); |
| 1386 inner_scope->AllocateModulesRecursively(host_scope); | 1386 inner_scope->AllocateModulesRecursively(host_scope); |
| 1387 } | 1387 } |
| 1388 } | 1388 } |
| 1389 | 1389 |
| 1390 | 1390 |
| 1391 int Scope::StackLocalCount() const { | 1391 int Scope::StackLocalCount() const { |
| 1392 return num_stack_slots() - | 1392 return num_stack_slots() - |
| 1393 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); | 1393 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); |
| 1394 } | 1394 } |
| 1395 | 1395 |
| 1396 | 1396 |
| 1397 int Scope::ContextLocalCount() const { | 1397 int Scope::ContextLocalCount() const { |
| 1398 if (num_heap_slots() == 0) return 0; | 1398 if (num_heap_slots() == 0) return 0; |
| 1399 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1399 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
| 1400 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 1400 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
| 1401 } | 1401 } |
| 1402 | 1402 |
| 1403 } } // namespace v8::internal | 1403 } } // namespace v8::internal |
| OLD | NEW |