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
3 // found in the LICENSE file.
9 #include "src/bootstrapper.h"
10 #include "src/scopeinfo.h"
11 #include "src/scopes.h"
17 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
19 // Collect stack and context locals.
20 ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone);
21 ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone);
22 ZoneList<Variable*> context_globals(scope->ContextGlobalCount(), zone);
23 ZoneList<Variable*> strong_mode_free_variables(0, zone);
25 scope->CollectStackAndContextLocals(&stack_locals, &context_locals,
27 &strong_mode_free_variables);
28 const int stack_local_count = stack_locals.length();
29 const int context_local_count = context_locals.length();
30 const int context_global_count = context_globals.length();
31 const int strong_mode_free_variable_count =
32 strong_mode_free_variables.length();
33 // Make sure we allocate the correct amount.
34 DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
35 DCHECK_EQ(scope->ContextGlobalCount(), context_global_count);
37 bool simple_parameter_list =
38 scope->is_function_scope() ? scope->is_simple_parameter_list() : true;
40 // Determine use and location of the "this" binding if it is present.
41 VariableAllocationInfo receiver_info;
42 if (scope->has_this_declaration()) {
43 Variable* var = scope->receiver();
44 if (!var->is_used()) {
45 receiver_info = UNUSED;
46 } else if (var->IsContextSlot()) {
47 receiver_info = CONTEXT;
49 DCHECK(var->IsParameter());
50 receiver_info = STACK;
56 // Determine use and location of the function variable if it is present.
57 VariableAllocationInfo function_name_info;
58 VariableMode function_variable_mode;
59 if (scope->is_function_scope() && scope->function() != NULL) {
60 Variable* var = scope->function()->proxy()->var();
61 if (!var->is_used()) {
62 function_name_info = UNUSED;
63 } else if (var->IsContextSlot()) {
64 function_name_info = CONTEXT;
66 DCHECK(var->IsStackLocal());
67 function_name_info = STACK;
69 function_variable_mode = var->mode();
71 function_name_info = NONE;
72 function_variable_mode = VAR;
74 DCHECK(context_global_count == 0 || scope->scope_type() == SCRIPT_SCOPE);
76 const bool has_function_name = function_name_info != NONE;
77 const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
78 const int parameter_count = scope->num_parameters();
79 const int length = kVariablePartIndex + parameter_count +
80 (1 + stack_local_count) + 2 * context_local_count +
81 2 * context_global_count +
82 3 * strong_mode_free_variable_count +
83 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
85 Factory* factory = isolate->factory();
86 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
89 int flags = ScopeTypeField::encode(scope->scope_type()) |
90 CallsEvalField::encode(scope->calls_eval()) |
91 LanguageModeField::encode(scope->language_mode()) |
92 ReceiverVariableField::encode(receiver_info) |
93 FunctionVariableField::encode(function_name_info) |
94 FunctionVariableMode::encode(function_variable_mode) |
95 AsmModuleField::encode(scope->asm_module()) |
96 AsmFunctionField::encode(scope->asm_function()) |
97 IsSimpleParameterListField::encode(simple_parameter_list) |
98 FunctionKindField::encode(scope->function_kind());
99 scope_info->SetFlags(flags);
100 scope_info->SetParameterCount(parameter_count);
101 scope_info->SetStackLocalCount(stack_local_count);
102 scope_info->SetContextLocalCount(context_local_count);
103 scope_info->SetContextGlobalCount(context_global_count);
104 scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
106 int index = kVariablePartIndex;
108 DCHECK(index == scope_info->ParameterEntriesIndex());
109 for (int i = 0; i < parameter_count; ++i) {
110 scope_info->set(index++, *scope->parameter(i)->name());
113 // Add stack locals' names. We are assuming that the stack locals'
114 // slots are allocated in increasing order, so we can simply add
115 // them to the ScopeInfo object.
116 int first_slot_index;
117 if (stack_local_count > 0) {
118 first_slot_index = stack_locals[0]->index();
120 first_slot_index = 0;
122 DCHECK(index == scope_info->StackLocalFirstSlotIndex());
123 scope_info->set(index++, Smi::FromInt(first_slot_index));
124 DCHECK(index == scope_info->StackLocalEntriesIndex());
125 for (int i = 0; i < stack_local_count; ++i) {
126 DCHECK(stack_locals[i]->index() == first_slot_index + i);
127 scope_info->set(index++, *stack_locals[i]->name());
130 // Due to usage analysis, context-allocated locals are not necessarily in
131 // increasing order: Some of them may be parameters which are allocated before
132 // the non-parameter locals. When the non-parameter locals are sorted
133 // according to usage, the allocated slot indices may not be in increasing
134 // order with the variable list anymore. Thus, we first need to sort them by
135 // context slot index before adding them to the ScopeInfo object.
136 context_locals.Sort(&Variable::CompareIndex);
138 // Add context locals' names.
139 DCHECK(index == scope_info->ContextLocalNameEntriesIndex());
140 for (int i = 0; i < context_local_count; ++i) {
141 scope_info->set(index++, *context_locals[i]->name());
144 // Add context globals' names.
145 DCHECK(index == scope_info->ContextGlobalNameEntriesIndex());
146 for (int i = 0; i < context_global_count; ++i) {
147 scope_info->set(index++, *context_globals[i]->name());
150 // Add context locals' info.
151 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
152 for (int i = 0; i < context_local_count; ++i) {
153 Variable* var = context_locals[i];
155 ContextLocalMode::encode(var->mode()) |
156 ContextLocalInitFlag::encode(var->initialization_flag()) |
157 ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned());
158 scope_info->set(index++, Smi::FromInt(value));
161 // Add context globals' info.
162 DCHECK(index == scope_info->ContextGlobalInfoEntriesIndex());
163 for (int i = 0; i < context_global_count; ++i) {
164 Variable* var = context_globals[i];
165 // TODO(ishell): do we need this kind of info for globals here?
167 ContextLocalMode::encode(var->mode()) |
168 ContextLocalInitFlag::encode(var->initialization_flag()) |
169 ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned());
170 scope_info->set(index++, Smi::FromInt(value));
173 DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
174 for (int i = 0; i < strong_mode_free_variable_count; ++i) {
175 scope_info->set(index++, *strong_mode_free_variables[i]->name());
178 DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex());
179 for (int i = 0; i < strong_mode_free_variable_count; ++i) {
180 // Unfortunately, the source code positions are stored as int even though
181 // int32_t would be enough (given the maximum source code length).
182 Handle<Object> start_position = factory->NewNumberFromInt(
183 static_cast<int32_t>(strong_mode_free_variables[i]
184 ->strong_mode_reference_start_position()));
185 scope_info->set(index++, *start_position);
186 Handle<Object> end_position = factory->NewNumberFromInt(
187 static_cast<int32_t>(strong_mode_free_variables[i]
188 ->strong_mode_reference_end_position()));
189 scope_info->set(index++, *end_position);
192 // If the receiver is allocated, add its index.
193 DCHECK(index == scope_info->ReceiverEntryIndex());
195 int var_index = scope->receiver()->index();
196 scope_info->set(index++, Smi::FromInt(var_index));
197 // ?? DCHECK(receiver_info != CONTEXT || var_index ==
198 // scope_info->ContextLength() - 1);
201 // If present, add the function variable name and its index.
202 DCHECK(index == scope_info->FunctionNameEntryIndex());
203 if (has_function_name) {
204 int var_index = scope->function()->proxy()->var()->index();
205 scope_info->set(index++, *scope->function()->proxy()->name());
206 scope_info->set(index++, Smi::FromInt(var_index));
207 DCHECK(function_name_info != CONTEXT ||
208 var_index == scope_info->ContextLength() - 1);
211 DCHECK(index == scope_info->length());
212 DCHECK(scope->num_parameters() == scope_info->ParameterCount());
213 DCHECK(scope->num_heap_slots() == scope_info->ContextLength() ||
214 (scope->num_heap_slots() == kVariablePartIndex &&
215 scope_info->ContextLength() == 0));
220 Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
221 DCHECK(isolate->bootstrapper()->IsActive());
223 const int stack_local_count = 0;
224 const int context_local_count = 1;
225 const int context_global_count = 0;
226 const int strong_mode_free_variable_count = 0;
227 const bool simple_parameter_list = true;
228 const VariableAllocationInfo receiver_info = CONTEXT;
229 const VariableAllocationInfo function_name_info = NONE;
230 const VariableMode function_variable_mode = VAR;
231 const bool has_function_name = false;
232 const bool has_receiver = true;
233 const int parameter_count = 0;
234 const int length = kVariablePartIndex + parameter_count +
235 (1 + stack_local_count) + 2 * context_local_count +
236 2 * context_global_count +
237 3 * strong_mode_free_variable_count +
238 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
240 Factory* factory = isolate->factory();
241 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
244 int flags = ScopeTypeField::encode(SCRIPT_SCOPE) |
245 CallsEvalField::encode(false) |
246 LanguageModeField::encode(SLOPPY) |
247 ReceiverVariableField::encode(receiver_info) |
248 FunctionVariableField::encode(function_name_info) |
249 FunctionVariableMode::encode(function_variable_mode) |
250 AsmModuleField::encode(false) | AsmFunctionField::encode(false) |
251 IsSimpleParameterListField::encode(simple_parameter_list) |
252 FunctionKindField::encode(FunctionKind::kNormalFunction);
253 scope_info->SetFlags(flags);
254 scope_info->SetParameterCount(parameter_count);
255 scope_info->SetStackLocalCount(stack_local_count);
256 scope_info->SetContextLocalCount(context_local_count);
257 scope_info->SetContextGlobalCount(context_global_count);
258 scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
260 int index = kVariablePartIndex;
261 const int first_slot_index = 0;
262 DCHECK(index == scope_info->StackLocalFirstSlotIndex());
263 scope_info->set(index++, Smi::FromInt(first_slot_index));
264 DCHECK(index == scope_info->StackLocalEntriesIndex());
266 // Here we add info for context-allocated "this".
267 DCHECK(index == scope_info->ContextLocalNameEntriesIndex());
268 scope_info->set(index++, *isolate->factory()->this_string());
269 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
270 const uint32_t value = ContextLocalMode::encode(CONST) |
271 ContextLocalInitFlag::encode(kCreatedInitialized) |
272 ContextLocalMaybeAssignedFlag::encode(kNotAssigned);
273 scope_info->set(index++, Smi::FromInt(value));
275 DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
276 DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex());
278 // And here we record that this scopeinfo binds a receiver.
279 DCHECK(index == scope_info->ReceiverEntryIndex());
280 const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0;
281 scope_info->set(index++, Smi::FromInt(receiver_index));
283 DCHECK(index == scope_info->FunctionNameEntryIndex());
285 DCHECK_EQ(index, scope_info->length());
286 DCHECK_EQ(scope_info->ParameterCount(), 0);
287 DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1);
293 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
294 return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array());
298 ScopeType ScopeInfo::scope_type() {
299 DCHECK(length() > 0);
300 return ScopeTypeField::decode(Flags());
304 bool ScopeInfo::CallsEval() {
305 return length() > 0 && CallsEvalField::decode(Flags());
309 LanguageMode ScopeInfo::language_mode() {
310 return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY;
314 int ScopeInfo::LocalCount() {
315 return StackLocalCount() + ContextLocalCount();
319 int ScopeInfo::StackSlotCount() {
321 bool function_name_stack_slot =
322 FunctionVariableField::decode(Flags()) == STACK;
323 return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
329 int ScopeInfo::ContextLength() {
331 int context_locals = ContextLocalCount();
332 int context_globals = ContextGlobalCount();
333 bool function_name_context_slot =
334 FunctionVariableField::decode(Flags()) == CONTEXT;
335 bool has_context = context_locals > 0 || context_globals > 0 ||
336 function_name_context_slot ||
337 scope_type() == WITH_SCOPE ||
338 (scope_type() == ARROW_SCOPE && CallsSloppyEval()) ||
339 (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
340 scope_type() == MODULE_SCOPE;
343 return Context::MIN_CONTEXT_SLOTS + context_locals + 2 * context_globals +
344 (function_name_context_slot ? 1 : 0);
351 bool ScopeInfo::HasReceiver() {
353 return NONE != ReceiverVariableField::decode(Flags());
360 bool ScopeInfo::HasAllocatedReceiver() {
362 VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags());
363 return allocation == STACK || allocation == CONTEXT;
370 bool ScopeInfo::HasFunctionName() {
372 return NONE != FunctionVariableField::decode(Flags());
379 bool ScopeInfo::HasHeapAllocatedLocals() {
381 return ContextLocalCount() > 0;
388 bool ScopeInfo::HasContext() {
389 return ContextLength() > 0;
393 String* ScopeInfo::FunctionName() {
394 DCHECK(HasFunctionName());
395 return String::cast(get(FunctionNameEntryIndex()));
399 String* ScopeInfo::ParameterName(int var) {
400 DCHECK(0 <= var && var < ParameterCount());
401 int info_index = ParameterEntriesIndex() + var;
402 return String::cast(get(info_index));
406 String* ScopeInfo::LocalName(int var) {
407 DCHECK(0 <= var && var < LocalCount());
408 DCHECK(StackLocalEntriesIndex() + StackLocalCount() ==
409 ContextLocalNameEntriesIndex());
410 int info_index = StackLocalEntriesIndex() + var;
411 return String::cast(get(info_index));
415 String* ScopeInfo::StackLocalName(int var) {
416 DCHECK(0 <= var && var < StackLocalCount());
417 int info_index = StackLocalEntriesIndex() + var;
418 return String::cast(get(info_index));
422 int ScopeInfo::StackLocalIndex(int var) {
423 DCHECK(0 <= var && var < StackLocalCount());
424 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
425 return first_slot_index + var;
429 String* ScopeInfo::ContextLocalName(int var) {
430 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
431 int info_index = ContextLocalNameEntriesIndex() + var;
432 return String::cast(get(info_index));
436 VariableMode ScopeInfo::ContextLocalMode(int var) {
437 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
438 int info_index = ContextLocalInfoEntriesIndex() + var;
439 int value = Smi::cast(get(info_index))->value();
440 return ContextLocalMode::decode(value);
444 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
445 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
446 int info_index = ContextLocalInfoEntriesIndex() + var;
447 int value = Smi::cast(get(info_index))->value();
448 return ContextLocalInitFlag::decode(value);
452 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) {
453 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
454 int info_index = ContextLocalInfoEntriesIndex() + var;
455 int value = Smi::cast(get(info_index))->value();
456 return ContextLocalMaybeAssignedFlag::decode(value);
460 bool ScopeInfo::LocalIsSynthetic(int var) {
461 DCHECK(0 <= var && var < LocalCount());
462 // There's currently no flag stored on the ScopeInfo to indicate that a
463 // variable is a compiler-introduced temporary. However, to avoid conflict
464 // with user declarations, the current temporaries like .generator_object and
465 // .result start with a dot, so we can use that as a flag. It's a hack!
466 Handle<String> name(LocalName(var));
467 return (name->length() > 0 && name->Get(0) == '.') ||
468 name->Equals(*GetIsolate()->factory()->this_string());
472 String* ScopeInfo::StrongModeFreeVariableName(int var) {
473 DCHECK(0 <= var && var < StrongModeFreeVariableCount());
474 int info_index = StrongModeFreeVariableNameEntriesIndex() + var;
475 return String::cast(get(info_index));
479 int ScopeInfo::StrongModeFreeVariableStartPosition(int var) {
480 DCHECK(0 <= var && var < StrongModeFreeVariableCount());
481 int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2;
483 bool ok = get(info_index)->ToInt32(&value);
490 int ScopeInfo::StrongModeFreeVariableEndPosition(int var) {
491 DCHECK(0 <= var && var < StrongModeFreeVariableCount());
492 int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2 + 1;
494 bool ok = get(info_index)->ToInt32(&value);
501 int ScopeInfo::StackSlotIndex(String* name) {
502 DCHECK(name->IsInternalizedString());
504 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
505 int start = StackLocalEntriesIndex();
506 int end = StackLocalEntriesIndex() + StackLocalCount();
507 for (int i = start; i < end; ++i) {
508 if (name == get(i)) {
509 return i - start + first_slot_index;
517 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
518 Handle<String> name, VariableMode* mode,
519 VariableLocation* location,
520 InitializationFlag* init_flag,
521 MaybeAssignedFlag* maybe_assigned_flag) {
522 DCHECK(name->IsInternalizedString());
523 DCHECK(mode != NULL);
524 DCHECK(location != NULL);
525 DCHECK(init_flag != NULL);
526 if (scope_info->length() > 0) {
527 ContextSlotCache* context_slot_cache =
528 scope_info->GetIsolate()->context_slot_cache();
529 int result = context_slot_cache->Lookup(*scope_info, *name, mode, location,
530 init_flag, maybe_assigned_flag);
531 if (result != ContextSlotCache::kNotFound) {
532 DCHECK(result < scope_info->ContextLength());
536 DCHECK_EQ(scope_info->ContextGlobalNameEntriesIndex(),
537 scope_info->ContextLocalNameEntriesIndex() +
538 scope_info->ContextLocalCount());
539 int start = scope_info->ContextLocalNameEntriesIndex();
540 int end = scope_info->ContextGlobalNameEntriesIndex() +
541 scope_info->ContextGlobalCount();
542 for (int i = start; i < end; ++i) {
543 if (*name == scope_info->get(i)) {
545 *mode = scope_info->ContextLocalMode(var);
546 *init_flag = scope_info->ContextLocalInitFlag(var);
547 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
549 if (var < scope_info->ContextLocalCount()) {
550 *location = VariableLocation::CONTEXT;
551 result = Context::MIN_CONTEXT_SLOTS + var;
553 var -= scope_info->ContextLocalCount();
554 *location = VariableLocation::GLOBAL;
555 result = Context::MIN_CONTEXT_SLOTS +
556 scope_info->ContextLocalCount() + 2 * var;
559 context_slot_cache->Update(scope_info, name, *mode, *location,
560 *init_flag, *maybe_assigned_flag, result);
561 DCHECK(result < scope_info->ContextLength());
565 // Cache as not found. Mode, location, init flag and maybe assigned flag
567 context_slot_cache->Update(scope_info, name, TEMPORARY,
568 VariableLocation::CONTEXT, kNeedsInitialization,
575 String* ScopeInfo::ContextSlotName(int slot_index) {
576 // TODO(bmeurer): Simplify this once we have only a single slot for both reads
577 // and writes to context globals; currently we have 2 slots per context
578 // global, and these are located after the common context slots (of which we
579 // always have Context::MIN_CONTEXT_SLOTS) and the context locals.
581 slot_index - (Context::MIN_CONTEXT_SLOTS + ContextLocalCount());
583 DCHECK_LT(var, 2 * ContextGlobalCount());
584 return ContextLocalName(ContextLocalCount() + var / 2);
588 int ScopeInfo::ParameterIndex(String* name) {
589 DCHECK(name->IsInternalizedString());
591 // We must read parameters from the end since for
592 // multiply declared parameters the value of the
593 // last declaration of that parameter is used
594 // inside a function (and thus we need to look
595 // at the last index). Was bug# 1110337.
596 int start = ParameterEntriesIndex();
597 int end = ParameterEntriesIndex() + ParameterCount();
598 for (int i = end - 1; i >= start; --i) {
599 if (name == get(i)) {
608 int ScopeInfo::ReceiverContextSlotIndex() {
609 if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT)
610 return Smi::cast(get(ReceiverEntryIndex()))->value();
615 int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) {
616 DCHECK(name->IsInternalizedString());
617 DCHECK(mode != NULL);
619 if (FunctionVariableField::decode(Flags()) == CONTEXT &&
620 FunctionName() == name) {
621 *mode = FunctionVariableMode::decode(Flags());
622 return Smi::cast(get(FunctionNameEntryIndex() + 1))->value();
629 FunctionKind ScopeInfo::function_kind() {
630 return FunctionKindField::decode(Flags());
634 void ScopeInfo::CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info,
635 Handle<Context> context,
636 Handle<JSObject> scope_object) {
637 Isolate* isolate = scope_info->GetIsolate();
638 int local_count = scope_info->ContextLocalCount();
639 if (local_count == 0) return;
640 // Fill all context locals to the context extension.
641 int first_context_var = scope_info->StackLocalCount();
642 int start = scope_info->ContextLocalNameEntriesIndex();
643 for (int i = 0; i < local_count; ++i) {
644 if (scope_info->LocalIsSynthetic(first_context_var + i)) continue;
645 int context_index = Context::MIN_CONTEXT_SLOTS + i;
646 Handle<Object> value = Handle<Object>(context->get(context_index), isolate);
647 // Reflect variables under TDZ as undefined in scope object.
648 if (value->IsTheHole()) continue;
649 // This should always succeed.
650 // TODO(verwaest): Use AddDataProperty instead.
651 JSObject::SetOwnPropertyIgnoreAttributes(
652 scope_object, handle(String::cast(scope_info->get(i + start))), value,
658 int ScopeInfo::ParameterEntriesIndex() {
659 DCHECK(length() > 0);
660 return kVariablePartIndex;
664 int ScopeInfo::StackLocalFirstSlotIndex() {
665 return ParameterEntriesIndex() + ParameterCount();
669 int ScopeInfo::StackLocalEntriesIndex() {
670 return StackLocalFirstSlotIndex() + 1;
674 int ScopeInfo::ContextLocalNameEntriesIndex() {
675 return StackLocalEntriesIndex() + StackLocalCount();
679 int ScopeInfo::ContextGlobalNameEntriesIndex() {
680 return ContextLocalNameEntriesIndex() + ContextLocalCount();
684 int ScopeInfo::ContextLocalInfoEntriesIndex() {
685 return ContextGlobalNameEntriesIndex() + ContextGlobalCount();
689 int ScopeInfo::ContextGlobalInfoEntriesIndex() {
690 return ContextLocalInfoEntriesIndex() + ContextLocalCount();
694 int ScopeInfo::StrongModeFreeVariableNameEntriesIndex() {
695 return ContextGlobalInfoEntriesIndex() + ContextGlobalCount();
699 int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() {
700 return StrongModeFreeVariableNameEntriesIndex() +
701 StrongModeFreeVariableCount();
705 int ScopeInfo::ReceiverEntryIndex() {
706 return StrongModeFreeVariablePositionEntriesIndex() +
707 2 * StrongModeFreeVariableCount();
711 int ScopeInfo::FunctionNameEntryIndex() {
712 return ReceiverEntryIndex() + (HasAllocatedReceiver() ? 1 : 0);
716 int ContextSlotCache::Hash(Object* data, String* name) {
717 // Uses only lower 32 bits if pointers are larger.
718 uintptr_t addr_hash =
719 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2;
720 return static_cast<int>((addr_hash ^ name->Hash()) % kLength);
724 int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode,
725 VariableLocation* location,
726 InitializationFlag* init_flag,
727 MaybeAssignedFlag* maybe_assigned_flag) {
728 int index = Hash(data, name);
729 Key& key = keys_[index];
730 if ((key.data == data) && key.name->Equals(name)) {
731 Value result(values_[index]);
732 if (mode != NULL) *mode = result.mode();
733 if (location != NULL) *location = result.location();
734 if (init_flag != NULL) *init_flag = result.initialization_flag();
735 if (maybe_assigned_flag != NULL)
736 *maybe_assigned_flag = result.maybe_assigned_flag();
737 return result.index() + kNotFound;
743 void ContextSlotCache::Update(Handle<Object> data, Handle<String> name,
744 VariableMode mode, VariableLocation location,
745 InitializationFlag init_flag,
746 MaybeAssignedFlag maybe_assigned_flag,
748 DisallowHeapAllocation no_gc;
749 Handle<String> internalized_name;
750 DCHECK(slot_index > kNotFound);
751 if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
752 ToHandle(&internalized_name)) {
753 int index = Hash(*data, *internalized_name);
754 Key& key = keys_[index];
756 key.name = *internalized_name;
757 // Please note value only takes a uint as index.
758 values_[index] = Value(mode, location, init_flag, maybe_assigned_flag,
759 slot_index - kNotFound).raw();
761 ValidateEntry(data, name, mode, location, init_flag, maybe_assigned_flag,
768 void ContextSlotCache::Clear() {
769 for (int index = 0; index < kLength; index++) keys_[index].data = NULL;
775 void ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name,
777 VariableLocation location,
778 InitializationFlag init_flag,
779 MaybeAssignedFlag maybe_assigned_flag,
781 DisallowHeapAllocation no_gc;
782 Handle<String> internalized_name;
783 if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
784 ToHandle(&internalized_name)) {
785 int index = Hash(*data, *name);
786 Key& key = keys_[index];
787 DCHECK(key.data == *data);
788 DCHECK(key.name->Equals(*name));
789 Value result(values_[index]);
790 DCHECK(result.mode() == mode);
791 DCHECK(result.location() == location);
792 DCHECK(result.initialization_flag() == init_flag);
793 DCHECK(result.maybe_assigned_flag() == maybe_assigned_flag);
794 DCHECK(result.index() + kNotFound == slot_index);
799 static void PrintList(const char* list_name,
800 int nof_internal_slots,
803 ScopeInfo* scope_info) {
805 PrintF("\n // %s\n", list_name);
806 if (nof_internal_slots > 0) {
807 PrintF(" %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
809 for (int i = nof_internal_slots; start < end; ++i, ++start) {
811 String::cast(scope_info->get(start))->ShortPrint();
818 void ScopeInfo::Print() {
819 PrintF("ScopeInfo ");
820 if (HasFunctionName()) {
821 FunctionName()->ShortPrint();
823 PrintF("/* no function name */");
827 PrintList("parameters", 0,
828 ParameterEntriesIndex(),
829 ParameterEntriesIndex() + ParameterCount(),
831 PrintList("stack slots", 0,
832 StackLocalEntriesIndex(),
833 StackLocalEntriesIndex() + StackLocalCount(),
835 PrintList("context slots",
836 Context::MIN_CONTEXT_SLOTS,
837 ContextLocalNameEntriesIndex(),
838 ContextLocalNameEntriesIndex() + ContextLocalCount(),
846 //---------------------------------------------------------------------------
849 Handle<ModuleInfo> ModuleInfo::Create(Isolate* isolate,
850 ModuleDescriptor* descriptor,
852 Handle<ModuleInfo> info = Allocate(isolate, descriptor->Length());
853 info->set_host_index(descriptor->Index());
855 for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done();
857 Variable* var = scope->LookupLocal(it.local_name());
858 info->set_name(i, *(it.export_name()->string()));
859 info->set_mode(i, var->mode());
860 DCHECK(var->index() >= 0);
861 info->set_index(i, var->index());
863 DCHECK(i == info->length());
867 } // namespace internal