Line data Source code
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
27 : 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 :
61 24196748 : 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 57660025 : for (Variable* var : *scope->locals()) {
73 23700511 : switch (var->location()) {
74 : case VariableLocation::LOCAL:
75 8862161 : if (stack_local_count == 0) first_slot_index = var->index();
76 8862161 : stack_local_count++;
77 8862161 : break;
78 : case VariableLocation::CONTEXT:
79 3476878 : context_local_count++;
80 3476878 : break;
81 : case VariableLocation::MODULE:
82 1780 : module_vars_count++;
83 1780 : 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 7735232 : if (scope->is_declaration_scope() &&
96 3702444 : scope->AsDeclarationScope()->has_this_declaration()) {
97 2065822 : Variable* var = scope->AsDeclarationScope()->receiver();
98 2065828 : if (!var->is_used()) {
99 : receiver_info = UNUSED;
100 586230 : } 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 7735241 : scope->is_declaration_scope() &&
112 3702437 : 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 6147140 : if (scope->is_function_scope() &&
117 2114336 : scope->AsDeclarationScope()->function_var() != nullptr) {
118 177410 : Variable* var = scope->AsDeclarationScope()->function_var();
119 177415 : if (!var->is_used()) {
120 : function_name_info = UNUSED;
121 177419 : } 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 4032809 : const bool has_function_name = function_name_info != NONE;
132 4032809 : const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
133 4032809 : const int parameter_count = scope->num_parameters();
134 4032790 : const bool has_outer_scope_info = !outer_scope.is_null();
135 8065580 : const int length = kVariablePartIndex + parameter_count +
136 8065580 : (1 + stack_local_count) + 2 * context_local_count +
137 4032790 : (has_receiver ? 1 : 0) + (has_function_name ? 2 : 0) +
138 4039246 : (has_outer_scope_info ? 1 : 0) +
139 : (scope->is_module_scope()
140 6456 : ? 2 + kModuleVariableEntryLength * module_vars_count
141 4032790 : : 0);
142 :
143 : Factory* factory = isolate->factory();
144 4032790 : 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 4032790 : if (scope->is_function_scope()) {
150 2114335 : 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 4032790 : if (scope->is_declaration_scope()) {
157 3702441 : function_kind = scope->AsDeclarationScope()->function_kind();
158 : }
159 :
160 : // Encode the flags.
161 : int flags =
162 4032791 : ScopeTypeField::encode(scope->scope_type()) |
163 4032791 : CallsEvalField::encode(scope->calls_eval()) |
164 4032791 : LanguageModeField::encode(scope->language_mode()) |
165 4032791 : DeclarationScopeField::encode(scope->is_declaration_scope()) |
166 4032791 : ReceiverVariableField::encode(receiver_info) |
167 4032791 : HasNewTargetField::encode(has_new_target) |
168 4032791 : FunctionVariableField::encode(function_name_info) |
169 4032791 : AsmModuleField::encode(asm_module) |
170 4032791 : AsmFunctionField::encode(asm_function) |
171 4032791 : HasSimpleParametersField::encode(has_simple_parameters) |
172 4032791 : FunctionKindField::encode(function_kind) |
173 4032791 : HasOuterScopeInfoField::encode(has_outer_scope_info) |
174 4032791 : 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 4032791 : if (scope->is_declaration_scope()) {
185 3894844 : for (int i = 0; i < parameter_count; ++i) {
186 : scope_info->set(index++,
187 15579376 : *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 4032791 : scope_info->set(index++, Smi::FromInt(first_slot_index));
197 : DCHECK_EQ(index, scope_info->StackLocalNamesIndex());
198 :
199 : int stack_local_base = index;
200 4032791 : int context_local_base = stack_local_base + stack_local_count;
201 4032791 : int context_local_info_base = context_local_base + context_local_count;
202 : int module_var_entry = scope_info->ModuleVariablesIndex();
203 :
204 80150072 : for (Variable* var : *scope->locals()) {
205 23700545 : switch (var->location()) {
206 : case VariableLocation::LOCAL: {
207 8862156 : int local_index = var->index() - first_slot_index;
208 : DCHECK_LE(0, local_index);
209 : DCHECK_LT(local_index, stack_local_count);
210 17724312 : scope_info->set(stack_local_base + local_index, *var->name());
211 8862168 : break;
212 : }
213 : case VariableLocation::CONTEXT: {
214 : // Due to duplicate parameters, context locals aren't guaranteed to come
215 : // in order.
216 3476878 : int local_index = var->index() - Context::MIN_CONTEXT_SLOTS;
217 : DCHECK_LE(0, local_index);
218 : DCHECK_LT(local_index, context_local_count);
219 3476878 : uint32_t info = VariableModeField::encode(var->mode()) |
220 : InitFlagField::encode(var->initialization_flag()) |
221 3476878 : MaybeAssignedFlagField::encode(var->maybe_assigned());
222 6953756 : scope_info->set(context_local_base + local_index, *var->name());
223 : scope_info->set(context_local_info_base + local_index,
224 6953756 : Smi::FromInt(info));
225 : break;
226 : }
227 : case VariableLocation::MODULE: {
228 : scope_info->set(module_var_entry + kModuleVariableNameOffset,
229 1780 : *var->name());
230 : scope_info->set(module_var_entry + kModuleVariableIndexOffset,
231 : Smi::FromInt(var->index()));
232 : uint32_t properties =
233 1780 : VariableModeField::encode(var->mode()) |
234 : InitFlagField::encode(var->initialization_flag()) |
235 1780 : MaybeAssignedFlagField::encode(var->maybe_assigned());
236 : scope_info->set(module_var_entry + kModuleVariablePropertiesOffset,
237 1780 : Smi::FromInt(properties));
238 : module_var_entry += kModuleVariableEntryLength;
239 1780 : break;
240 : }
241 : default:
242 : break;
243 : }
244 : }
245 :
246 4032793 : 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 4032793 : if (has_receiver) {
251 586230 : int var_index = scope->AsDeclarationScope()->receiver()->index();
252 586230 : 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 4032793 : if (has_function_name) {
260 177421 : int var_index = scope->AsDeclarationScope()->function_var()->index();
261 : scope_info->set(index++,
262 532263 : *scope->AsDeclarationScope()->function_var()->name());
263 177415 : 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 4032787 : if (has_outer_scope_info) {
271 3916942 : scope_info->set(index++, *outer_scope.ToHandleChecked());
272 : }
273 :
274 : // Module-specific information (only for module scopes).
275 4032785 : if (scope->is_module_scope()) {
276 : Handle<ModuleInfo> module_info =
277 6456 : ModuleInfo::New(isolate, zone, scope->AsModuleScope()->module());
278 : DCHECK_EQ(index, scope_info->ModuleInfoIndex());
279 12912 : 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 4032785 : return scope_info;
291 : }
292 :
293 16449 : Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
294 : Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope) {
295 16449 : const bool has_outer_scope_info = !outer_scope.is_null();
296 16449 : const int length = kVariablePartIndex + 1 + (has_outer_scope_info ? 1 : 0);
297 :
298 : Factory* factory = isolate->factory();
299 16449 : 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 16449 : FunctionKindField::encode(kNormalFunction) |
309 : HasOuterScopeInfoField::encode(has_outer_scope_info) |
310 16449 : 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 16449 : if (has_outer_scope_info) {
326 3139 : 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 16449 : return scope_info;
332 : }
333 :
334 79 : 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 79 : 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 158 : 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 79 : return scope_info;
397 : }
398 :
399 19397486 : ScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
400 19397486 : return isolate->heap()->empty_scope_info();
401 : }
402 :
403 13686301 : ScopeType ScopeInfo::scope_type() {
404 : DCHECK_LT(0, length());
405 29094916 : return ScopeTypeField::decode(Flags());
406 : }
407 :
408 3814506 : bool ScopeInfo::CallsEval() {
409 7629012 : return length() > 0 && CallsEvalField::decode(Flags());
410 : }
411 :
412 3503172 : LanguageMode ScopeInfo::language_mode() {
413 7006344 : return length() > 0 ? LanguageModeField::decode(Flags()) : SLOPPY;
414 : }
415 :
416 128636 : bool ScopeInfo::is_declaration_scope() {
417 263862 : return DeclarationScopeField::decode(Flags());
418 : }
419 :
420 360941 : int ScopeInfo::LocalCount() { return StackLocalCount() + ContextLocalCount(); }
421 :
422 0 : int ScopeInfo::StackSlotCount() {
423 0 : if (length() > 0) {
424 : bool function_name_stack_slot =
425 0 : FunctionVariableField::decode(Flags()) == STACK;
426 0 : return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
427 : }
428 : return 0;
429 : }
430 :
431 4020988 : int ScopeInfo::ContextLength() {
432 4020988 : if (length() > 0) {
433 4020988 : int context_locals = ContextLocalCount();
434 : bool function_name_context_slot =
435 8041976 : FunctionVariableField::decode(Flags()) == CONTEXT;
436 4409841 : bool has_context = context_locals > 0 || function_name_context_slot ||
437 340935 : scope_type() == WITH_SCOPE ||
438 25472 : (scope_type() == BLOCK_SCOPE && CallsSloppyEval() &&
439 334345 : is_declaration_scope()) ||
440 633387 : (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
441 4646070 : (scope_type() == FUNCTION_SCOPE && IsAsmModule()) ||
442 : scope_type() == MODULE_SCOPE;
443 :
444 4020988 : if (has_context) {
445 3694948 : return Context::MIN_CONTEXT_SLOTS + context_locals +
446 3694948 : (function_name_context_slot ? 1 : 0);
447 : }
448 : }
449 : return 0;
450 : }
451 :
452 14902 : bool ScopeInfo::HasReceiver() {
453 14902 : if (length() > 0) {
454 29804 : return NONE != ReceiverVariableField::decode(Flags());
455 : } else {
456 : return false;
457 : }
458 : }
459 :
460 4981773 : bool ScopeInfo::HasAllocatedReceiver() {
461 4981773 : if (length() > 0) {
462 4981774 : VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags());
463 4981775 : return allocation == STACK || allocation == CONTEXT;
464 : } else {
465 : return false;
466 : }
467 : }
468 :
469 996 : bool ScopeInfo::HasNewTarget() { return HasNewTargetField::decode(Flags()); }
470 :
471 4852292 : bool ScopeInfo::HasFunctionName() {
472 4852292 : if (length() > 0) {
473 9703074 : return NONE != FunctionVariableField::decode(Flags());
474 : } else {
475 : return false;
476 : }
477 : }
478 :
479 7560185 : bool ScopeInfo::HasOuterScopeInfo() {
480 7560185 : if (length() > 0) {
481 15120371 : return HasOuterScopeInfoField::decode(Flags());
482 : } else {
483 : return false;
484 : }
485 : }
486 :
487 38418 : bool ScopeInfo::IsDebugEvaluateScope() {
488 38418 : if (length() > 0) {
489 76836 : return IsDebugEvaluateScopeField::decode(Flags());
490 : } else {
491 : return false;
492 : }
493 : }
494 :
495 16414 : void ScopeInfo::SetIsDebugEvaluateScope() {
496 16414 : if (length() > 0) {
497 : DCHECK_EQ(scope_type(), WITH_SCOPE);
498 16414 : SetFlags(Flags() | IsDebugEvaluateScopeField::encode(true));
499 : } else {
500 0 : UNREACHABLE();
501 : }
502 16414 : }
503 :
504 0 : bool ScopeInfo::HasHeapAllocatedLocals() {
505 0 : if (length() > 0) {
506 0 : return ContextLocalCount() > 0;
507 : } else {
508 : return false;
509 : }
510 : }
511 :
512 422384 : bool ScopeInfo::HasContext() { return ContextLength() > 0; }
513 :
514 138881 : String* ScopeInfo::FunctionName() {
515 : DCHECK(HasFunctionName());
516 277762 : return String::cast(get(FunctionNameInfoIndex()));
517 : }
518 :
519 780119 : ScopeInfo* ScopeInfo::OuterScopeInfo() {
520 : DCHECK(HasOuterScopeInfo());
521 1560238 : return ScopeInfo::cast(get(OuterScopeInfoIndex()));
522 : }
523 :
524 15986 : ModuleInfo* ScopeInfo::ModuleDescriptorInfo() {
525 : DCHECK(scope_type() == MODULE_SCOPE);
526 31972 : return ModuleInfo::cast(get(ModuleInfoIndex()));
527 : }
528 :
529 96745 : String* ScopeInfo::ParameterName(int var) {
530 : DCHECK_LE(0, var);
531 : DCHECK_LT(var, ParameterCount());
532 96745 : int info_index = ParameterNamesIndex() + var;
533 96745 : return String::cast(get(info_index));
534 : }
535 :
536 15325979 : String* ScopeInfo::LocalName(int var) {
537 : DCHECK_LE(0, var);
538 : DCHECK_LT(var, LocalCount());
539 : DCHECK(StackLocalNamesIndex() + StackLocalCount() ==
540 : ContextLocalNamesIndex());
541 15325979 : int info_index = StackLocalNamesIndex() + var;
542 15325979 : return String::cast(get(info_index));
543 : }
544 :
545 4758208 : String* ScopeInfo::StackLocalName(int var) {
546 : DCHECK_LE(0, var);
547 : DCHECK_LT(var, StackLocalCount());
548 4758208 : int info_index = StackLocalNamesIndex() + var;
549 4758208 : return String::cast(get(info_index));
550 : }
551 :
552 9562757 : 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 9562757 : return first_slot_index + var;
557 : }
558 :
559 1547477 : String* ScopeInfo::ContextLocalName(int var) {
560 : DCHECK_LE(0, var);
561 : DCHECK_LT(var, ContextLocalCount());
562 1547477 : int info_index = ContextLocalNamesIndex() + var;
563 1547477 : return String::cast(get(info_index));
564 : }
565 :
566 1230396 : VariableMode ScopeInfo::ContextLocalMode(int var) {
567 : DCHECK_LE(0, var);
568 : DCHECK_LT(var, ContextLocalCount());
569 1230396 : int info_index = ContextLocalInfosIndex() + var;
570 : int value = Smi::cast(get(info_index))->value();
571 1230396 : return VariableModeField::decode(value);
572 : }
573 :
574 903812 : InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
575 : DCHECK_LE(0, var);
576 : DCHECK_LT(var, ContextLocalCount());
577 903812 : int info_index = ContextLocalInfosIndex() + var;
578 : int value = Smi::cast(get(info_index))->value();
579 1807624 : return InitFlagField::decode(value);
580 : }
581 :
582 908506 : MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) {
583 : DCHECK_LE(0, var);
584 : DCHECK_LT(var, ContextLocalCount());
585 908506 : int info_index = ContextLocalInfosIndex() + var;
586 : int value = Smi::cast(get(info_index))->value();
587 1817012 : return MaybeAssignedFlagField::decode(value);
588 : }
589 :
590 19959517 : 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 59049996 : return name->length() == 0 || name->Get(0) == '.' ||
596 39339367 : name->Equals(name->GetHeap()->this_string());
597 : }
598 :
599 0 : int ScopeInfo::StackSlotIndex(String* name) {
600 : DCHECK(name->IsInternalizedString());
601 0 : if (length() > 0) {
602 : int first_slot_index = Smi::cast(get(StackLocalFirstSlotIndex()))->value();
603 : int start = StackLocalNamesIndex();
604 0 : int end = start + StackLocalCount();
605 0 : for (int i = start; i < end; ++i) {
606 0 : if (name == get(i)) {
607 0 : return i - start + first_slot_index;
608 : }
609 : }
610 : }
611 : return -1;
612 : }
613 :
614 5331 : 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 8231 : for (int i = 0; i < module_vars_count; ++i) {
626 3396 : if (*name == get(entry + kModuleVariableNameOffset)) {
627 : int index;
628 496 : ModuleVariable(i, nullptr, &index, mode, init_flag, maybe_assigned_flag);
629 496 : return index;
630 : }
631 2900 : entry += kModuleVariableEntryLength;
632 : }
633 :
634 : return 0;
635 : }
636 :
637 18659692 : 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 18659692 : if (scope_info->length() > 0) {
647 : ContextSlotCache* context_slot_cache =
648 18659693 : scope_info->GetIsolate()->context_slot_cache();
649 : int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag,
650 18659693 : maybe_assigned_flag);
651 18659692 : if (result != ContextSlotCache::kNotFound) {
652 : DCHECK_LT(result, scope_info->ContextLength());
653 : return result;
654 : }
655 :
656 4262819 : int start = scope_info->ContextLocalNamesIndex();
657 4262819 : int end = start + scope_info->ContextLocalCount();
658 40482074 : for (int i = start; i < end; ++i) {
659 37123067 : if (*name == scope_info->get(i)) {
660 903812 : int var = i - start;
661 903812 : *mode = scope_info->ContextLocalMode(var);
662 903812 : *init_flag = scope_info->ContextLocalInitFlag(var);
663 903812 : *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
664 903812 : result = Context::MIN_CONTEXT_SLOTS + var;
665 :
666 : context_slot_cache->Update(scope_info, name, *mode, *init_flag,
667 1807624 : *maybe_assigned_flag, result);
668 : DCHECK_LT(result, scope_info->ContextLength());
669 903812 : 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 3359007 : kNeedsInitialization, kNotAssigned, -1);
675 : }
676 :
677 : return -1;
678 : }
679 :
680 0 : String* ScopeInfo::ContextSlotName(int slot_index) {
681 0 : int const var = slot_index - Context::MIN_CONTEXT_SLOTS;
682 : DCHECK_LE(0, var);
683 : DCHECK_LT(var, ContextLocalCount());
684 0 : return ContextLocalName(var);
685 : }
686 :
687 0 : int ScopeInfo::ParameterIndex(String* name) {
688 : DCHECK(name->IsInternalizedString());
689 0 : 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 0 : int end = start + ParameterCount();
697 0 : for (int i = end - 1; i >= start; --i) {
698 0 : if (name == get(i)) {
699 0 : return i - start;
700 : }
701 : }
702 : }
703 : return -1;
704 : }
705 :
706 1306273 : int ScopeInfo::ReceiverContextSlotIndex() {
707 2612546 : if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT)
708 813916 : return Smi::cast(get(ReceiverInfoIndex()))->value();
709 : return -1;
710 : }
711 :
712 3280915 : int ScopeInfo::FunctionContextSlotIndex(String* name) {
713 : DCHECK(name->IsInternalizedString());
714 3280915 : if (length() > 0) {
715 6699197 : if (FunctionVariableField::decode(Flags()) == CONTEXT &&
716 137367 : FunctionName() == name) {
717 3322 : return Smi::cast(get(FunctionNameInfoIndex() + 1))->value();
718 : }
719 : }
720 : return -1;
721 : }
722 :
723 3342984 : FunctionKind ScopeInfo::function_kind() {
724 6685968 : return FunctionKindField::decode(Flags());
725 : }
726 :
727 0 : int ScopeInfo::ParameterNamesIndex() {
728 : DCHECK_LT(0, length());
729 0 : return kVariablePartIndex;
730 : }
731 :
732 0 : int ScopeInfo::StackLocalFirstSlotIndex() {
733 43888672 : return ParameterNamesIndex() + ParameterCount();
734 : }
735 :
736 34325917 : int ScopeInfo::StackLocalNamesIndex() { return StackLocalFirstSlotIndex() + 1; }
737 :
738 14241728 : int ScopeInfo::ContextLocalNamesIndex() {
739 14241730 : return StackLocalNamesIndex() + StackLocalCount();
740 : }
741 :
742 8431433 : int ScopeInfo::ContextLocalInfosIndex() {
743 8431433 : return ContextLocalNamesIndex() + ContextLocalCount();
744 : }
745 :
746 5388717 : int ScopeInfo::ReceiverInfoIndex() {
747 5388717 : return ContextLocalInfosIndex() + ContextLocalCount();
748 : }
749 :
750 4981759 : int ScopeInfo::FunctionNameInfoIndex() {
751 4981759 : return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0);
752 : }
753 :
754 4841215 : int ScopeInfo::OuterScopeInfoIndex() {
755 4841215 : return FunctionNameInfoIndex() + (HasFunctionName() ? 2 : 0);
756 : }
757 :
758 4061096 : int ScopeInfo::ModuleInfoIndex() {
759 4061096 : return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0);
760 : }
761 :
762 4045127 : int ScopeInfo::ModuleVariableCountIndex() { return ModuleInfoIndex() + 1; }
763 :
764 4038800 : int ScopeInfo::ModuleVariablesIndex() { return ModuleVariableCountIndex() + 1; }
765 :
766 688 : 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 688 : int entry = ModuleVariablesIndex() + i * kModuleVariableEntryLength;
774 : int properties =
775 688 : Smi::cast(get(entry + kModuleVariablePropertiesOffset))->value();
776 :
777 688 : if (name != nullptr) {
778 192 : *name = String::cast(get(entry + kModuleVariableNameOffset));
779 : }
780 688 : if (index != nullptr) {
781 1376 : *index = Smi::cast(get(entry + kModuleVariableIndexOffset))->value();
782 : DCHECK_NE(*index, 0);
783 : }
784 688 : if (mode != nullptr) {
785 496 : *mode = VariableModeField::decode(properties);
786 : }
787 688 : if (init_flag != nullptr) {
788 992 : *init_flag = InitFlagField::decode(properties);
789 : }
790 688 : if (maybe_assigned_flag != nullptr) {
791 992 : *maybe_assigned_flag = MaybeAssignedFlagField::decode(properties);
792 : }
793 688 : }
794 :
795 : #ifdef DEBUG
796 :
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 :
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 :
836 906 : 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 906 : isolate->factory()->NewStruct(MODULE_INFO_ENTRY_TYPE));
844 906 : result->set_export_name(*export_name);
845 906 : result->set_local_name(*local_name);
846 906 : 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 906 : return result;
852 : }
853 :
854 6456 : Handle<ModuleInfo> ModuleInfo::New(Isolate* isolate, Zone* zone,
855 : ModuleDescriptor* descr) {
856 : // Serialize module requests.
857 : Handle<FixedArray> module_requests = isolate->factory()->NewFixedArray(
858 6456 : static_cast<int>(descr->module_requests().size()));
859 13630 : for (const auto& elem : descr->module_requests()) {
860 2154 : module_requests->set(elem.second, *elem.first->string());
861 : }
862 :
863 : // Serialize special exports.
864 : Handle<FixedArray> special_exports =
865 6456 : isolate->factory()->NewFixedArray(descr->special_exports().length());
866 : {
867 : int i = 0;
868 13131 : for (auto entry : descr->special_exports()) {
869 219 : Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
870 438 : special_exports->set(i++, *serialized_entry);
871 : }
872 : }
873 :
874 : // Serialize namespace imports.
875 : Handle<FixedArray> namespace_imports =
876 6456 : isolate->factory()->NewFixedArray(descr->namespace_imports().length());
877 : {
878 : int i = 0;
879 13004 : for (auto entry : descr->namespace_imports()) {
880 92 : Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
881 184 : namespace_imports->set(i++, *serialized_entry);
882 : }
883 : }
884 :
885 : // Serialize regular exports.
886 : Handle<FixedArray> regular_exports =
887 6456 : descr->SerializeRegularExports(isolate, zone);
888 :
889 : // Serialize regular imports.
890 : Handle<FixedArray> regular_imports = isolate->factory()->NewFixedArray(
891 6456 : static_cast<int>(descr->regular_imports().size()));
892 : {
893 : int i = 0;
894 13507 : for (const auto& elem : descr->regular_imports()) {
895 : Handle<ModuleInfoEntry> serialized_entry =
896 595 : elem.second->Serialize(isolate);
897 1190 : regular_imports->set(i++, *serialized_entry);
898 : }
899 : }
900 :
901 6456 : Handle<ModuleInfo> result = isolate->factory()->NewModuleInfo();
902 6456 : result->set(kModuleRequestsIndex, *module_requests);
903 6456 : result->set(kSpecialExportsIndex, *special_exports);
904 6456 : result->set(kRegularExportsIndex, *regular_exports);
905 6456 : result->set(kNamespaceImportsIndex, *namespace_imports);
906 6456 : result->set(kRegularImportsIndex, *regular_imports);
907 6456 : return result;
908 : }
909 :
910 11311 : int ModuleInfo::RegularExportCount() const {
911 : DCHECK_EQ(regular_exports()->length() % kRegularExportLength, 0);
912 11311 : return regular_exports()->length() / kRegularExportLength;
913 : }
914 :
915 3460 : String* ModuleInfo::RegularExportLocalName(int i) const {
916 : return String::cast(regular_exports()->get(i * kRegularExportLength +
917 6920 : kRegularExportLocalNameOffset));
918 : }
919 :
920 5436 : int ModuleInfo::RegularExportCellIndex(int i) const {
921 5436 : return Smi::cast(regular_exports()->get(i * kRegularExportLength +
922 : kRegularExportCellIndexOffset))
923 10872 : ->value();
924 : }
925 :
926 5436 : FixedArray* ModuleInfo::RegularExportExportNames(int i) const {
927 : return FixedArray::cast(regular_exports()->get(
928 10872 : i * kRegularExportLength + kRegularExportExportNamesOffset));
929 : }
930 :
931 0 : 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 0 : for (int i = 0, n = regular_imports->length(); i < n; ++i) {
936 : Handle<ModuleInfoEntry> entry(
937 : ModuleInfoEntry::cast(regular_imports->get(i)), isolate);
938 0 : if (String::cast(entry->local_name())->Equals(*local_name)) {
939 0 : return entry;
940 : }
941 : }
942 0 : UNREACHABLE();
943 : return Handle<ModuleInfoEntry>();
944 : }
945 :
946 : } // namespace internal
947 : } // namespace v8
|