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