blob: 668879fe5129f63140dfee72ca9d64bad05d062f [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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.
4
5#include "src/ast/scopeinfo.h"
6
7#include <stdlib.h>
8
9#include "src/ast/scopes.h"
10#include "src/bootstrapper.h"
11
12namespace v8 {
13namespace internal {
14
15
16Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
17 Scope* scope) {
18 // Collect stack and context locals.
19 ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone);
20 ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone);
21 ZoneList<Variable*> context_globals(scope->ContextGlobalCount(), zone);
22 ZoneList<Variable*> strong_mode_free_variables(0, zone);
23
24 scope->CollectStackAndContextLocals(&stack_locals, &context_locals,
25 &context_globals,
26 &strong_mode_free_variables);
27 const int stack_local_count = stack_locals.length();
28 const int context_local_count = context_locals.length();
29 const int context_global_count = context_globals.length();
30 const int strong_mode_free_variable_count =
31 strong_mode_free_variables.length();
32 // Make sure we allocate the correct amount.
33 DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
34 DCHECK_EQ(scope->ContextGlobalCount(), context_global_count);
35
36 // Determine use and location of the "this" binding if it is present.
37 VariableAllocationInfo receiver_info;
38 if (scope->has_this_declaration()) {
39 Variable* var = scope->receiver();
40 if (!var->is_used()) {
41 receiver_info = UNUSED;
42 } else if (var->IsContextSlot()) {
43 receiver_info = CONTEXT;
44 } else {
45 DCHECK(var->IsParameter());
46 receiver_info = STACK;
47 }
48 } else {
49 receiver_info = NONE;
50 }
51
52 bool has_new_target = scope->new_target_var() != nullptr;
53
54 // Determine use and location of the function variable if it is present.
55 VariableAllocationInfo function_name_info;
56 VariableMode function_variable_mode;
57 if (scope->is_function_scope() && scope->function() != NULL) {
58 Variable* var = scope->function()->proxy()->var();
59 if (!var->is_used()) {
60 function_name_info = UNUSED;
61 } else if (var->IsContextSlot()) {
62 function_name_info = CONTEXT;
63 } else {
64 DCHECK(var->IsStackLocal());
65 function_name_info = STACK;
66 }
67 function_variable_mode = var->mode();
68 } else {
69 function_name_info = NONE;
70 function_variable_mode = VAR;
71 }
72 DCHECK(context_global_count == 0 || scope->scope_type() == SCRIPT_SCOPE);
73
74 const bool has_function_name = function_name_info != NONE;
75 const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
76 const int parameter_count = scope->num_parameters();
77 const int length = kVariablePartIndex + parameter_count +
78 (1 + stack_local_count) + 2 * context_local_count +
79 2 * context_global_count +
80 3 * strong_mode_free_variable_count +
81 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
82
83 Factory* factory = isolate->factory();
84 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
85
86 bool has_simple_parameters =
87 scope->is_function_scope() && scope->has_simple_parameters();
88
89 // Encode the flags.
90 int flags = ScopeTypeField::encode(scope->scope_type()) |
91 CallsEvalField::encode(scope->calls_eval()) |
92 LanguageModeField::encode(scope->language_mode()) |
93 DeclarationScopeField::encode(scope->is_declaration_scope()) |
94 ReceiverVariableField::encode(receiver_info) |
95 HasNewTargetField::encode(has_new_target) |
96 FunctionVariableField::encode(function_name_info) |
97 FunctionVariableMode::encode(function_variable_mode) |
98 AsmModuleField::encode(scope->asm_module()) |
99 AsmFunctionField::encode(scope->asm_function()) |
100 HasSimpleParametersField::encode(has_simple_parameters) |
101 FunctionKindField::encode(scope->function_kind());
102 scope_info->SetFlags(flags);
103 scope_info->SetParameterCount(parameter_count);
104 scope_info->SetStackLocalCount(stack_local_count);
105 scope_info->SetContextLocalCount(context_local_count);
106 scope_info->SetContextGlobalCount(context_global_count);
107 scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
108
109 int index = kVariablePartIndex;
110 // Add parameters.
111 DCHECK(index == scope_info->ParameterEntriesIndex());
112 for (int i = 0; i < parameter_count; ++i) {
113 scope_info->set(index++, *scope->parameter(i)->name());
114 }
115
116 // Add stack locals' names. We are assuming that the stack locals'
117 // slots are allocated in increasing order, so we can simply add
118 // them to the ScopeInfo object.
119 int first_slot_index;
120 if (stack_local_count > 0) {
121 first_slot_index = stack_locals[0]->index();
122 } else {
123 first_slot_index = 0;
124 }
125 DCHECK(index == scope_info->StackLocalFirstSlotIndex());
126 scope_info->set(index++, Smi::FromInt(first_slot_index));
127 DCHECK(index == scope_info->StackLocalEntriesIndex());
128 for (int i = 0; i < stack_local_count; ++i) {
129 DCHECK(stack_locals[i]->index() == first_slot_index + i);
130 scope_info->set(index++, *stack_locals[i]->name());
131 }
132
133 // Due to usage analysis, context-allocated locals are not necessarily in
134 // increasing order: Some of them may be parameters which are allocated before
135 // the non-parameter locals. When the non-parameter locals are sorted
136 // according to usage, the allocated slot indices may not be in increasing
137 // order with the variable list anymore. Thus, we first need to sort them by
138 // context slot index before adding them to the ScopeInfo object.
139 context_locals.Sort(&Variable::CompareIndex);
140
141 // Add context locals' names.
142 DCHECK(index == scope_info->ContextLocalNameEntriesIndex());
143 for (int i = 0; i < context_local_count; ++i) {
144 scope_info->set(index++, *context_locals[i]->name());
145 }
146
147 // Add context globals' names.
148 DCHECK(index == scope_info->ContextGlobalNameEntriesIndex());
149 for (int i = 0; i < context_global_count; ++i) {
150 scope_info->set(index++, *context_globals[i]->name());
151 }
152
153 // Add context locals' info.
154 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
155 for (int i = 0; i < context_local_count; ++i) {
156 Variable* var = context_locals[i];
157 uint32_t value =
158 ContextLocalMode::encode(var->mode()) |
159 ContextLocalInitFlag::encode(var->initialization_flag()) |
160 ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned());
161 scope_info->set(index++, Smi::FromInt(value));
162 }
163
164 // Add context globals' info.
165 DCHECK(index == scope_info->ContextGlobalInfoEntriesIndex());
166 for (int i = 0; i < context_global_count; ++i) {
167 Variable* var = context_globals[i];
168 // TODO(ishell): do we need this kind of info for globals here?
169 uint32_t value =
170 ContextLocalMode::encode(var->mode()) |
171 ContextLocalInitFlag::encode(var->initialization_flag()) |
172 ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned());
173 scope_info->set(index++, Smi::FromInt(value));
174 }
175
176 DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
177 for (int i = 0; i < strong_mode_free_variable_count; ++i) {
178 scope_info->set(index++, *strong_mode_free_variables[i]->name());
179 }
180
181 DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex());
182 for (int i = 0; i < strong_mode_free_variable_count; ++i) {
183 // Unfortunately, the source code positions are stored as int even though
184 // int32_t would be enough (given the maximum source code length).
185 Handle<Object> start_position = factory->NewNumberFromInt(
186 static_cast<int32_t>(strong_mode_free_variables[i]
187 ->strong_mode_reference_start_position()));
188 scope_info->set(index++, *start_position);
189 Handle<Object> end_position = factory->NewNumberFromInt(
190 static_cast<int32_t>(strong_mode_free_variables[i]
191 ->strong_mode_reference_end_position()));
192 scope_info->set(index++, *end_position);
193 }
194
195 // If the receiver is allocated, add its index.
196 DCHECK(index == scope_info->ReceiverEntryIndex());
197 if (has_receiver) {
198 int var_index = scope->receiver()->index();
199 scope_info->set(index++, Smi::FromInt(var_index));
200 // ?? DCHECK(receiver_info != CONTEXT || var_index ==
201 // scope_info->ContextLength() - 1);
202 }
203
204 // If present, add the function variable name and its index.
205 DCHECK(index == scope_info->FunctionNameEntryIndex());
206 if (has_function_name) {
207 int var_index = scope->function()->proxy()->var()->index();
208 scope_info->set(index++, *scope->function()->proxy()->name());
209 scope_info->set(index++, Smi::FromInt(var_index));
210 DCHECK(function_name_info != CONTEXT ||
211 var_index == scope_info->ContextLength() - 1);
212 }
213
214 DCHECK(index == scope_info->length());
215 DCHECK(scope->num_parameters() == scope_info->ParameterCount());
216 DCHECK(scope->num_heap_slots() == scope_info->ContextLength() ||
217 (scope->num_heap_slots() == kVariablePartIndex &&
218 scope_info->ContextLength() == 0));
219 return scope_info;
220}
221
222
223Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
224 DCHECK(isolate->bootstrapper()->IsActive());
225
226 const int stack_local_count = 0;
227 const int context_local_count = 1;
228 const int context_global_count = 0;
229 const int strong_mode_free_variable_count = 0;
230 const bool has_simple_parameters = true;
231 const VariableAllocationInfo receiver_info = CONTEXT;
232 const VariableAllocationInfo function_name_info = NONE;
233 const VariableMode function_variable_mode = VAR;
234 const bool has_function_name = false;
235 const bool has_receiver = true;
236 const int parameter_count = 0;
237 const int length = kVariablePartIndex + parameter_count +
238 (1 + stack_local_count) + 2 * context_local_count +
239 2 * context_global_count +
240 3 * strong_mode_free_variable_count +
241 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0);
242
243 Factory* factory = isolate->factory();
244 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
245
246 // Encode the flags.
247 int flags = ScopeTypeField::encode(SCRIPT_SCOPE) |
248 CallsEvalField::encode(false) |
249 LanguageModeField::encode(SLOPPY) |
250 DeclarationScopeField::encode(true) |
251 ReceiverVariableField::encode(receiver_info) |
252 FunctionVariableField::encode(function_name_info) |
253 FunctionVariableMode::encode(function_variable_mode) |
254 AsmModuleField::encode(false) | AsmFunctionField::encode(false) |
255 HasSimpleParametersField::encode(has_simple_parameters) |
256 FunctionKindField::encode(FunctionKind::kNormalFunction);
257 scope_info->SetFlags(flags);
258 scope_info->SetParameterCount(parameter_count);
259 scope_info->SetStackLocalCount(stack_local_count);
260 scope_info->SetContextLocalCount(context_local_count);
261 scope_info->SetContextGlobalCount(context_global_count);
262 scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);
263
264 int index = kVariablePartIndex;
265 const int first_slot_index = 0;
266 DCHECK(index == scope_info->StackLocalFirstSlotIndex());
267 scope_info->set(index++, Smi::FromInt(first_slot_index));
268 DCHECK(index == scope_info->StackLocalEntriesIndex());
269
270 // Here we add info for context-allocated "this".
271 DCHECK(index == scope_info->ContextLocalNameEntriesIndex());
272 scope_info->set(index++, *isolate->factory()->this_string());
273 DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
274 const uint32_t value = ContextLocalMode::encode(CONST) |
275 ContextLocalInitFlag::encode(kCreatedInitialized) |
276 ContextLocalMaybeAssignedFlag::encode(kNotAssigned);
277 scope_info->set(index++, Smi::FromInt(value));
278
279 DCHECK(index == scope_info->StrongModeFreeVariableNameEntriesIndex());
280 DCHECK(index == scope_info->StrongModeFreeVariablePositionEntriesIndex());
281
282 // And here we record that this scopeinfo binds a receiver.
283 DCHECK(index == scope_info->ReceiverEntryIndex());
284 const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0;
285 scope_info->set(index++, Smi::FromInt(receiver_index));
286
287 DCHECK(index == scope_info->FunctionNameEntryIndex());
288
289 DCHECK_EQ(index, scope_info->length());
290 DCHECK_EQ(scope_info->ParameterCount(), 0);
291 DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1);
292
293 return scope_info;
294}
295
296
297ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
298 return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array());
299}
300
301
302ScopeType ScopeInfo::scope_type() {
303 DCHECK(length() > 0);
304 return ScopeTypeField::decode(Flags());
305}
306
307
308bool ScopeInfo::CallsEval() {
309 return length() > 0 && CallsEvalField::decode(Flags());
310}
311
312
313LanguageMode ScopeInfo::language_mode() {
314 return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY;
315}
316
317
318bool ScopeInfo::is_declaration_scope() {
319 return DeclarationScopeField::decode(Flags());
320}
321
322
323int ScopeInfo::LocalCount() {
324 return StackLocalCount() + ContextLocalCount();
325}
326
327
328int ScopeInfo::StackSlotCount() {
329 if (length() > 0) {
330 bool function_name_stack_slot =
331 FunctionVariableField::decode(Flags()) == STACK;
332 return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
333 }
334 return 0;
335}
336
337
338int ScopeInfo::ContextLength() {
339 if (length() > 0) {
340 int context_locals = ContextLocalCount();
341 int context_globals = ContextGlobalCount();
342 bool function_name_context_slot =
343 FunctionVariableField::decode(Flags()) == CONTEXT;
344 bool has_context = context_locals > 0 || context_globals > 0 ||
345 function_name_context_slot ||
346 scope_type() == WITH_SCOPE ||
347 (scope_type() == BLOCK_SCOPE && CallsSloppyEval() &&
348 is_declaration_scope()) ||
349 (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
350 scope_type() == MODULE_SCOPE;
351
352 if (has_context) {
353 return Context::MIN_CONTEXT_SLOTS + context_locals + context_globals +
354 (function_name_context_slot ? 1 : 0);
355 }
356 }
357 return 0;
358}
359
360
361bool ScopeInfo::HasReceiver() {
362 if (length() > 0) {
363 return NONE != ReceiverVariableField::decode(Flags());
364 } else {
365 return false;
366 }
367}
368
369
370bool ScopeInfo::HasAllocatedReceiver() {
371 if (length() > 0) {
372 VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags());
373 return allocation == STACK || allocation == CONTEXT;
374 } else {
375 return false;
376 }
377}
378
379
380bool ScopeInfo::HasNewTarget() { return HasNewTargetField::decode(Flags()); }
381
382
383bool ScopeInfo::HasFunctionName() {
384 if (length() > 0) {
385 return NONE != FunctionVariableField::decode(Flags());
386 } else {
387 return false;
388 }
389}
390
391
392bool ScopeInfo::HasHeapAllocatedLocals() {
393 if (length() > 0) {
394 return ContextLocalCount() > 0;
395 } else {
396 return false;
397 }
398}
399
400
401bool ScopeInfo::HasContext() {
402 return ContextLength() > 0;
403}
404
405
406String* ScopeInfo::FunctionName() {
407 DCHECK(HasFunctionName());
408 return String::cast(get(FunctionNameEntryIndex()));
409}
410
411
412String* ScopeInfo::ParameterName(int var) {
413 DCHECK(0 <= var && var < ParameterCount());
414 int info_index = ParameterEntriesIndex() + var;
415 return String::cast(get(info_index));
416}
417
418
419String* ScopeInfo::LocalName(int var) {
420 DCHECK(0 <= var && var < LocalCount());
421 DCHECK(StackLocalEntriesIndex() + StackLocalCount() ==
422 ContextLocalNameEntriesIndex());
423 int info_index = StackLocalEntriesIndex() + var;
424 return String::cast(get(info_index));
425}
426
427
428String* ScopeInfo::StackLocalName(int var) {
429 DCHECK(0 <= var && var < StackLocalCount());
430 int info_index = StackLocalEntriesIndex() + var;
431 return String::cast(get(info_index));
432}
433
434
435int ScopeInfo::StackLocalIndex(int var) {
436 DCHECK(0 <= var && var < StackLocalCount());
437 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
438 return first_slot_index + var;
439}
440
441
442String* ScopeInfo::ContextLocalName(int var) {
443 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
444 int info_index = ContextLocalNameEntriesIndex() + var;
445 return String::cast(get(info_index));
446}
447
448
449VariableMode ScopeInfo::ContextLocalMode(int var) {
450 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
451 int info_index = ContextLocalInfoEntriesIndex() + var;
452 int value = Smi::cast(get(info_index))->value();
453 return ContextLocalMode::decode(value);
454}
455
456
457InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
458 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
459 int info_index = ContextLocalInfoEntriesIndex() + var;
460 int value = Smi::cast(get(info_index))->value();
461 return ContextLocalInitFlag::decode(value);
462}
463
464
465MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) {
466 DCHECK(0 <= var && var < ContextLocalCount() + ContextGlobalCount());
467 int info_index = ContextLocalInfoEntriesIndex() + var;
468 int value = Smi::cast(get(info_index))->value();
469 return ContextLocalMaybeAssignedFlag::decode(value);
470}
471
472
473bool ScopeInfo::LocalIsSynthetic(int var) {
474 DCHECK(0 <= var && var < LocalCount());
475 // There's currently no flag stored on the ScopeInfo to indicate that a
476 // variable is a compiler-introduced temporary. However, to avoid conflict
477 // with user declarations, the current temporaries like .generator_object and
478 // .result start with a dot, so we can use that as a flag. It's a hack!
479 Handle<String> name(LocalName(var));
480 return (name->length() > 0 && name->Get(0) == '.') ||
481 name->Equals(*GetIsolate()->factory()->this_string());
482}
483
484
485String* ScopeInfo::StrongModeFreeVariableName(int var) {
486 DCHECK(0 <= var && var < StrongModeFreeVariableCount());
487 int info_index = StrongModeFreeVariableNameEntriesIndex() + var;
488 return String::cast(get(info_index));
489}
490
491
492int ScopeInfo::StrongModeFreeVariableStartPosition(int var) {
493 DCHECK(0 <= var && var < StrongModeFreeVariableCount());
494 int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2;
495 int32_t value = 0;
496 bool ok = get(info_index)->ToInt32(&value);
497 USE(ok);
498 DCHECK(ok);
499 return value;
500}
501
502
503int ScopeInfo::StrongModeFreeVariableEndPosition(int var) {
504 DCHECK(0 <= var && var < StrongModeFreeVariableCount());
505 int info_index = StrongModeFreeVariablePositionEntriesIndex() + var * 2 + 1;
506 int32_t value = 0;
507 bool ok = get(info_index)->ToInt32(&value);
508 USE(ok);
509 DCHECK(ok);
510 return value;
511}
512
513
514int ScopeInfo::StackSlotIndex(String* name) {
515 DCHECK(name->IsInternalizedString());
516 if (length() > 0) {
517 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
518 int start = StackLocalEntriesIndex();
519 int end = StackLocalEntriesIndex() + StackLocalCount();
520 for (int i = start; i < end; ++i) {
521 if (name == get(i)) {
522 return i - start + first_slot_index;
523 }
524 }
525 }
526 return -1;
527}
528
529
530int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
531 Handle<String> name, VariableMode* mode,
532 InitializationFlag* init_flag,
533 MaybeAssignedFlag* maybe_assigned_flag) {
534 DCHECK(name->IsInternalizedString());
535 DCHECK(mode != NULL);
536 DCHECK(init_flag != NULL);
537 if (scope_info->length() > 0) {
538 ContextSlotCache* context_slot_cache =
539 scope_info->GetIsolate()->context_slot_cache();
540 int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag,
541 maybe_assigned_flag);
542 if (result != ContextSlotCache::kNotFound) {
543 DCHECK(result < scope_info->ContextLength());
544 return result;
545 }
546
547 int start = scope_info->ContextLocalNameEntriesIndex();
548 int end = scope_info->ContextLocalNameEntriesIndex() +
549 scope_info->ContextLocalCount();
550 for (int i = start; i < end; ++i) {
551 if (*name == scope_info->get(i)) {
552 int var = i - start;
553 *mode = scope_info->ContextLocalMode(var);
554 *init_flag = scope_info->ContextLocalInitFlag(var);
555 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
556 result = Context::MIN_CONTEXT_SLOTS + var;
557
558 context_slot_cache->Update(scope_info, name, *mode, *init_flag,
559 *maybe_assigned_flag, result);
560 DCHECK(result < scope_info->ContextLength());
561 return result;
562 }
563 }
564 // Cache as not found. Mode, init flag and maybe assigned flag don't matter.
565 context_slot_cache->Update(scope_info, name, TEMPORARY,
566 kNeedsInitialization, kNotAssigned, -1);
567 }
568 return -1;
569}
570
571
572int ScopeInfo::ContextGlobalSlotIndex(Handle<ScopeInfo> scope_info,
573 Handle<String> name, VariableMode* mode,
574 InitializationFlag* init_flag,
575 MaybeAssignedFlag* maybe_assigned_flag) {
576 DCHECK(name->IsInternalizedString());
577 DCHECK(mode != NULL);
578 DCHECK(init_flag != NULL);
579 if (scope_info->length() > 0) {
580 // This is to ensure that ContextLocalMode() and co. queries would work.
581 DCHECK_EQ(scope_info->ContextGlobalNameEntriesIndex(),
582 scope_info->ContextLocalNameEntriesIndex() +
583 scope_info->ContextLocalCount());
584 int base = scope_info->ContextLocalNameEntriesIndex();
585 int start = scope_info->ContextGlobalNameEntriesIndex();
586 int end = scope_info->ContextGlobalNameEntriesIndex() +
587 scope_info->ContextGlobalCount();
588 for (int i = start; i < end; ++i) {
589 if (*name == scope_info->get(i)) {
590 int var = i - base;
591 *mode = scope_info->ContextLocalMode(var);
592 *init_flag = scope_info->ContextLocalInitFlag(var);
593 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
594 int result = Context::MIN_CONTEXT_SLOTS + var;
595 DCHECK(result < scope_info->ContextLength());
596 return result;
597 }
598 }
599 }
600 return -1;
601}
602
603
604String* ScopeInfo::ContextSlotName(int slot_index) {
605 int const var = slot_index - Context::MIN_CONTEXT_SLOTS;
606 DCHECK_LE(0, var);
607 DCHECK_LT(var, ContextLocalCount() + ContextGlobalCount());
608 return ContextLocalName(var);
609}
610
611
612int ScopeInfo::ParameterIndex(String* name) {
613 DCHECK(name->IsInternalizedString());
614 if (length() > 0) {
615 // We must read parameters from the end since for
616 // multiply declared parameters the value of the
617 // last declaration of that parameter is used
618 // inside a function (and thus we need to look
619 // at the last index). Was bug# 1110337.
620 int start = ParameterEntriesIndex();
621 int end = ParameterEntriesIndex() + ParameterCount();
622 for (int i = end - 1; i >= start; --i) {
623 if (name == get(i)) {
624 return i - start;
625 }
626 }
627 }
628 return -1;
629}
630
631
632int ScopeInfo::ReceiverContextSlotIndex() {
633 if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT)
634 return Smi::cast(get(ReceiverEntryIndex()))->value();
635 return -1;
636}
637
638
639int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) {
640 DCHECK(name->IsInternalizedString());
641 DCHECK(mode != NULL);
642 if (length() > 0) {
643 if (FunctionVariableField::decode(Flags()) == CONTEXT &&
644 FunctionName() == name) {
645 *mode = FunctionVariableMode::decode(Flags());
646 return Smi::cast(get(FunctionNameEntryIndex() + 1))->value();
647 }
648 }
649 return -1;
650}
651
652
653FunctionKind ScopeInfo::function_kind() {
654 return FunctionKindField::decode(Flags());
655}
656
657
658int ScopeInfo::ParameterEntriesIndex() {
659 DCHECK(length() > 0);
660 return kVariablePartIndex;
661}
662
663
664int ScopeInfo::StackLocalFirstSlotIndex() {
665 return ParameterEntriesIndex() + ParameterCount();
666}
667
668
669int ScopeInfo::StackLocalEntriesIndex() {
670 return StackLocalFirstSlotIndex() + 1;
671}
672
673
674int ScopeInfo::ContextLocalNameEntriesIndex() {
675 return StackLocalEntriesIndex() + StackLocalCount();
676}
677
678
679int ScopeInfo::ContextGlobalNameEntriesIndex() {
680 return ContextLocalNameEntriesIndex() + ContextLocalCount();
681}
682
683
684int ScopeInfo::ContextLocalInfoEntriesIndex() {
685 return ContextGlobalNameEntriesIndex() + ContextGlobalCount();
686}
687
688
689int ScopeInfo::ContextGlobalInfoEntriesIndex() {
690 return ContextLocalInfoEntriesIndex() + ContextLocalCount();
691}
692
693
694int ScopeInfo::StrongModeFreeVariableNameEntriesIndex() {
695 return ContextGlobalInfoEntriesIndex() + ContextGlobalCount();
696}
697
698
699int ScopeInfo::StrongModeFreeVariablePositionEntriesIndex() {
700 return StrongModeFreeVariableNameEntriesIndex() +
701 StrongModeFreeVariableCount();
702}
703
704
705int ScopeInfo::ReceiverEntryIndex() {
706 return StrongModeFreeVariablePositionEntriesIndex() +
707 2 * StrongModeFreeVariableCount();
708}
709
710
711int ScopeInfo::FunctionNameEntryIndex() {
712 return ReceiverEntryIndex() + (HasAllocatedReceiver() ? 1 : 0);
713}
714
715
716int 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);
721}
722
723
724int ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode,
725 InitializationFlag* init_flag,
726 MaybeAssignedFlag* maybe_assigned_flag) {
727 int index = Hash(data, name);
728 Key& key = keys_[index];
729 if ((key.data == data) && key.name->Equals(name)) {
730 Value result(values_[index]);
731 if (mode != NULL) *mode = result.mode();
732 if (init_flag != NULL) *init_flag = result.initialization_flag();
733 if (maybe_assigned_flag != NULL)
734 *maybe_assigned_flag = result.maybe_assigned_flag();
735 return result.index() + kNotFound;
736 }
737 return kNotFound;
738}
739
740
741void ContextSlotCache::Update(Handle<Object> data, Handle<String> name,
742 VariableMode mode, InitializationFlag init_flag,
743 MaybeAssignedFlag maybe_assigned_flag,
744 int slot_index) {
745 DisallowHeapAllocation no_gc;
746 Handle<String> internalized_name;
747 DCHECK(slot_index > kNotFound);
748 if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
749 ToHandle(&internalized_name)) {
750 int index = Hash(*data, *internalized_name);
751 Key& key = keys_[index];
752 key.data = *data;
753 key.name = *internalized_name;
754 // Please note value only takes a uint as index.
755 values_[index] = Value(mode, init_flag, maybe_assigned_flag,
756 slot_index - kNotFound).raw();
757#ifdef DEBUG
758 ValidateEntry(data, name, mode, init_flag, maybe_assigned_flag, slot_index);
759#endif
760 }
761}
762
763
764void ContextSlotCache::Clear() {
765 for (int index = 0; index < kLength; index++) keys_[index].data = NULL;
766}
767
768
769#ifdef DEBUG
770
771void ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name,
772 VariableMode mode,
773 InitializationFlag init_flag,
774 MaybeAssignedFlag maybe_assigned_flag,
775 int slot_index) {
776 DisallowHeapAllocation no_gc;
777 Handle<String> internalized_name;
778 if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
779 ToHandle(&internalized_name)) {
780 int index = Hash(*data, *name);
781 Key& key = keys_[index];
782 DCHECK(key.data == *data);
783 DCHECK(key.name->Equals(*name));
784 Value result(values_[index]);
785 DCHECK(result.mode() == mode);
786 DCHECK(result.initialization_flag() == init_flag);
787 DCHECK(result.maybe_assigned_flag() == maybe_assigned_flag);
788 DCHECK(result.index() + kNotFound == slot_index);
789 }
790}
791
792
793static void PrintList(const char* list_name,
794 int nof_internal_slots,
795 int start,
796 int end,
797 ScopeInfo* scope_info) {
798 if (start < end) {
799 PrintF("\n // %s\n", list_name);
800 if (nof_internal_slots > 0) {
801 PrintF(" %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
802 }
803 for (int i = nof_internal_slots; start < end; ++i, ++start) {
804 PrintF(" %2d ", i);
805 String::cast(scope_info->get(start))->ShortPrint();
806 PrintF("\n");
807 }
808 }
809}
810
811
812void ScopeInfo::Print() {
813 PrintF("ScopeInfo ");
814 if (HasFunctionName()) {
815 FunctionName()->ShortPrint();
816 } else {
817 PrintF("/* no function name */");
818 }
819 PrintF("{");
820
821 if (length() > 0) {
822 PrintList("parameters", 0, ParameterEntriesIndex(),
823 ParameterEntriesIndex() + ParameterCount(), this);
824 PrintList("stack slots", 0, StackLocalEntriesIndex(),
825 StackLocalEntriesIndex() + StackLocalCount(), this);
826 PrintList("context slots", Context::MIN_CONTEXT_SLOTS,
827 ContextLocalNameEntriesIndex(),
828 ContextLocalNameEntriesIndex() + ContextLocalCount(), this);
829 }
830
831 PrintF("}\n");
832}
833#endif // DEBUG
834
835
836//---------------------------------------------------------------------------
837// ModuleInfo.
838
839Handle<ModuleInfo> ModuleInfo::Create(Isolate* isolate,
840 ModuleDescriptor* descriptor,
841 Scope* scope) {
842 Handle<ModuleInfo> info = Allocate(isolate, descriptor->Length());
843 info->set_host_index(descriptor->Index());
844 int i = 0;
845 for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done();
846 it.Advance(), ++i) {
847 Variable* var = scope->LookupLocal(it.local_name());
848 info->set_name(i, *(it.export_name()->string()));
849 info->set_mode(i, var->mode());
850 DCHECK(var->index() >= 0);
851 info->set_index(i, var->index());
852 }
853 DCHECK(i == info->length());
854 return info;
855}
856
857} // namespace internal
858} // namespace v8