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.
4
5 #include <stdlib.h>
6
7 #include "src/ast/context-slot-cache.h"
8 #include "src/ast/scopes.h"
9 #include "src/ast/variables.h"
10 #include "src/bootstrapper.h"
11
12 namespace v8 {
13 namespace internal {
14
15 // An entry in ModuleVariableEntries consists of several slots:
16 enum ModuleVariableEntryOffset {
17 kModuleVariableNameOffset,
18 kModuleVariableIndexOffset,
19 kModuleVariablePropertiesOffset,
20 kModuleVariableEntryLength // Sentinel value.
21 };
22
23 #ifdef DEBUG
Equals(ScopeInfo * other) const24 bool ScopeInfo::Equals(ScopeInfo* other) const {
25 if (length() != other->length()) return false;
26 for (int index = 0; index < length(); ++index) {
27 Object* entry = get(index);
28 Object* other_entry = other->get(index);
29 if (entry->IsSmi()) {
30 if (entry != other_entry) return false;
31 } else {
32 if (HeapObject::cast(entry)->map()->instance_type() !=
33 HeapObject::cast(other_entry)->map()->instance_type()) {
34 return false;
35 }
36 if (entry->IsString()) {
37 if (!String::cast(entry)->Equals(String::cast(other_entry))) {
38 return false;
39 }
40 } else if (entry->IsScopeInfo()) {
41 if (!ScopeInfo::cast(entry)->Equals(ScopeInfo::cast(other_entry))) {
42 return false;
43 }
44 } else if (entry->IsModuleInfo()) {
45 if (!ModuleInfo::cast(entry)->Equals(ModuleInfo::cast(other_entry))) {
46 return false;
47 }
48 } else {
49 UNREACHABLE();
50 return false;
51 }
52 }
53 }
54 return true;
55 }
56 #endif
57
Create(Isolate * isolate,Zone * zone,Scope * scope,MaybeHandle<ScopeInfo> outer_scope)58 Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
59 MaybeHandle<ScopeInfo> outer_scope) {
60 // Collect variables.
61 int stack_local_count = 0;
62 int context_local_count = 0;
63 int module_vars_count = 0;
64 // Stack allocated block scope variables are allocated in the parent
65 // declaration scope, but are recorded in the block scope's scope info. First
66 // slot index indicates at which offset a particular scope starts in the
67 // parent declaration scope.
68 int first_slot_index = 0;
69 for (Variable* var : *scope->locals()) {
70 switch (var->location()) {
71 case VariableLocation::LOCAL:
72 if (stack_local_count == 0) first_slot_index = var->index();
73 stack_local_count++;
74 break;
75 case VariableLocation::CONTEXT:
76 context_local_count++;
77 break;
78 case VariableLocation::MODULE:
79 module_vars_count++;
80 break;
81 default:
82 break;
83 }
84 }
85 DCHECK(module_vars_count == 0 || scope->is_module_scope());
86
87 // Make sure we allocate the correct amount.
88 DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
89
90 // Determine use and location of the "this" binding if it is present.
91 VariableAllocationInfo receiver_info;
92 if (scope->is_declaration_scope() &&
93 scope->AsDeclarationScope()->has_this_declaration()) {
94 Variable* var = scope->AsDeclarationScope()->receiver();
95 if (!var->is_used()) {
96 receiver_info = UNUSED;
97 } else if (var->IsContextSlot()) {
98 receiver_info = CONTEXT;
99 } else {
100 DCHECK(var->IsParameter());
101 receiver_info = STACK;
102 }
103 } else {
104 receiver_info = NONE;
105 }
106
107 bool has_new_target =
108 scope->is_declaration_scope() &&
109 scope->AsDeclarationScope()->new_target_var() != nullptr;
110
111 // Determine use and location of the function variable if it is present.
112 VariableAllocationInfo function_name_info;
113 if (scope->is_function_scope() &&
114 scope->AsDeclarationScope()->function_var() != nullptr) {
115 Variable* var = scope->AsDeclarationScope()->function_var();
116 if (!var->is_used()) {
117 function_name_info = UNUSED;
118 } else if (var->IsContextSlot()) {
119 function_name_info = CONTEXT;
120 } else {
121 DCHECK(var->IsStackLocal());
122 function_name_info = STACK;
123 }
124 } else {
125 function_name_info = NONE;
126 }
127
128 const bool has_function_name = function_name_info != NONE;
129 const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
130 const int parameter_count = scope->num_parameters();
131 const bool has_outer_scope_info = !outer_scope.is_null();
132 const int length = kVariablePartIndex + parameter_count +
133 (1 + stack_local_count) + 2 * context_local_count +
134 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0) +
135 (has_outer_scope_info ? 1 : 0) +
136 (scope->is_module_scope()
137 ? 2 + kModuleVariableEntryLength * module_vars_count
138 : 0);
139
140 Factory* factory = isolate->factory();
141 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
142
143 bool has_simple_parameters = false;
144 bool asm_module = false;
145 bool asm_function = false;
146 FunctionKind function_kind = kNormalFunction;
147 if (scope->is_function_scope()) {
148 DeclarationScope* function_scope = scope->AsDeclarationScope();
149 has_simple_parameters = function_scope->has_simple_parameters();
150 asm_module = function_scope->asm_module();
151 asm_function = function_scope->asm_function();
152 function_kind = function_scope->function_kind();
153 }
154
155 // Encode the flags.
156 int flags =
157 ScopeTypeField::encode(scope->scope_type()) |
158 CallsEvalField::encode(scope->calls_eval()) |
159 LanguageModeField::encode(scope->language_mode()) |
160 DeclarationScopeField::encode(scope->is_declaration_scope()) |
161 ReceiverVariableField::encode(receiver_info) |
162 HasNewTargetField::encode(has_new_target) |
163 FunctionVariableField::encode(function_name_info) |
164 AsmModuleField::encode(asm_module) |
165 AsmFunctionField::encode(asm_function) |
166 HasSimpleParametersField::encode(has_simple_parameters) |
167 FunctionKindField::encode(function_kind) |
168 HasOuterScopeInfoField::encode(has_outer_scope_info) |
169 IsDebugEvaluateScopeField::encode(scope->is_debug_evaluate_scope());
170 scope_info->SetFlags(flags);
171
172 scope_info->SetParameterCount(parameter_count);
173 scope_info->SetStackLocalCount(stack_local_count);
174 scope_info->SetContextLocalCount(context_local_count);
175
176 int index = kVariablePartIndex;
177 // Add parameters.
178 DCHECK_EQ(index, scope_info->ParameterNamesIndex());
179 if (scope->is_declaration_scope()) {
180 for (int i = 0; i < parameter_count; ++i) {
181 scope_info->set(index++,
182 *scope->AsDeclarationScope()->parameter(i)->name());
183 }
184 }
185
186 // Add stack locals' names, context locals' names and info, module variables'
187 // names and info. We are assuming that the stack locals' slots are allocated
188 // in increasing order, so we can simply add them to the ScopeInfo object.
189 // Context locals are added using their index.
190 DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
191 scope_info->set(index++, Smi::FromInt(first_slot_index));
192 DCHECK_EQ(index, scope_info->StackLocalNamesIndex());
193
194 int stack_local_base = index;
195 int context_local_base = stack_local_base + stack_local_count;
196 int context_local_info_base = context_local_base + context_local_count;
197 int module_var_entry = scope_info->ModuleVariablesIndex();
198
199 for (Variable* var : *scope->locals()) {
200 switch (var->location()) {
201 case VariableLocation::LOCAL: {
202 int local_index = var->index() - first_slot_index;
203 DCHECK_LE(0, local_index);
204 DCHECK_LT(local_index, stack_local_count);
205 scope_info->set(stack_local_base + local_index, *var->name());
206 break;
207 }
208 case VariableLocation::CONTEXT: {
209 // Due to duplicate parameters, context locals aren't guaranteed to come
210 // in order.
211 int local_index = var->index() - Context::MIN_CONTEXT_SLOTS;
212 DCHECK_LE(0, local_index);
213 DCHECK_LT(local_index, context_local_count);
214 uint32_t info = VariableModeField::encode(var->mode()) |
215 InitFlagField::encode(var->initialization_flag()) |
216 MaybeAssignedFlagField::encode(var->maybe_assigned());
217 scope_info->set(context_local_base + local_index, *var->name());
218 scope_info->set(context_local_info_base + local_index,
219 Smi::FromInt(info));
220 break;
221 }
222 case VariableLocation::MODULE: {
223 scope_info->set(module_var_entry + kModuleVariableNameOffset,
224 *var->name());
225 scope_info->set(module_var_entry + kModuleVariableIndexOffset,
226 Smi::FromInt(var->index()));
227 uint32_t properties =
228 VariableModeField::encode(var->mode()) |
229 InitFlagField::encode(var->initialization_flag()) |
230 MaybeAssignedFlagField::encode(var->maybe_assigned());
231 scope_info->set(module_var_entry + kModuleVariablePropertiesOffset,
232 Smi::FromInt(properties));
233 module_var_entry += kModuleVariableEntryLength;
234 break;
235 }
236 default:
237 break;
238 }
239 }
240
241 index += stack_local_count + 2 * context_local_count;
242
243 // If the receiver is allocated, add its index.
244 DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
245 if (has_receiver) {
246 int var_index = scope->AsDeclarationScope()->receiver()->index();
247 scope_info->set(index++, Smi::FromInt(var_index));
248 // ?? DCHECK(receiver_info != CONTEXT || var_index ==
249 // scope_info->ContextLength() - 1);
250 }
251
252 // If present, add the function variable name and its index.
253 DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
254 if (has_function_name) {
255 int var_index = scope->AsDeclarationScope()->function_var()->index();
256 scope_info->set(index++,
257 *scope->AsDeclarationScope()->function_var()->name());
258 scope_info->set(index++, Smi::FromInt(var_index));
259 DCHECK(function_name_info != CONTEXT ||
260 var_index == scope_info->ContextLength() - 1);
261 }
262
263 // If present, add the outer scope info.
264 DCHECK(index == scope_info->OuterScopeInfoIndex());
265 if (has_outer_scope_info) {
266 scope_info->set(index++, *outer_scope.ToHandleChecked());
267 }
268
269 // Module-specific information (only for module scopes).
270 if (scope->is_module_scope()) {
271 Handle<ModuleInfo> module_info =
272 ModuleInfo::New(isolate, zone, scope->AsModuleScope()->module());
273 DCHECK_EQ(index, scope_info->ModuleInfoIndex());
274 scope_info->set(index++, *module_info);
275 DCHECK_EQ(index, scope_info->ModuleVariableCountIndex());
276 scope_info->set(index++, Smi::FromInt(module_vars_count));
277 DCHECK_EQ(index, scope_info->ModuleVariablesIndex());
278 // The variable entries themselves have already been written above.
279 index += kModuleVariableEntryLength * module_vars_count;
280 }
281
282 DCHECK_EQ(index, scope_info->length());
283 DCHECK_EQ(scope->num_parameters(), scope_info->ParameterCount());
284 DCHECK_EQ(scope->num_heap_slots(), scope_info->ContextLength());
285 return scope_info;
286 }
287
CreateForWithScope(Isolate * isolate,MaybeHandle<ScopeInfo> outer_scope)288 Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
289 Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope) {
290 const bool has_outer_scope_info = !outer_scope.is_null();
291 const int length = kVariablePartIndex + 1 + (has_outer_scope_info ? 1 : 0);
292
293 Factory* factory = isolate->factory();
294 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
295
296 // Encode the flags.
297 int flags =
298 ScopeTypeField::encode(WITH_SCOPE) | CallsEvalField::encode(false) |
299 LanguageModeField::encode(SLOPPY) | DeclarationScopeField::encode(false) |
300 ReceiverVariableField::encode(NONE) | HasNewTargetField::encode(false) |
301 FunctionVariableField::encode(NONE) | AsmModuleField::encode(false) |
302 AsmFunctionField::encode(false) | HasSimpleParametersField::encode(true) |
303 FunctionKindField::encode(kNormalFunction) |
304 HasOuterScopeInfoField::encode(has_outer_scope_info) |
305 IsDebugEvaluateScopeField::encode(false);
306 scope_info->SetFlags(flags);
307
308 scope_info->SetParameterCount(0);
309 scope_info->SetStackLocalCount(0);
310 scope_info->SetContextLocalCount(0);
311
312 int index = kVariablePartIndex;
313 DCHECK_EQ(index, scope_info->ParameterNamesIndex());
314 DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
315 scope_info->set(index++, Smi::kZero);
316 DCHECK_EQ(index, scope_info->StackLocalNamesIndex());
317 DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
318 DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
319 DCHECK(index == scope_info->OuterScopeInfoIndex());
320 if (has_outer_scope_info) {
321 scope_info->set(index++, *outer_scope.ToHandleChecked());
322 }
323 DCHECK_EQ(index, scope_info->length());
324 DCHECK_EQ(0, scope_info->ParameterCount());
325 DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, scope_info->ContextLength());
326 return scope_info;
327 }
328
CreateGlobalThisBinding(Isolate * isolate)329 Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
330 DCHECK(isolate->bootstrapper()->IsActive());
331
332 const int stack_local_count = 0;
333 const int context_local_count = 1;
334 const bool has_simple_parameters = true;
335 const VariableAllocationInfo receiver_info = CONTEXT;
336 const VariableAllocationInfo function_name_info = NONE;
337 const bool has_function_name = false;
338 const bool has_receiver = true;
339 const bool has_outer_scope_info = false;
340 const int parameter_count = 0;
341 const int length = kVariablePartIndex + parameter_count +
342 (1 + stack_local_count) + 2 * context_local_count +
343 (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0) +
344 (has_outer_scope_info ? 1 : 0);
345
346 Factory* factory = isolate->factory();
347 Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
348
349 // Encode the flags.
350 int flags =
351 ScopeTypeField::encode(SCRIPT_SCOPE) | CallsEvalField::encode(false) |
352 LanguageModeField::encode(SLOPPY) | DeclarationScopeField::encode(true) |
353 ReceiverVariableField::encode(receiver_info) |
354 FunctionVariableField::encode(function_name_info) |
355 AsmModuleField::encode(false) | AsmFunctionField::encode(false) |
356 HasSimpleParametersField::encode(has_simple_parameters) |
357 FunctionKindField::encode(FunctionKind::kNormalFunction) |
358 HasOuterScopeInfoField::encode(has_outer_scope_info) |
359 IsDebugEvaluateScopeField::encode(false);
360 scope_info->SetFlags(flags);
361 scope_info->SetParameterCount(parameter_count);
362 scope_info->SetStackLocalCount(stack_local_count);
363 scope_info->SetContextLocalCount(context_local_count);
364
365 int index = kVariablePartIndex;
366 const int first_slot_index = 0;
367 DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
368 scope_info->set(index++, Smi::FromInt(first_slot_index));
369 DCHECK_EQ(index, scope_info->StackLocalNamesIndex());
370
371 // Here we add info for context-allocated "this".
372 DCHECK_EQ(index, scope_info->ContextLocalNamesIndex());
373 scope_info->set(index++, isolate->heap()->this_string());
374 DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
375 const uint32_t value = VariableModeField::encode(CONST) |
376 InitFlagField::encode(kCreatedInitialized) |
377 MaybeAssignedFlagField::encode(kNotAssigned);
378 scope_info->set(index++, Smi::FromInt(value));
379
380 // And here we record that this scopeinfo binds a receiver.
381 DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
382 const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0;
383 scope_info->set(index++, Smi::FromInt(receiver_index));
384
385 DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
386 DCHECK_EQ(index, scope_info->OuterScopeInfoIndex());
387 DCHECK_EQ(index, scope_info->length());
388 DCHECK_EQ(scope_info->ParameterCount(), 0);
389 DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1);
390
391 return scope_info;
392 }
393
394
Empty(Isolate * isolate)395 ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
396 return isolate->heap()->empty_scope_info();
397 }
398
399
scope_type()400 ScopeType ScopeInfo::scope_type() {
401 DCHECK_LT(0, length());
402 return ScopeTypeField::decode(Flags());
403 }
404
405
CallsEval()406 bool ScopeInfo::CallsEval() {
407 return length() > 0 && CallsEvalField::decode(Flags());
408 }
409
410
language_mode()411 LanguageMode ScopeInfo::language_mode() {
412 return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY;
413 }
414
415
is_declaration_scope()416 bool ScopeInfo::is_declaration_scope() {
417 return DeclarationScopeField::decode(Flags());
418 }
419
420
LocalCount()421 int ScopeInfo::LocalCount() {
422 return StackLocalCount() + ContextLocalCount();
423 }
424
425
StackSlotCount()426 int ScopeInfo::StackSlotCount() {
427 if (length() > 0) {
428 bool function_name_stack_slot =
429 FunctionVariableField::decode(Flags()) == STACK;
430 return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
431 }
432 return 0;
433 }
434
435
ContextLength()436 int ScopeInfo::ContextLength() {
437 if (length() > 0) {
438 int context_locals = ContextLocalCount();
439 bool function_name_context_slot =
440 FunctionVariableField::decode(Flags()) == CONTEXT;
441 bool has_context = context_locals > 0 || function_name_context_slot ||
442 scope_type() == WITH_SCOPE ||
443 (scope_type() == BLOCK_SCOPE && CallsSloppyEval() &&
444 is_declaration_scope()) ||
445 (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
446 scope_type() == MODULE_SCOPE;
447
448 if (has_context) {
449 return Context::MIN_CONTEXT_SLOTS + context_locals +
450 (function_name_context_slot ? 1 : 0);
451 }
452 }
453 return 0;
454 }
455
456
HasReceiver()457 bool ScopeInfo::HasReceiver() {
458 if (length() > 0) {
459 return NONE != ReceiverVariableField::decode(Flags());
460 } else {
461 return false;
462 }
463 }
464
465
HasAllocatedReceiver()466 bool ScopeInfo::HasAllocatedReceiver() {
467 if (length() > 0) {
468 VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags());
469 return allocation == STACK || allocation == CONTEXT;
470 } else {
471 return false;
472 }
473 }
474
475
HasNewTarget()476 bool ScopeInfo::HasNewTarget() { return HasNewTargetField::decode(Flags()); }
477
478
HasFunctionName()479 bool ScopeInfo::HasFunctionName() {
480 if (length() > 0) {
481 return NONE != FunctionVariableField::decode(Flags());
482 } else {
483 return false;
484 }
485 }
486
HasOuterScopeInfo()487 bool ScopeInfo::HasOuterScopeInfo() {
488 if (length() > 0) {
489 return HasOuterScopeInfoField::decode(Flags());
490 } else {
491 return false;
492 }
493 }
494
IsDebugEvaluateScope()495 bool ScopeInfo::IsDebugEvaluateScope() {
496 if (length() > 0) {
497 return IsDebugEvaluateScopeField::decode(Flags());
498 } else {
499 return false;
500 }
501 }
502
SetIsDebugEvaluateScope()503 void ScopeInfo::SetIsDebugEvaluateScope() {
504 if (length() > 0) {
505 DCHECK_EQ(scope_type(), WITH_SCOPE);
506 SetFlags(Flags() | IsDebugEvaluateScopeField::encode(true));
507 } else {
508 UNREACHABLE();
509 }
510 }
511
HasHeapAllocatedLocals()512 bool ScopeInfo::HasHeapAllocatedLocals() {
513 if (length() > 0) {
514 return ContextLocalCount() > 0;
515 } else {
516 return false;
517 }
518 }
519
520
HasContext()521 bool ScopeInfo::HasContext() {
522 return ContextLength() > 0;
523 }
524
525
FunctionName()526 String* ScopeInfo::FunctionName() {
527 DCHECK(HasFunctionName());
528 return String::cast(get(FunctionNameInfoIndex()));
529 }
530
OuterScopeInfo()531 ScopeInfo* ScopeInfo::OuterScopeInfo() {
532 DCHECK(HasOuterScopeInfo());
533 return ScopeInfo::cast(get(OuterScopeInfoIndex()));
534 }
535
ModuleDescriptorInfo()536 ModuleInfo* ScopeInfo::ModuleDescriptorInfo() {
537 DCHECK(scope_type() == MODULE_SCOPE);
538 return ModuleInfo::cast(get(ModuleInfoIndex()));
539 }
540
ParameterName(int var)541 String* ScopeInfo::ParameterName(int var) {
542 DCHECK_LE(0, var);
543 DCHECK_LT(var, ParameterCount());
544 int info_index = ParameterNamesIndex() + var;
545 return String::cast(get(info_index));
546 }
547
548
LocalName(int var)549 String* ScopeInfo::LocalName(int var) {
550 DCHECK_LE(0, var);
551 DCHECK_LT(var, LocalCount());
552 DCHECK(StackLocalNamesIndex() + StackLocalCount() ==
553 ContextLocalNamesIndex());
554 int info_index = StackLocalNamesIndex() + var;
555 return String::cast(get(info_index));
556 }
557
558
StackLocalName(int var)559 String* ScopeInfo::StackLocalName(int var) {
560 DCHECK_LE(0, var);
561 DCHECK_LT(var, StackLocalCount());
562 int info_index = StackLocalNamesIndex() + var;
563 return String::cast(get(info_index));
564 }
565
566
StackLocalIndex(int var)567 int ScopeInfo::StackLocalIndex(int var) {
568 DCHECK_LE(0, var);
569 DCHECK_LT(var, StackLocalCount());
570 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
571 return first_slot_index + var;
572 }
573
574
ContextLocalName(int var)575 String* ScopeInfo::ContextLocalName(int var) {
576 DCHECK_LE(0, var);
577 DCHECK_LT(var, ContextLocalCount());
578 int info_index = ContextLocalNamesIndex() + var;
579 return String::cast(get(info_index));
580 }
581
582
ContextLocalMode(int var)583 VariableMode ScopeInfo::ContextLocalMode(int var) {
584 DCHECK_LE(0, var);
585 DCHECK_LT(var, ContextLocalCount());
586 int info_index = ContextLocalInfosIndex() + var;
587 int value = Smi::cast(get(info_index))->value();
588 return VariableModeField::decode(value);
589 }
590
591
ContextLocalInitFlag(int var)592 InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
593 DCHECK_LE(0, var);
594 DCHECK_LT(var, ContextLocalCount());
595 int info_index = ContextLocalInfosIndex() + var;
596 int value = Smi::cast(get(info_index))->value();
597 return InitFlagField::decode(value);
598 }
599
600
ContextLocalMaybeAssignedFlag(int var)601 MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) {
602 DCHECK_LE(0, var);
603 DCHECK_LT(var, ContextLocalCount());
604 int info_index = ContextLocalInfosIndex() + var;
605 int value = Smi::cast(get(info_index))->value();
606 return MaybeAssignedFlagField::decode(value);
607 }
608
VariableIsSynthetic(String * name)609 bool ScopeInfo::VariableIsSynthetic(String* name) {
610 // There's currently no flag stored on the ScopeInfo to indicate that a
611 // variable is a compiler-introduced temporary. However, to avoid conflict
612 // with user declarations, the current temporaries like .generator_object and
613 // .result start with a dot, so we can use that as a flag. It's a hack!
614 return name->length() == 0 || name->Get(0) == '.' ||
615 name->Equals(name->GetHeap()->this_string());
616 }
617
618
StackSlotIndex(String * name)619 int ScopeInfo::StackSlotIndex(String* name) {
620 DCHECK(name->IsInternalizedString());
621 if (length() > 0) {
622 int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
623 int start = StackLocalNamesIndex();
624 int end = start + StackLocalCount();
625 for (int i = start; i < end; ++i) {
626 if (name == get(i)) {
627 return i - start + first_slot_index;
628 }
629 }
630 }
631 return -1;
632 }
633
ModuleIndex(Handle<String> name,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)634 int ScopeInfo::ModuleIndex(Handle<String> name, VariableMode* mode,
635 InitializationFlag* init_flag,
636 MaybeAssignedFlag* maybe_assigned_flag) {
637 DCHECK_EQ(scope_type(), MODULE_SCOPE);
638 DCHECK(name->IsInternalizedString());
639 DCHECK_NOT_NULL(mode);
640 DCHECK_NOT_NULL(init_flag);
641 DCHECK_NOT_NULL(maybe_assigned_flag);
642
643 int module_vars_count = Smi::cast(get(ModuleVariableCountIndex()))->value();
644 int entry = ModuleVariablesIndex();
645 for (int i = 0; i < module_vars_count; ++i) {
646 if (*name == get(entry + kModuleVariableNameOffset)) {
647 int index;
648 ModuleVariable(i, nullptr, &index, mode, init_flag, maybe_assigned_flag);
649 return index;
650 }
651 entry += kModuleVariableEntryLength;
652 }
653
654 return 0;
655 }
656
ContextSlotIndex(Handle<ScopeInfo> scope_info,Handle<String> name,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)657 int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
658 Handle<String> name, VariableMode* mode,
659 InitializationFlag* init_flag,
660 MaybeAssignedFlag* maybe_assigned_flag) {
661 DCHECK(name->IsInternalizedString());
662 DCHECK_NOT_NULL(mode);
663 DCHECK_NOT_NULL(init_flag);
664 DCHECK_NOT_NULL(maybe_assigned_flag);
665
666 if (scope_info->length() > 0) {
667 ContextSlotCache* context_slot_cache =
668 scope_info->GetIsolate()->context_slot_cache();
669 int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag,
670 maybe_assigned_flag);
671 if (result != ContextSlotCache::kNotFound) {
672 DCHECK_LT(result, scope_info->ContextLength());
673 return result;
674 }
675
676 int start = scope_info->ContextLocalNamesIndex();
677 int end = start + scope_info->ContextLocalCount();
678 for (int i = start; i < end; ++i) {
679 if (*name == scope_info->get(i)) {
680 int var = i - start;
681 *mode = scope_info->ContextLocalMode(var);
682 *init_flag = scope_info->ContextLocalInitFlag(var);
683 *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
684 result = Context::MIN_CONTEXT_SLOTS + var;
685
686 context_slot_cache->Update(scope_info, name, *mode, *init_flag,
687 *maybe_assigned_flag, result);
688 DCHECK_LT(result, scope_info->ContextLength());
689 return result;
690 }
691 }
692 // Cache as not found. Mode, init flag and maybe assigned flag don't matter.
693 context_slot_cache->Update(scope_info, name, TEMPORARY,
694 kNeedsInitialization, kNotAssigned, -1);
695 }
696
697 return -1;
698 }
699
ContextSlotName(int slot_index)700 String* ScopeInfo::ContextSlotName(int slot_index) {
701 int const var = slot_index - Context::MIN_CONTEXT_SLOTS;
702 DCHECK_LE(0, var);
703 DCHECK_LT(var, ContextLocalCount());
704 return ContextLocalName(var);
705 }
706
707
ParameterIndex(String * name)708 int ScopeInfo::ParameterIndex(String* name) {
709 DCHECK(name->IsInternalizedString());
710 if (length() > 0) {
711 // We must read parameters from the end since for
712 // multiply declared parameters the value of the
713 // last declaration of that parameter is used
714 // inside a function (and thus we need to look
715 // at the last index). Was bug# 1110337.
716 int start = ParameterNamesIndex();
717 int end = start + ParameterCount();
718 for (int i = end - 1; i >= start; --i) {
719 if (name == get(i)) {
720 return i - start;
721 }
722 }
723 }
724 return -1;
725 }
726
727
ReceiverContextSlotIndex()728 int ScopeInfo::ReceiverContextSlotIndex() {
729 if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT)
730 return Smi::cast(get(ReceiverInfoIndex()))->value();
731 return -1;
732 }
733
FunctionContextSlotIndex(String * name)734 int ScopeInfo::FunctionContextSlotIndex(String* name) {
735 DCHECK(name->IsInternalizedString());
736 if (length() > 0) {
737 if (FunctionVariableField::decode(Flags()) == CONTEXT &&
738 FunctionName() == name) {
739 return Smi::cast(get(FunctionNameInfoIndex() + 1))->value();
740 }
741 }
742 return -1;
743 }
744
745
function_kind()746 FunctionKind ScopeInfo::function_kind() {
747 return FunctionKindField::decode(Flags());
748 }
749
ParameterNamesIndex()750 int ScopeInfo::ParameterNamesIndex() {
751 DCHECK_LT(0, length());
752 return kVariablePartIndex;
753 }
754
755
StackLocalFirstSlotIndex()756 int ScopeInfo::StackLocalFirstSlotIndex() {
757 return ParameterNamesIndex() + ParameterCount();
758 }
759
StackLocalNamesIndex()760 int ScopeInfo::StackLocalNamesIndex() { return StackLocalFirstSlotIndex() + 1; }
761
ContextLocalNamesIndex()762 int ScopeInfo::ContextLocalNamesIndex() {
763 return StackLocalNamesIndex() + StackLocalCount();
764 }
765
ContextLocalInfosIndex()766 int ScopeInfo::ContextLocalInfosIndex() {
767 return ContextLocalNamesIndex() + ContextLocalCount();
768 }
769
ReceiverInfoIndex()770 int ScopeInfo::ReceiverInfoIndex() {
771 return ContextLocalInfosIndex() + ContextLocalCount();
772 }
773
FunctionNameInfoIndex()774 int ScopeInfo::FunctionNameInfoIndex() {
775 return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0);
776 }
777
OuterScopeInfoIndex()778 int ScopeInfo::OuterScopeInfoIndex() {
779 return FunctionNameInfoIndex() + (HasFunctionName() ? 2 : 0);
780 }
781
ModuleInfoIndex()782 int ScopeInfo::ModuleInfoIndex() {
783 return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0);
784 }
785
ModuleVariableCountIndex()786 int ScopeInfo::ModuleVariableCountIndex() { return ModuleInfoIndex() + 1; }
787
ModuleVariablesIndex()788 int ScopeInfo::ModuleVariablesIndex() { return ModuleVariableCountIndex() + 1; }
789
ModuleVariable(int i,String ** name,int * index,VariableMode * mode,InitializationFlag * init_flag,MaybeAssignedFlag * maybe_assigned_flag)790 void ScopeInfo::ModuleVariable(int i, String** name, int* index,
791 VariableMode* mode,
792 InitializationFlag* init_flag,
793 MaybeAssignedFlag* maybe_assigned_flag) {
794 DCHECK_LE(0, i);
795 DCHECK_LT(i, Smi::cast(get(ModuleVariableCountIndex()))->value());
796
797 int entry = ModuleVariablesIndex() + i * kModuleVariableEntryLength;
798 int properties =
799 Smi::cast(get(entry + kModuleVariablePropertiesOffset))->value();
800
801 if (name != nullptr) {
802 *name = String::cast(get(entry + kModuleVariableNameOffset));
803 }
804 if (index != nullptr) {
805 *index = Smi::cast(get(entry + kModuleVariableIndexOffset))->value();
806 DCHECK_NE(*index, 0);
807 }
808 if (mode != nullptr) {
809 *mode = VariableModeField::decode(properties);
810 }
811 if (init_flag != nullptr) {
812 *init_flag = InitFlagField::decode(properties);
813 }
814 if (maybe_assigned_flag != nullptr) {
815 *maybe_assigned_flag = MaybeAssignedFlagField::decode(properties);
816 }
817 }
818
819 #ifdef DEBUG
820
PrintList(const char * list_name,int nof_internal_slots,int start,int end,ScopeInfo * scope_info)821 static void PrintList(const char* list_name,
822 int nof_internal_slots,
823 int start,
824 int end,
825 ScopeInfo* scope_info) {
826 if (start < end) {
827 PrintF("\n // %s\n", list_name);
828 if (nof_internal_slots > 0) {
829 PrintF(" %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
830 }
831 for (int i = nof_internal_slots; start < end; ++i, ++start) {
832 PrintF(" %2d ", i);
833 String::cast(scope_info->get(start))->ShortPrint();
834 PrintF("\n");
835 }
836 }
837 }
838
839
Print()840 void ScopeInfo::Print() {
841 PrintF("ScopeInfo ");
842 if (HasFunctionName()) {
843 FunctionName()->ShortPrint();
844 } else {
845 PrintF("/* no function name */");
846 }
847 PrintF("{");
848
849 if (length() > 0) {
850 PrintList("parameters", 0, ParameterNamesIndex(),
851 ParameterNamesIndex() + ParameterCount(), this);
852 PrintList("stack slots", 0, StackLocalNamesIndex(),
853 StackLocalNamesIndex() + StackLocalCount(), this);
854 PrintList("context slots", Context::MIN_CONTEXT_SLOTS,
855 ContextLocalNamesIndex(),
856 ContextLocalNamesIndex() + ContextLocalCount(), this);
857 // TODO(neis): Print module stuff if present.
858 }
859
860 PrintF("}\n");
861 }
862 #endif // DEBUG
863
New(Isolate * isolate,Handle<Object> export_name,Handle<Object> local_name,Handle<Object> import_name,int module_request,int cell_index,int beg_pos,int end_pos)864 Handle<ModuleInfoEntry> ModuleInfoEntry::New(Isolate* isolate,
865 Handle<Object> export_name,
866 Handle<Object> local_name,
867 Handle<Object> import_name,
868 int module_request, int cell_index,
869 int beg_pos, int end_pos) {
870 Handle<ModuleInfoEntry> result = Handle<ModuleInfoEntry>::cast(
871 isolate->factory()->NewStruct(MODULE_INFO_ENTRY_TYPE));
872 result->set_export_name(*export_name);
873 result->set_local_name(*local_name);
874 result->set_import_name(*import_name);
875 result->set_module_request(module_request);
876 result->set_cell_index(cell_index);
877 result->set_beg_pos(beg_pos);
878 result->set_end_pos(end_pos);
879 return result;
880 }
881
New(Isolate * isolate,Zone * zone,ModuleDescriptor * descr)882 Handle<ModuleInfo> ModuleInfo::New(Isolate* isolate, Zone* zone,
883 ModuleDescriptor* descr) {
884 // Serialize module requests.
885 Handle<FixedArray> module_requests = isolate->factory()->NewFixedArray(
886 static_cast<int>(descr->module_requests().size()));
887 for (const auto& elem : descr->module_requests()) {
888 module_requests->set(elem.second, *elem.first->string());
889 }
890
891 // Serialize special exports.
892 Handle<FixedArray> special_exports =
893 isolate->factory()->NewFixedArray(descr->special_exports().length());
894 {
895 int i = 0;
896 for (auto entry : descr->special_exports()) {
897 Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
898 special_exports->set(i++, *serialized_entry);
899 }
900 }
901
902 // Serialize namespace imports.
903 Handle<FixedArray> namespace_imports =
904 isolate->factory()->NewFixedArray(descr->namespace_imports().length());
905 {
906 int i = 0;
907 for (auto entry : descr->namespace_imports()) {
908 Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
909 namespace_imports->set(i++, *serialized_entry);
910 }
911 }
912
913 // Serialize regular exports.
914 Handle<FixedArray> regular_exports =
915 descr->SerializeRegularExports(isolate, zone);
916
917 // Serialize regular imports.
918 Handle<FixedArray> regular_imports = isolate->factory()->NewFixedArray(
919 static_cast<int>(descr->regular_imports().size()));
920 {
921 int i = 0;
922 for (const auto& elem : descr->regular_imports()) {
923 Handle<ModuleInfoEntry> serialized_entry =
924 elem.second->Serialize(isolate);
925 regular_imports->set(i++, *serialized_entry);
926 }
927 }
928
929 Handle<ModuleInfo> result = isolate->factory()->NewModuleInfo();
930 result->set(kModuleRequestsIndex, *module_requests);
931 result->set(kSpecialExportsIndex, *special_exports);
932 result->set(kRegularExportsIndex, *regular_exports);
933 result->set(kNamespaceImportsIndex, *namespace_imports);
934 result->set(kRegularImportsIndex, *regular_imports);
935 return result;
936 }
937
RegularExportCount() const938 int ModuleInfo::RegularExportCount() const {
939 DCHECK_EQ(regular_exports()->length() % kRegularExportLength, 0);
940 return regular_exports()->length() / kRegularExportLength;
941 }
942
RegularExportLocalName(int i) const943 String* ModuleInfo::RegularExportLocalName(int i) const {
944 return String::cast(regular_exports()->get(i * kRegularExportLength +
945 kRegularExportLocalNameOffset));
946 }
947
RegularExportCellIndex(int i) const948 int ModuleInfo::RegularExportCellIndex(int i) const {
949 return Smi::cast(regular_exports()->get(i * kRegularExportLength +
950 kRegularExportCellIndexOffset))
951 ->value();
952 }
953
RegularExportExportNames(int i) const954 FixedArray* ModuleInfo::RegularExportExportNames(int i) const {
955 return FixedArray::cast(regular_exports()->get(
956 i * kRegularExportLength + kRegularExportExportNamesOffset));
957 }
958
LookupRegularImport(Handle<ModuleInfo> info,Handle<String> local_name)959 Handle<ModuleInfoEntry> ModuleInfo::LookupRegularImport(
960 Handle<ModuleInfo> info, Handle<String> local_name) {
961 Isolate* isolate = info->GetIsolate();
962 Handle<FixedArray> regular_imports(info->regular_imports(), isolate);
963 for (int i = 0, n = regular_imports->length(); i < n; ++i) {
964 Handle<ModuleInfoEntry> entry(
965 ModuleInfoEntry::cast(regular_imports->get(i)), isolate);
966 if (String::cast(entry->local_name())->Equals(*local_name)) {
967 return entry;
968 }
969 }
970 UNREACHABLE();
971 return Handle<ModuleInfoEntry>();
972 }
973
974 } // namespace internal
975 } // namespace v8
976