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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 | 139 |
142 // Add context locals' names and info. Info lies beyond context globals' | 140 // Add context locals' names and info. Info lies beyond context globals' |
143 // names. | 141 // names. |
144 // Make sure to store them in the order that they appear in the context. | 142 // Make sure to store them in the order that they appear in the context. |
145 DCHECK_EQ(index, scope_info->ContextLocalNameEntriesIndex()); | 143 DCHECK_EQ(index, scope_info->ContextLocalNameEntriesIndex()); |
146 int info_index = index + context_local_count + context_global_count; | 144 int info_index = index + context_local_count + context_global_count; |
147 DCHECK_EQ(info_index, scope_info->ContextLocalInfoEntriesIndex()); | 145 DCHECK_EQ(info_index, scope_info->ContextLocalInfoEntriesIndex()); |
148 for (int i = 0; i < context_local_count; ++i) { | 146 for (int i = 0; i < context_local_count; ++i) { |
149 Variable* var = context_locals[i]; | 147 Variable* var = context_locals[i]; |
150 int context_index = var->index() - Context::MIN_CONTEXT_SLOTS; | 148 int context_index = var->index() - Context::MIN_CONTEXT_SLOTS; |
151 uint32_t info = | 149 uint32_t info = VariableModeField::encode(var->mode()) | |
152 ContextLocalMode::encode(var->mode()) | | 150 InitFlagField::encode(var->initialization_flag()) | |
153 ContextLocalInitFlag::encode(var->initialization_flag()) | | 151 MaybeAssignedFlagField::encode(var->maybe_assigned()); |
154 ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned()); | |
155 scope_info->set(index + context_index, *var->name()); | 152 scope_info->set(index + context_index, *var->name()); |
156 scope_info->set(info_index + context_index, Smi::FromInt(info)); | 153 scope_info->set(info_index + context_index, Smi::FromInt(info)); |
157 } | 154 } |
158 | 155 |
159 index += context_local_count; | 156 index += context_local_count; |
160 | 157 |
161 // Add context globals' names and info. Info lies beyond context locals' info. | 158 // Add context globals' names and info. Info lies beyond context locals' info. |
162 DCHECK_EQ(index, scope_info->ContextGlobalNameEntriesIndex()); | 159 DCHECK_EQ(index, scope_info->ContextGlobalNameEntriesIndex()); |
163 info_index = index + context_global_count + context_local_count; | 160 info_index = index + context_global_count + context_local_count; |
164 DCHECK_EQ(info_index, scope_info->ContextGlobalInfoEntriesIndex()); | 161 DCHECK_EQ(info_index, scope_info->ContextGlobalInfoEntriesIndex()); |
165 for (int i = 0; i < context_global_count; ++i) { | 162 for (int i = 0; i < context_global_count; ++i) { |
166 Variable* var = context_globals[i]; | 163 Variable* var = context_globals[i]; |
167 scope_info->set(index + i, *var->name()); | 164 scope_info->set(index + i, *var->name()); |
168 // TODO(ishell): do we need this kind of info for globals here? | 165 // TODO(ishell): do we need this kind of info for globals here? |
169 uint32_t info = | 166 uint32_t info = VariableModeField::encode(var->mode()) | |
170 ContextLocalMode::encode(var->mode()) | | 167 InitFlagField::encode(var->initialization_flag()) | |
171 ContextLocalInitFlag::encode(var->initialization_flag()) | | 168 MaybeAssignedFlagField::encode(var->maybe_assigned()); |
172 ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned()); | |
173 scope_info->set(info_index + i, Smi::FromInt(info)); | 169 scope_info->set(info_index + i, Smi::FromInt(info)); |
174 } | 170 } |
175 | 171 |
176 index += context_local_count + 2 * context_global_count; | 172 index += context_local_count + 2 * context_global_count; |
177 | 173 |
178 // If the receiver is allocated, add its index. | 174 // If the receiver is allocated, add its index. |
179 DCHECK(index == scope_info->ReceiverEntryIndex()); | 175 DCHECK(index == scope_info->ReceiverEntryIndex()); |
180 if (has_receiver) { | 176 if (has_receiver) { |
181 int var_index = scope->AsDeclarationScope()->receiver()->index(); | 177 int var_index = scope->AsDeclarationScope()->receiver()->index(); |
182 scope_info->set(index++, Smi::FromInt(var_index)); | 178 scope_info->set(index++, Smi::FromInt(var_index)); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 int index = kVariablePartIndex; | 241 int index = kVariablePartIndex; |
246 const int first_slot_index = 0; | 242 const int first_slot_index = 0; |
247 DCHECK(index == scope_info->StackLocalFirstSlotIndex()); | 243 DCHECK(index == scope_info->StackLocalFirstSlotIndex()); |
248 scope_info->set(index++, Smi::FromInt(first_slot_index)); | 244 scope_info->set(index++, Smi::FromInt(first_slot_index)); |
249 DCHECK(index == scope_info->StackLocalEntriesIndex()); | 245 DCHECK(index == scope_info->StackLocalEntriesIndex()); |
250 | 246 |
251 // Here we add info for context-allocated "this". | 247 // Here we add info for context-allocated "this". |
252 DCHECK(index == scope_info->ContextLocalNameEntriesIndex()); | 248 DCHECK(index == scope_info->ContextLocalNameEntriesIndex()); |
253 scope_info->set(index++, *isolate->factory()->this_string()); | 249 scope_info->set(index++, *isolate->factory()->this_string()); |
254 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex()); | 250 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex()); |
255 const uint32_t value = ContextLocalMode::encode(CONST) | | 251 const uint32_t value = VariableModeField::encode(CONST) | |
256 ContextLocalInitFlag::encode(kCreatedInitialized) | | 252 InitFlagField::encode(kCreatedInitialized) | |
257 ContextLocalMaybeAssignedFlag::encode(kNotAssigned); | 253 MaybeAssignedFlagField::encode(kNotAssigned); |
258 scope_info->set(index++, Smi::FromInt(value)); | 254 scope_info->set(index++, Smi::FromInt(value)); |
259 | 255 |
260 // And here we record that this scopeinfo binds a receiver. | 256 // And here we record that this scopeinfo binds a receiver. |
261 DCHECK(index == scope_info->ReceiverEntryIndex()); | 257 DCHECK(index == scope_info->ReceiverEntryIndex()); |
262 const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0; | 258 const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0; |
263 scope_info->set(index++, Smi::FromInt(receiver_index)); | 259 scope_info->set(index++, Smi::FromInt(receiver_index)); |
264 | 260 |
265 DCHECK(index == scope_info->FunctionNameEntryIndex()); | 261 DCHECK(index == scope_info->FunctionNameEntryIndex()); |
266 | 262 |
267 DCHECK_EQ(index, scope_info->length()); | 263 DCHECK_EQ(index, scope_info->length()); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); | 417 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); |
422 int info_index = ContextLocalNameEntriesIndex() + var; | 418 int info_index = ContextLocalNameEntriesIndex() + var; |
423 return String::cast(get(info_index)); | 419 return String::cast(get(info_index)); |
424 } | 420 } |
425 | 421 |
426 | 422 |
427 VariableMode ScopeInfo::ContextLocalMode(int var) { | 423 VariableMode ScopeInfo::ContextLocalMode(int var) { |
428 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); | 424 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); |
429 int info_index = ContextLocalInfoEntriesIndex() + var; | 425 int info_index = ContextLocalInfoEntriesIndex() + var; |
430 int value = Smi::cast(get(info_index))->value(); | 426 int value = Smi::cast(get(info_index))->value(); |
431 return ContextLocalMode::decode(value); | 427 return VariableModeField::decode(value); |
432 } | 428 } |
433 | 429 |
434 | 430 |
435 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) { | 431 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) { |
436 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); | 432 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); |
437 int info_index = ContextLocalInfoEntriesIndex() + var; | 433 int info_index = ContextLocalInfoEntriesIndex() + var; |
438 int value = Smi::cast(get(info_index))->value(); | 434 int value = Smi::cast(get(info_index))->value(); |
439 return ContextLocalInitFlag::decode(value); | 435 return InitFlagField::decode(value); |
440 } | 436 } |
441 | 437 |
442 | 438 |
443 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) { | 439 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) { |
444 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); | 440 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount()); |
445 int info_index = ContextLocalInfoEntriesIndex() + var; | 441 int info_index = ContextLocalInfoEntriesIndex() + var; |
446 int value = Smi::cast(get(info_index))->value(); | 442 int value = Smi::cast(get(info_index))->value(); |
447 return ContextLocalMaybeAssignedFlag::decode(value); | 443 return MaybeAssignedFlagField::decode(value); |
448 } | 444 } |
449 | 445 |
450 bool ScopeInfo::VariableIsSynthetic(String* name) { | 446 bool ScopeInfo::VariableIsSynthetic(String* name) { |
451 // There's currently no flag stored on the ScopeInfo to indicate that a | 447 // There's currently no flag stored on the ScopeInfo to indicate that a |
452 // variable is a compiler-introduced temporary. However, to avoid conflict | 448 // variable is a compiler-introduced temporary. However, to avoid conflict |
453 // with user declarations, the current temporaries like .generator_object and | 449 // with user declarations, the current temporaries like .generator_object and |
454 // .result start with a dot, so we can use that as a flag. It's a hack! | 450 // .result start with a dot, so we can use that as a flag. It's a hack! |
455 return name->length() == 0 || name->Get(0) == '.' || | 451 return name->length() == 0 || name->Get(0) == '.' || |
456 name->Equals(name->GetHeap()->this_string()); | 452 name->Equals(name->GetHeap()->this_string()); |
457 } | 453 } |
458 | 454 |
459 | 455 |
460 int ScopeInfo::StackSlotIndex(String* name) { | 456 int ScopeInfo::StackSlotIndex(String* name) { |
461 DCHECK(name->IsInternalizedString()); | 457 DCHECK(name->IsInternalizedString()); |
462 if (length() > 0) { | 458 if (length() > 0) { |
463 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); | 459 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value(); |
464 int start = StackLocalEntriesIndex(); | 460 int start = StackLocalEntriesIndex(); |
465 int end = StackLocalEntriesIndex() + StackLocalCount(); | 461 int end = start + StackLocalCount(); |
466 for (int i = start; i < end; ++i) { | 462 for (int i = start; i < end; ++i) { |
467 if (name == get(i)) { | 463 if (name == get(i)) { |
468 return i - start + first_slot_index; | 464 return i - start + first_slot_index; |
469 } | 465 } |
470 } | 466 } |
471 } | 467 } |
472 return -1; | 468 return -1; |
473 } | 469 } |
474 | 470 |
475 | 471 |
476 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, | 472 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info, |
477 Handle<String> name, VariableMode* mode, | 473 Handle<String> name, VariableMode* mode, |
478 InitializationFlag* init_flag, | 474 InitializationFlag* init_flag, |
479 MaybeAssignedFlag* maybe_assigned_flag) { | 475 MaybeAssignedFlag* maybe_assigned_flag) { |
480 DCHECK(name->IsInternalizedString()); | 476 DCHECK(name->IsInternalizedString()); |
481 DCHECK(mode != NULL); | 477 DCHECK_NOT_NULL(mode); |
482 DCHECK(init_flag != NULL); | 478 DCHECK_NOT_NULL(init_flag); |
| 479 DCHECK_NOT_NULL(maybe_assigned_flag); |
| 480 |
483 if (scope_info->length() > 0) { | 481 if (scope_info->length() > 0) { |
484 ContextSlotCache* context_slot_cache = | 482 ContextSlotCache* context_slot_cache = |
485 scope_info->GetIsolate()->context_slot_cache(); | 483 scope_info->GetIsolate()->context_slot_cache(); |
486 int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag, | 484 int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag, |
487 maybe_assigned_flag); | 485 maybe_assigned_flag); |
488 if (result != ContextSlotCache::kNotFound) { | 486 if (result != ContextSlotCache::kNotFound) { |
489 DCHECK(result < scope_info->ContextLength()); | 487 DCHECK(result < scope_info->ContextLength()); |
490 return result; | 488 return result; |
491 } | 489 } |
492 | 490 |
493 int start = scope_info->ContextLocalNameEntriesIndex(); | 491 int start = scope_info->ContextLocalNameEntriesIndex(); |
494 int end = scope_info->ContextLocalNameEntriesIndex() + | 492 int end = start + scope_info->ContextLocalCount(); |
495 scope_info->ContextLocalCount(); | |
496 for (int i = start; i < end; ++i) { | 493 for (int i = start; i < end; ++i) { |
497 if (*name == scope_info->get(i)) { | 494 if (*name == scope_info->get(i)) { |
498 int var = i - start; | 495 int var = i - start; |
499 *mode = scope_info->ContextLocalMode(var); | 496 *mode = scope_info->ContextLocalMode(var); |
500 *init_flag = scope_info->ContextLocalInitFlag(var); | 497 *init_flag = scope_info->ContextLocalInitFlag(var); |
501 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); | 498 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); |
502 result = Context::MIN_CONTEXT_SLOTS + var; | 499 result = Context::MIN_CONTEXT_SLOTS + var; |
503 | 500 |
504 context_slot_cache->Update(scope_info, name, *mode, *init_flag, | 501 context_slot_cache->Update(scope_info, name, *mode, *init_flag, |
505 *maybe_assigned_flag, result); | 502 *maybe_assigned_flag, result); |
506 DCHECK(result < scope_info->ContextLength()); | 503 DCHECK(result < scope_info->ContextLength()); |
507 return result; | 504 return result; |
508 } | 505 } |
509 } | 506 } |
510 // Cache as not found. Mode, init flag and maybe assigned flag don't matter. | 507 // Cache as not found. Mode, init flag and maybe assigned flag don't matter. |
511 context_slot_cache->Update(scope_info, name, TEMPORARY, | 508 context_slot_cache->Update(scope_info, name, TEMPORARY, |
512 kNeedsInitialization, kNotAssigned, -1); | 509 kNeedsInitialization, kNotAssigned, -1); |
513 } | 510 } |
| 511 |
514 return -1; | 512 return -1; |
515 } | 513 } |
516 | 514 |
517 | |
518 int ScopeInfo::ContextGlobalSlotIndex(Handle<ScopeInfo> scope_info, | 515 int ScopeInfo::ContextGlobalSlotIndex(Handle<ScopeInfo> scope_info, |
519 Handle<String> name, VariableMode* mode, | 516 Handle<String> name, VariableMode* mode, |
520 InitializationFlag* init_flag, | 517 InitializationFlag* init_flag, |
521 MaybeAssignedFlag* maybe_assigned_flag) { | 518 MaybeAssignedFlag* maybe_assigned_flag) { |
522 DCHECK(name->IsInternalizedString()); | 519 DCHECK(name->IsInternalizedString()); |
523 DCHECK(mode != NULL); | 520 DCHECK_NOT_NULL(mode); |
524 DCHECK(init_flag != NULL); | 521 DCHECK_NOT_NULL(init_flag); |
| 522 DCHECK_NOT_NULL(maybe_assigned_flag); |
525 if (scope_info->length() > 0) { | 523 if (scope_info->length() > 0) { |
526 // This is to ensure that ContextLocalMode() and co. queries would work. | 524 // This is to ensure that ContextLocalMode() and co. queries would work. |
527 DCHECK_EQ(scope_info->ContextGlobalNameEntriesIndex(), | 525 DCHECK_EQ(scope_info->ContextGlobalNameEntriesIndex(), |
528 scope_info->ContextLocalNameEntriesIndex() + | 526 scope_info->ContextLocalNameEntriesIndex() + |
529 scope_info->ContextLocalCount()); | 527 scope_info->ContextLocalCount()); |
530 int base = scope_info->ContextLocalNameEntriesIndex(); | 528 int base = scope_info->ContextLocalNameEntriesIndex(); |
531 int start = scope_info->ContextGlobalNameEntriesIndex(); | 529 int start = scope_info->ContextGlobalNameEntriesIndex(); |
532 int end = scope_info->ContextGlobalNameEntriesIndex() + | 530 int end = start + scope_info->ContextGlobalCount(); |
533 scope_info->ContextGlobalCount(); | |
534 for (int i = start; i < end; ++i) { | 531 for (int i = start; i < end; ++i) { |
535 if (*name == scope_info->get(i)) { | 532 if (*name == scope_info->get(i)) { |
536 int var = i - base; | 533 int var = i - base; |
537 *mode = scope_info->ContextLocalMode(var); | 534 *mode = scope_info->ContextLocalMode(var); |
538 *init_flag = scope_info->ContextLocalInitFlag(var); | 535 *init_flag = scope_info->ContextLocalInitFlag(var); |
539 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); | 536 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var); |
540 int result = Context::MIN_CONTEXT_SLOTS + var; | 537 int result = Context::MIN_CONTEXT_SLOTS + var; |
541 DCHECK(result < scope_info->ContextLength()); | 538 DCHECK(result < scope_info->ContextLength()); |
542 return result; | 539 return result; |
543 } | 540 } |
(...skipping 13 matching lines...) Expand all Loading... |
557 | 554 |
558 int ScopeInfo::ParameterIndex(String* name) { | 555 int ScopeInfo::ParameterIndex(String* name) { |
559 DCHECK(name->IsInternalizedString()); | 556 DCHECK(name->IsInternalizedString()); |
560 if (length() > 0) { | 557 if (length() > 0) { |
561 // We must read parameters from the end since for | 558 // We must read parameters from the end since for |
562 // multiply declared parameters the value of the | 559 // multiply declared parameters the value of the |
563 // last declaration of that parameter is used | 560 // last declaration of that parameter is used |
564 // inside a function (and thus we need to look | 561 // inside a function (and thus we need to look |
565 // at the last index). Was bug# 1110337. | 562 // at the last index). Was bug# 1110337. |
566 int start = ParameterEntriesIndex(); | 563 int start = ParameterEntriesIndex(); |
567 int end = ParameterEntriesIndex() + ParameterCount(); | 564 int end = start + ParameterCount(); |
568 for (int i = end - 1; i >= start; --i) { | 565 for (int i = end - 1; i >= start; --i) { |
569 if (name == get(i)) { | 566 if (name == get(i)) { |
570 return i - start; | 567 return i - start; |
571 } | 568 } |
572 } | 569 } |
573 } | 570 } |
574 return -1; | 571 return -1; |
575 } | 572 } |
576 | 573 |
577 | 574 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
686 ContextLocalNameEntriesIndex() + ContextLocalCount(), this); | 683 ContextLocalNameEntriesIndex() + ContextLocalCount(), this); |
687 } | 684 } |
688 | 685 |
689 PrintF("}\n"); | 686 PrintF("}\n"); |
690 } | 687 } |
691 #endif // DEBUG | 688 #endif // DEBUG |
692 | 689 |
693 | 690 |
694 } // namespace internal | 691 } // namespace internal |
695 } // namespace v8 | 692 } // namespace v8 |
OLD | NEW |