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