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 |