| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 <stdlib.h> | 5 #include <stdlib.h> |
| 6 | 6 |
| 7 #include "src/ast/context-slot-cache.h" | 7 #include "src/ast/context-slot-cache.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 | 10 |
| 11 namespace v8 { | 11 namespace v8 { |
| 12 namespace internal { | 12 namespace internal { |
| 13 | 13 |
| 14 | 14 |
| 15 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, | 15 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, |
| 16 Scope* scope) { | 16 Scope* scope) { |
| 17 // Collect stack and context locals. | 17 // Collect variables. |
| 18 ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone); | 18 ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone); |
| 19 ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone); | 19 ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone); |
| 20 ZoneList<Variable*> context_globals(scope->ContextGlobalCount(), zone); | 20 ZoneList<Variable*> context_globals(scope->ContextGlobalCount(), zone); |
| 21 | 21 scope->CollectVariables(&stack_locals, &context_locals, &context_globals); |
| 22 scope->CollectStackAndContextLocals(&stack_locals, &context_locals, | |
| 23 &context_globals); | |
| 24 const int stack_local_count = stack_locals.length(); | 22 const int stack_local_count = stack_locals.length(); |
| 25 const int context_local_count = context_locals.length(); | 23 const int context_local_count = context_locals.length(); |
| 26 const int context_global_count = context_globals.length(); | 24 const int context_global_count = context_globals.length(); |
| 27 // Make sure we allocate the correct amount. | 25 // Make sure we allocate the correct amount. |
| 28 DCHECK_EQ(scope->ContextLocalCount(), context_local_count); | 26 DCHECK_EQ(scope->ContextLocalCount(), context_local_count); |
| 29 DCHECK_EQ(scope->ContextGlobalCount(), context_global_count); | 27 DCHECK_EQ(scope->ContextGlobalCount(), context_global_count); |
| 30 | 28 |
| 31 // Determine use and location of the "this" binding if it is present. | 29 // Determine use and location of the "this" binding if it is present. |
| 32 VariableAllocationInfo receiver_info; | 30 VariableAllocationInfo receiver_info; |
| 33 if (scope->is_declaration_scope() && | 31 if (scope->is_declaration_scope() && |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 // Add context globals' names. | 154 // Add context globals' names. |
| 157 DCHECK(index == scope_info->ContextGlobalNameEntriesIndex()); | 155 DCHECK(index == scope_info->ContextGlobalNameEntriesIndex()); |
| 158 for (int i = 0; i < context_global_count; ++i) { | 156 for (int i = 0; i < context_global_count; ++i) { |
| 159 scope_info->set(index++, *context_globals[i]->name()); | 157 scope_info->set(index++, *context_globals[i]->name()); |
| 160 } | 158 } |
| 161 | 159 |
| 162 // Add context locals' info. | 160 // Add context locals' info. |
| 163 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex()); | 161 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex()); |
| 164 for (int i = 0; i < context_local_count; ++i) { | 162 for (int i = 0; i < context_local_count; ++i) { |
| 165 Variable* var = context_locals[i]; | 163 Variable* var = context_locals[i]; |
| 166 uint32_t value = | 164 uint32_t value = VariableModeField::encode(var->mode()) | |
| 167 ContextLocalMode::encode(var->mode()) | | 165 InitFlagField::encode(var->initialization_flag()) | |
| 168 ContextLocalInitFlag::encode(var->initialization_flag()) | | 166 MaybeAssignedFlagField::encode(var->maybe_assigned()); |
| 169 ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned()); | |
| 170 scope_info->set(index++, Smi::FromInt(value)); | 167 scope_info->set(index++, Smi::FromInt(value)); |
| 171 } | 168 } |
| 172 | 169 |
| 173 // Add context globals' info. | 170 // Add context globals' info. |
| 174 DCHECK(index == scope_info->ContextGlobalInfoEntriesIndex()); | 171 DCHECK(index == scope_info->ContextGlobalInfoEntriesIndex()); |
| 175 for (int i = 0; i < context_global_count; ++i) { | 172 for (int i = 0; i < context_global_count; ++i) { |
| 176 Variable* var = context_globals[i]; | 173 Variable* var = context_globals[i]; |
| 177 // TODO(ishell): do we need this kind of info for globals here? | 174 // TODO(ishell): do we need this kind of info for globals here? |
| 178 uint32_t value = | 175 uint32_t value = VariableModeField::encode(var->mode()) | |
| 179 ContextLocalMode::encode(var->mode()) | | 176 InitFlagField::encode(var->initialization_flag()) | |
| 180 ContextLocalInitFlag::encode(var->initialization_flag()) | | 177 MaybeAssignedFlagField::encode(var->maybe_assigned()); |
| 181 ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned()); | |
| 182 scope_info->set(index++, Smi::FromInt(value)); | 178 scope_info->set(index++, Smi::FromInt(value)); |
| 183 } | 179 } |
| 184 | 180 |
| 185 // If the receiver is allocated, add its index. | 181 // If the receiver is allocated, add its index. |
| 186 DCHECK(index == scope_info->ReceiverEntryIndex()); | 182 DCHECK(index == scope_info->ReceiverEntryIndex()); |
| 187 if (has_receiver) { | 183 if (has_receiver) { |
| 188 int var_index = scope->AsDeclarationScope()->receiver()->index(); | 184 int var_index = scope->AsDeclarationScope()->receiver()->index(); |
| 189 scope_info->set(index++, Smi::FromInt(var_index)); | 185 scope_info->set(index++, Smi::FromInt(var_index)); |
| 190 // ?? DCHECK(receiver_info != CONTEXT || var_index == | 186 // ?? DCHECK(receiver_info != CONTEXT || var_index == |
| 191 // scope_info->ContextLength() - 1); | 187 // scope_info->ContextLength() - 1); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 int index = kVariablePartIndex; | 248 int index = kVariablePartIndex; |
| 253 const int first_slot_index = 0; | 249 const int first_slot_index = 0; |
| 254 DCHECK(index == scope_info->StackLocalFirstSlotIndex()); | 250 DCHECK(index == scope_info->StackLocalFirstSlotIndex()); |
| 255 scope_info->set(index++, Smi::FromInt(first_slot_index)); | 251 scope_info->set(index++, Smi::FromInt(first_slot_index)); |
| 256 DCHECK(index == scope_info->StackLocalEntriesIndex()); | 252 DCHECK(index == scope_info->StackLocalEntriesIndex()); |
| 257 | 253 |
| 258 // Here we add info for context-allocated "this". | 254 // Here we add info for context-allocated "this". |
| 259 DCHECK(index == scope_info->ContextLocalNameEntriesIndex()); | 255 DCHECK(index == scope_info->ContextLocalNameEntriesIndex()); |
| 260 scope_info->set(index++, *isolate->factory()->this_string()); | 256 scope_info->set(index++, *isolate->factory()->this_string()); |
| 261 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex()); | 257 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex()); |
| 262 const uint32_t value = ContextLocalMode::encode(CONST) | | 258 const uint32_t value = VariableModeField::encode(CONST) | |
| 263 ContextLocalInitFlag::encode(kCreatedInitialized) | | 259 InitFlagField::encode(kCreatedInitialized) | |
| 264 ContextLocalMaybeAssignedFlag::encode(kNotAssigned); | 260 MaybeAssignedFlagField::encode(kNotAssigned); |
| 265 scope_info->set(index++, Smi::FromInt(value)); | 261 scope_info->set(index++, Smi::FromInt(value)); |
| 266 | 262 |
| 267 // And here we record that this scopeinfo binds a receiver. | 263 // And here we record that this scopeinfo binds a receiver. |
| 268 DCHECK(index == scope_info->ReceiverEntryIndex()); | 264 DCHECK(index == scope_info->ReceiverEntryIndex()); |
| 269 const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0; | 265 const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0; |
| 270 scope_info->set(index++, Smi::FromInt(receiver_index)); | 266 scope_info->set(index++, Smi::FromInt(receiver_index)); |
| 271 | 267 |
| 272 DCHECK(index == scope_info->FunctionNameEntryIndex()); | 268 DCHECK(index == scope_info->FunctionNameEntryIndex()); |
| 273 | 269 |
| 274 DCHECK_EQ(index, scope_info->length()); | 270 DCHECK_EQ(index, scope_info->length()); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); | 424 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); |
| 429 int info_index = ContextLocalNameEntriesIndex() + var; | 425 int info_index = ContextLocalNameEntriesIndex() + var; |
| 430 return String::cast(get(info_index)); | 426 return String::cast(get(info_index)); |
| 431 } | 427 } |
| 432 | 428 |
| 433 | 429 |
| 434 VariableMode ScopeInfo::ContextLocalMode(int var) { | 430 VariableMode ScopeInfo::ContextLocalMode(int var) { |
| 435 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); | 431 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); |
| 436 int info_index = ContextLocalInfoEntriesIndex() + var; | 432 int info_index = ContextLocalInfoEntriesIndex() + var; |
| 437 int value = Smi::cast(get(info_index))->value(); | 433 int value = Smi::cast(get(info_index))->value(); |
| 438 return ContextLocalMode::decode(value); | 434 return VariableModeField::decode(value); |
| 439 } | 435 } |
| 440 | 436 |
| 441 | 437 |
| 442 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) { | 438 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) { |
| 443 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); | 439 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); |
| 444 int info_index = ContextLocalInfoEntriesIndex() + var; | 440 int info_index = ContextLocalInfoEntriesIndex() + var; |
| 445 int value = Smi::cast(get(info_index))->value(); | 441 int value = Smi::cast(get(info_index))->value(); |
| 446 return ContextLocalInitFlag::decode(value); | 442 return InitFlagField::decode(value); |
| 447 } | 443 } |
| 448 | 444 |
| 449 | 445 |
| 450 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) { | 446 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) { |
| 451 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); | 447 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); |
| 452 int info_index = ContextLocalInfoEntriesIndex() + var; | 448 int info_index = ContextLocalInfoEntriesIndex() + var; |
| 453 int value = Smi::cast(get(info_index))->value(); | 449 int value = Smi::cast(get(info_index))->value(); |
| 454 return ContextLocalMaybeAssignedFlag::decode(value); | 450 return MaybeAssignedFlagField::decode(value); |
| 455 } | 451 } |
| 456 | 452 |
| 457 bool ScopeInfo::VariableIsSynthetic(String* name) { | 453 bool ScopeInfo::VariableIsSynthetic(String* name) { |
| 458 // There's currently no flag stored on the ScopeInfo to indicate that a | 454 // There's currently no flag stored on the ScopeInfo to indicate that a |
| 459 // variable is a compiler-introduced temporary. However, to avoid conflict | 455 // variable is a compiler-introduced temporary. However, to avoid conflict |
| 460 // with user declarations, the current temporaries like .generator_object and | 456 // with user declarations, the current temporaries like .generator_object and |
| 461 // .result start with a dot, so we can use that as a flag. It's a hack! | 457 // .result start with a dot, so we can use that as a flag. It's a hack! |
| 462 return name->length() == 0 || name->Get(0) == '.' || | 458 return name->length() == 0 || name->Get(0) == '.' || |
| 463 name->Equals(name->GetHeap()->this_string()); | 459 name->Equals(name->GetHeap()->this_string()); |
| 464 } | 460 } |
| 465 | 461 |
| 466 | 462 |
| 467 int ScopeInfo::StackSlotIndex(String* name) { | 463 int ScopeInfo::StackSlotIndex(String* name) { |
| 468 DCHECK(name->IsInternalizedString()); | 464 DCHECK(name->IsInternalizedString()); |
| 469 if (length() > 0) { | 465 if (length() > 0) { |
| 470 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); | 466 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); |
| 471 int start = StackLocalEntriesIndex(); | 467 int start = StackLocalEntriesIndex(); |
| 472 int end = StackLocalEntriesIndex() + StackLocalCount(); | 468 int end = start + StackLocalCount(); |
| 473 for (int i = start; i < end; ++i) { | 469 for (int i = start; i < end; ++i) { |
| 474 if (name == get(i)) { | 470 if (name == get(i)) { |
| 475 return i - start + first_slot_index; | 471 return i - start + first_slot_index; |
| 476 } | 472 } |
| 477 } | 473 } |
| 478 } | 474 } |
| 479 return -1; | 475 return -1; |
| 480 } | 476 } |
| 481 | 477 |
| 482 | 478 |
| 483 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, | 479 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, |
| 484 Handle<String> name, VariableMode* mode, | 480 Handle<String> name, VariableMode* mode, |
| 485 InitializationFlag* init_flag, | 481 InitializationFlag* init_flag, |
| 486 MaybeAssignedFlag* maybe_assigned_flag) { | 482 MaybeAssignedFlag* maybe_assigned_flag) { |
| 487 DCHECK(name->IsInternalizedString()); | 483 DCHECK(name->IsInternalizedString()); |
| 488 DCHECK(mode != NULL); | 484 DCHECK_NOT_NULL(mode); |
| 489 DCHECK(init_flag != NULL); | 485 DCHECK_NOT_NULL(init_flag); |
| 486 DCHECK_NOT_NULL(maybe_assigned_flag); |
| 487 |
| 490 if (scope_info->length() > 0) { | 488 if (scope_info->length() > 0) { |
| 491 ContextSlotCache* context_slot_cache = | 489 ContextSlotCache* context_slot_cache = |
| 492 scope_info->GetIsolate()->context_slot_cache(); | 490 scope_info->GetIsolate()->context_slot_cache(); |
| 493 int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag, | 491 int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag, |
| 494 maybe_assigned_flag); | 492 maybe_assigned_flag); |
| 495 if (result != ContextSlotCache::kNotFound) { | 493 if (result != ContextSlotCache::kNotFound) { |
| 496 DCHECK(result < scope_info->ContextLength()); | 494 DCHECK(result < scope_info->ContextLength()); |
| 497 return result; | 495 return result; |
| 498 } | 496 } |
| 499 | 497 |
| 500 int start = scope_info->ContextLocalNameEntriesIndex(); | 498 int start = scope_info->ContextLocalNameEntriesIndex(); |
| 501 int end = scope_info->ContextLocalNameEntriesIndex() + | 499 int end = start + scope_info->ContextLocalCount(); |
| 502 scope_info->ContextLocalCount(); | |
| 503 for (int i = start; i < end; ++i) { | 500 for (int i = start; i < end; ++i) { |
| 504 if (*name == scope_info->get(i)) { | 501 if (*name == scope_info->get(i)) { |
| 505 int var = i - start; | 502 int var = i - start; |
| 506 *mode = scope_info->ContextLocalMode(var); | 503 *mode = scope_info->ContextLocalMode(var); |
| 507 *init_flag = scope_info->ContextLocalInitFlag(var); | 504 *init_flag = scope_info->ContextLocalInitFlag(var); |
| 508 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); | 505 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); |
| 509 result = Context::MIN_CONTEXT_SLOTS + var; | 506 result = Context::MIN_CONTEXT_SLOTS + var; |
| 510 | 507 |
| 511 context_slot_cache->Update(scope_info, name, *mode, *init_flag, | 508 context_slot_cache->Update(scope_info, name, *mode, *init_flag, |
| 512 *maybe_assigned_flag, result); | 509 *maybe_assigned_flag, result); |
| 513 DCHECK(result < scope_info->ContextLength()); | 510 DCHECK(result < scope_info->ContextLength()); |
| 514 return result; | 511 return result; |
| 515 } | 512 } |
| 516 } | 513 } |
| 517 // Cache as not found. Mode, init flag and maybe assigned flag don't matter. | 514 // Cache as not found. Mode, init flag and maybe assigned flag don't matter. |
| 518 context_slot_cache->Update(scope_info, name, TEMPORARY, | 515 context_slot_cache->Update(scope_info, name, TEMPORARY, |
| 519 kNeedsInitialization, kNotAssigned, -1); | 516 kNeedsInitialization, kNotAssigned, -1); |
| 520 } | 517 } |
| 518 |
| 521 return -1; | 519 return -1; |
| 522 } | 520 } |
| 523 | 521 |
| 524 | |
| 525 int ScopeInfo::ContextGlobalSlotIndex(Handle<ScopeInfo> scope_info, | 522 int ScopeInfo::ContextGlobalSlotIndex(Handle<ScopeInfo> scope_info, |
| 526 Handle<String> name, VariableMode* mode, | 523 Handle<String> name, VariableMode* mode, |
| 527 InitializationFlag* init_flag, | 524 InitializationFlag* init_flag, |
| 528 MaybeAssignedFlag* maybe_assigned_flag) { | 525 MaybeAssignedFlag* maybe_assigned_flag) { |
| 529 DCHECK(name->IsInternalizedString()); | 526 DCHECK(name->IsInternalizedString()); |
| 530 DCHECK(mode != NULL); | 527 DCHECK_NOT_NULL(mode); |
| 531 DCHECK(init_flag != NULL); | 528 DCHECK_NOT_NULL(init_flag); |
| 529 DCHECK_NOT_NULL(maybe_assigned_flag); |
| 532 if (scope_info->length() > 0) { | 530 if (scope_info->length() > 0) { |
| 533 // This is to ensure that ContextLocalMode() and co. queries would work. | 531 // This is to ensure that ContextLocalMode() and co. queries would work. |
| 534 DCHECK_EQ(scope_info->ContextGlobalNameEntriesIndex(), | 532 DCHECK_EQ(scope_info->ContextGlobalNameEntriesIndex(), |
| 535 scope_info->ContextLocalNameEntriesIndex() + | 533 scope_info->ContextLocalNameEntriesIndex() + |
| 536 scope_info->ContextLocalCount()); | 534 scope_info->ContextLocalCount()); |
| 537 int base = scope_info->ContextLocalNameEntriesIndex(); | 535 int base = scope_info->ContextLocalNameEntriesIndex(); |
| 538 int start = scope_info->ContextGlobalNameEntriesIndex(); | 536 int start = scope_info->ContextGlobalNameEntriesIndex(); |
| 539 int end = scope_info->ContextGlobalNameEntriesIndex() + | 537 int end = start + scope_info->ContextGlobalCount(); |
| 540 scope_info->ContextGlobalCount(); | |
| 541 for (int i = start; i < end; ++i) { | 538 for (int i = start; i < end; ++i) { |
| 542 if (*name == scope_info->get(i)) { | 539 if (*name == scope_info->get(i)) { |
| 543 int var = i - base; | 540 int var = i - base; |
| 544 *mode = scope_info->ContextLocalMode(var); | 541 *mode = scope_info->ContextLocalMode(var); |
| 545 *init_flag = scope_info->ContextLocalInitFlag(var); | 542 *init_flag = scope_info->ContextLocalInitFlag(var); |
| 546 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); | 543 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); |
| 547 int result = Context::MIN_CONTEXT_SLOTS + var; | 544 int result = Context::MIN_CONTEXT_SLOTS + var; |
| 548 DCHECK(result < scope_info->ContextLength()); | 545 DCHECK(result < scope_info->ContextLength()); |
| 549 return result; | 546 return result; |
| 550 } | 547 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 564 | 561 |
| 565 int ScopeInfo::ParameterIndex(String* name) { | 562 int ScopeInfo::ParameterIndex(String* name) { |
| 566 DCHECK(name->IsInternalizedString()); | 563 DCHECK(name->IsInternalizedString()); |
| 567 if (length() > 0) { | 564 if (length() > 0) { |
| 568 // We must read parameters from the end since for | 565 // We must read parameters from the end since for |
| 569 // multiply declared parameters the value of the | 566 // multiply declared parameters the value of the |
| 570 // last declaration of that parameter is used | 567 // last declaration of that parameter is used |
| 571 // inside a function (and thus we need to look | 568 // inside a function (and thus we need to look |
| 572 // at the last index). Was bug# 1110337. | 569 // at the last index). Was bug# 1110337. |
| 573 int start = ParameterEntriesIndex(); | 570 int start = ParameterEntriesIndex(); |
| 574 int end = ParameterEntriesIndex() + ParameterCount(); | 571 int end = start + ParameterCount(); |
| 575 for (int i = end - 1; i >= start; --i) { | 572 for (int i = end - 1; i >= start; --i) { |
| 576 if (name == get(i)) { | 573 if (name == get(i)) { |
| 577 return i - start; | 574 return i - start; |
| 578 } | 575 } |
| 579 } | 576 } |
| 580 } | 577 } |
| 581 return -1; | 578 return -1; |
| 582 } | 579 } |
| 583 | 580 |
| 584 | 581 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 ContextLocalNameEntriesIndex() + ContextLocalCount(), this); | 690 ContextLocalNameEntriesIndex() + ContextLocalCount(), this); |
| 694 } | 691 } |
| 695 | 692 |
| 696 PrintF("}\n"); | 693 PrintF("}\n"); |
| 697 } | 694 } |
| 698 #endif // DEBUG | 695 #endif // DEBUG |
| 699 | 696 |
| 700 | 697 |
| 701 } // namespace internal | 698 } // namespace internal |
| 702 } // namespace v8 | 699 } // namespace v8 |
| OLD | NEW |