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/scopes.h"
10 : #include "src/ast/variables.h"
11 : #include "src/bootstrapper.h"
12 :
13 : #include "src/objects-inl.h"
14 : #include "src/objects/module-inl.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 :
19 : // An entry in ModuleVariableEntries consists of several slots:
20 : enum ModuleVariableEntryOffset {
21 : kModuleVariableNameOffset,
22 : kModuleVariableIndexOffset,
23 : kModuleVariablePropertiesOffset,
24 : kModuleVariableEntryLength // Sentinel value.
25 : };
26 :
27 : #ifdef DEBUG
28 : bool ScopeInfo::Equals(ScopeInfo other) const {
29 : if (length() != other->length()) return false;
30 : for (int index = 0; index < length(); ++index) {
31 : Object entry = get(index);
32 : Object other_entry = other->get(index);
33 : if (entry->IsSmi()) {
34 : if (entry != other_entry) return false;
35 : } else {
36 : if (HeapObject::cast(entry)->map()->instance_type() !=
37 : HeapObject::cast(other_entry)->map()->instance_type()) {
38 : return false;
39 : }
40 : if (entry->IsString()) {
41 : if (!String::cast(entry)->Equals(String::cast(other_entry))) {
42 : return false;
43 : }
44 : } else if (entry->IsScopeInfo()) {
45 : if (!ScopeInfo::cast(entry)->Equals(ScopeInfo::cast(other_entry))) {
46 : return false;
47 : }
48 : } else if (entry->IsModuleInfo()) {
49 : if (!ModuleInfo::cast(entry)->Equals(ModuleInfo::cast(other_entry))) {
50 : return false;
51 : }
52 : } else {
53 : UNREACHABLE();
54 : }
55 : }
56 : }
57 : return true;
58 : }
59 : #endif
60 :
61 : // static
62 2228621 : Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
63 : MaybeHandle<ScopeInfo> outer_scope) {
64 : // Collect variables.
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 11596213 : for (Variable* var : *scope->locals()) {
72 9367592 : switch (var->location()) {
73 : case VariableLocation::CONTEXT:
74 1849920 : context_local_count++;
75 1849920 : break;
76 : case VariableLocation::MODULE:
77 18155 : module_vars_count++;
78 18155 : break;
79 : default:
80 : break;
81 : }
82 : }
83 : // Determine use and location of the "this" binding if it is present.
84 : VariableAllocationInfo receiver_info;
85 4328767 : if (scope->is_declaration_scope() &&
86 2100133 : scope->AsDeclarationScope()->has_this_declaration()) {
87 910753 : Variable* var = scope->AsDeclarationScope()->receiver();
88 910757 : if (!var->is_used()) {
89 : receiver_info = UNUSED;
90 183849 : } else if (var->IsContextSlot()) {
91 : receiver_info = CONTEXT;
92 101226 : context_local_count++;
93 : } else {
94 : DCHECK(var->IsParameter());
95 : receiver_info = STACK;
96 : }
97 : } else {
98 : receiver_info = NONE;
99 : }
100 :
101 : DCHECK(module_vars_count == 0 || scope->is_module_scope());
102 :
103 : // Make sure we allocate the correct amount.
104 : DCHECK_EQ(scope->ContextLocalCount(), context_local_count);
105 :
106 : const bool has_new_target =
107 4328794 : scope->is_declaration_scope() &&
108 2100154 : scope->AsDeclarationScope()->new_target_var() != nullptr;
109 : // TODO(cbruni): Don't always waste a field for the inferred name.
110 : const bool has_inferred_function_name = scope->is_function_scope();
111 :
112 : // Determine use and location of the function variable if it is present.
113 : VariableAllocationInfo function_name_info;
114 2228640 : if (scope->is_function_scope()) {
115 1084369 : if (scope->AsDeclarationScope()->function_var() != nullptr) {
116 21362 : Variable* var = scope->AsDeclarationScope()->function_var();
117 21362 : if (!var->is_used()) {
118 : function_name_info = UNUSED;
119 21362 : } else if (var->IsContextSlot()) {
120 : function_name_info = CONTEXT;
121 : } else {
122 : DCHECK(var->IsStackLocal());
123 : function_name_info = STACK;
124 : }
125 : } else {
126 : // Always reserve space for the debug name in the scope info.
127 : function_name_info = UNUSED;
128 : }
129 1144271 : } else if (scope->is_module_scope() || scope->is_script_scope() ||
130 : scope->is_eval_scope()) {
131 : // Always reserve space for the debug name in the scope info.
132 : function_name_info = UNUSED;
133 : } else {
134 : function_name_info = NONE;
135 : }
136 :
137 : const bool has_function_name = function_name_info != NONE;
138 : const bool has_position_info = NeedsPositionInfo(scope->scope_type());
139 2228642 : const bool has_receiver = receiver_info == STACK || receiver_info == CONTEXT;
140 : const int parameter_count =
141 : scope->is_declaration_scope()
142 2100139 : ? scope->AsDeclarationScope()->num_parameters()
143 2228642 : : 0;
144 2228658 : const bool has_outer_scope_info = !outer_scope.is_null();
145 2228658 : const int length = kVariablePartIndex + 2 * context_local_count +
146 2228658 : (has_receiver ? 1 : 0) +
147 2228658 : (has_function_name ? kFunctionNameEntries : 0) +
148 2228658 : (has_inferred_function_name ? 1 : 0) +
149 2228658 : (has_position_info ? kPositionInfoEntries : 0) +
150 2229915 : (has_outer_scope_info ? 1 : 0) +
151 : (scope->is_module_scope()
152 1257 : ? 2 + kModuleVariableEntryLength * module_vars_count
153 2228658 : : 0);
154 :
155 : Handle<ScopeInfo> scope_info_handle =
156 2228658 : isolate->factory()->NewScopeInfo(length);
157 : int index = kVariablePartIndex;
158 : {
159 : DisallowHeapAllocation no_gc;
160 2228647 : ScopeInfo scope_info = *scope_info_handle;
161 : WriteBarrierMode mode = scope_info->GetWriteBarrierMode(no_gc);
162 :
163 : bool has_simple_parameters = false;
164 : bool is_asm_module = false;
165 : bool calls_sloppy_eval = false;
166 2228647 : if (scope->is_function_scope()) {
167 1084379 : DeclarationScope* function_scope = scope->AsDeclarationScope();
168 : has_simple_parameters = function_scope->has_simple_parameters();
169 : is_asm_module = function_scope->is_asm_module();
170 : }
171 : FunctionKind function_kind = kNormalFunction;
172 2228648 : if (scope->is_declaration_scope()) {
173 2100164 : function_kind = scope->AsDeclarationScope()->function_kind();
174 2100165 : calls_sloppy_eval = scope->AsDeclarationScope()->calls_sloppy_eval();
175 : }
176 :
177 : // Encode the flags.
178 : int flags =
179 2228647 : ScopeTypeField::encode(scope->scope_type()) |
180 2228647 : CallsSloppyEvalField::encode(calls_sloppy_eval) |
181 2228647 : LanguageModeField::encode(scope->language_mode()) |
182 2228647 : DeclarationScopeField::encode(scope->is_declaration_scope()) |
183 2228647 : ReceiverVariableField::encode(receiver_info) |
184 2228647 : HasNewTargetField::encode(has_new_target) |
185 2228647 : FunctionVariableField::encode(function_name_info) |
186 2228647 : HasInferredFunctionNameField::encode(has_inferred_function_name) |
187 2228647 : IsAsmModuleField::encode(is_asm_module) |
188 2228647 : HasSimpleParametersField::encode(has_simple_parameters) |
189 2228647 : FunctionKindField::encode(function_kind) |
190 2228647 : HasOuterScopeInfoField::encode(has_outer_scope_info) |
191 2228647 : IsDebugEvaluateScopeField::encode(scope->is_debug_evaluate_scope()) |
192 : ForceContextAllocationField::encode(
193 2228647 : scope->ForceContextForLanguageMode());
194 : scope_info->SetFlags(flags);
195 :
196 : scope_info->SetParameterCount(parameter_count);
197 : scope_info->SetContextLocalCount(context_local_count);
198 :
199 : // Add context locals' names and info, module variables' names and info.
200 : // Context locals are added using their index.
201 : int context_local_base = index;
202 2228647 : int context_local_info_base = context_local_base + context_local_count;
203 : int module_var_entry = scope_info->ModuleVariablesIndex();
204 :
205 11596395 : for (Variable* var : *scope->locals()) {
206 9367745 : switch (var->location()) {
207 : case VariableLocation::CONTEXT: {
208 : // Due to duplicate parameters, context locals aren't guaranteed to
209 : // come in order.
210 1849929 : int local_index = var->index() - Context::MIN_CONTEXT_SLOTS;
211 : DCHECK_LE(0, local_index);
212 : DCHECK_LT(local_index, context_local_count);
213 : uint32_t info =
214 1849929 : VariableModeField::encode(var->mode()) |
215 1849929 : InitFlagField::encode(var->initialization_flag()) |
216 : MaybeAssignedFlagField::encode(var->maybe_assigned()) |
217 1849929 : ParameterNumberField::encode(ParameterNumberField::kMax);
218 1849929 : scope_info->set(context_local_base + local_index, *var->name(), mode);
219 3699856 : scope_info->set(context_local_info_base + local_index,
220 : Smi::FromInt(info));
221 : break;
222 : }
223 : case VariableLocation::MODULE: {
224 36310 : scope_info->set(module_var_entry + kModuleVariableNameOffset,
225 18155 : *var->name(), mode);
226 : scope_info->set(module_var_entry + kModuleVariableIndexOffset,
227 : Smi::FromInt(var->index()));
228 : uint32_t properties =
229 18155 : VariableModeField::encode(var->mode()) |
230 18155 : InitFlagField::encode(var->initialization_flag()) |
231 : MaybeAssignedFlagField::encode(var->maybe_assigned()) |
232 18155 : ParameterNumberField::encode(ParameterNumberField::kMax);
233 18155 : scope_info->set(module_var_entry + kModuleVariablePropertiesOffset,
234 : Smi::FromInt(properties));
235 : module_var_entry += kModuleVariableEntryLength;
236 18155 : break;
237 : }
238 : default:
239 : break;
240 : }
241 : }
242 :
243 2228650 : if (scope->is_declaration_scope()) {
244 : // Mark contexts slots with the parameter number they represent. We walk
245 : // the list of parameters. That can include duplicate entries if a
246 : // parameter name is repeated. By walking upwards, we'll automatically
247 : // mark the context slot with the highest parameter number that uses this
248 : // variable. That will be the parameter number that is represented by the
249 : // context slot. All lower parameters will only be available on the stack
250 : // through the arguments object.
251 6815262 : for (int i = 0; i < parameter_count; i++) {
252 2357552 : Variable* parameter = scope->AsDeclarationScope()->parameter(i);
253 2357551 : if (parameter->location() != VariableLocation::CONTEXT) continue;
254 32312 : int index = parameter->index() - Context::MIN_CONTEXT_SLOTS;
255 32312 : int info_index = context_local_info_base + index;
256 : int info = Smi::ToInt(scope_info->get(info_index));
257 64624 : info = ParameterNumberField::update(info, i);
258 : scope_info->set(info_index, Smi::FromInt(info));
259 : }
260 :
261 : // TODO(verwaest): Remove this unnecessary entry.
262 4200321 : if (scope->AsDeclarationScope()->has_this_declaration()) {
263 910758 : Variable* var = scope->AsDeclarationScope()->receiver();
264 910761 : if (var->location() == VariableLocation::CONTEXT) {
265 101226 : int local_index = var->index() - Context::MIN_CONTEXT_SLOTS;
266 : uint32_t info =
267 101226 : VariableModeField::encode(var->mode()) |
268 101226 : InitFlagField::encode(var->initialization_flag()) |
269 : MaybeAssignedFlagField::encode(var->maybe_assigned()) |
270 101226 : ParameterNumberField::encode(ParameterNumberField::kMax);
271 101226 : scope_info->set(context_local_base + local_index, *var->name(), mode);
272 202452 : scope_info->set(context_local_info_base + local_index,
273 : Smi::FromInt(info));
274 : }
275 : }
276 : }
277 :
278 : index += 2 * context_local_count;
279 :
280 : // If the receiver is allocated, add its index.
281 : DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
282 2228655 : if (has_receiver) {
283 183854 : int var_index = scope->AsDeclarationScope()->receiver()->index();
284 183852 : scope_info->set(index++, Smi::FromInt(var_index));
285 : // ?? DCHECK(receiver_info != CONTEXT || var_index ==
286 : // scope_info->ContextLength() - 1);
287 : }
288 :
289 : // If present, add the function variable name and its index.
290 : DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
291 2228653 : if (has_function_name) {
292 2097727 : Variable* var = scope->AsDeclarationScope()->function_var();
293 : int var_index = -1;
294 2097730 : Object name = Smi::kZero;
295 2097730 : if (var != nullptr) {
296 : var_index = var->index();
297 21362 : name = *var->name();
298 : }
299 2097730 : scope_info->set(index++, name, mode);
300 2097733 : scope_info->set(index++, Smi::FromInt(var_index));
301 : DCHECK(function_name_info != CONTEXT ||
302 : var_index == scope_info->ContextLength() - 1);
303 : }
304 :
305 : DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
306 2228659 : if (has_inferred_function_name) {
307 : // The inferred function name is taken from the SFI.
308 1084381 : index++;
309 : }
310 :
311 : DCHECK_EQ(index, scope_info->PositionInfoIndex());
312 2228659 : if (has_position_info) {
313 : scope_info->set(index++, Smi::FromInt(scope->start_position()));
314 : scope_info->set(index++, Smi::FromInt(scope->end_position()));
315 : }
316 :
317 : // If present, add the outer scope info.
318 : DCHECK(index == scope_info->OuterScopeInfoIndex());
319 2228659 : if (has_outer_scope_info) {
320 1112425 : scope_info->set(index++, *outer_scope.ToHandleChecked(), mode);
321 : }
322 : }
323 :
324 : // Module-specific information (only for module scopes).
325 2228655 : if (scope->is_module_scope()) {
326 : Handle<ModuleInfo> module_info =
327 1257 : ModuleInfo::New(isolate, zone, scope->AsModuleScope()->module());
328 : DCHECK_EQ(index, scope_info_handle->ModuleInfoIndex());
329 2514 : scope_info_handle->set(index++, *module_info);
330 : DCHECK_EQ(index, scope_info_handle->ModuleVariableCountIndex());
331 : scope_info_handle->set(index++, Smi::FromInt(module_vars_count));
332 : DCHECK_EQ(index, scope_info_handle->ModuleVariablesIndex());
333 : // The variable entries themselves have already been written above.
334 : index += kModuleVariableEntryLength * module_vars_count;
335 : }
336 :
337 : DCHECK_EQ(index, scope_info_handle->length());
338 : DCHECK_EQ(parameter_count, scope_info_handle->ParameterCount());
339 : DCHECK_EQ(scope->num_heap_slots(), scope_info_handle->ContextLength());
340 2228655 : return scope_info_handle;
341 : }
342 :
343 : // static
344 12551 : Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
345 : Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope) {
346 12551 : const bool has_outer_scope_info = !outer_scope.is_null();
347 12551 : const int length = kVariablePartIndex + (has_outer_scope_info ? 1 : 0);
348 :
349 : Factory* factory = isolate->factory();
350 12551 : Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
351 :
352 : // Encode the flags.
353 : int flags =
354 : ScopeTypeField::encode(WITH_SCOPE) | CallsSloppyEvalField::encode(false) |
355 : LanguageModeField::encode(LanguageMode::kSloppy) |
356 : DeclarationScopeField::encode(false) |
357 : ReceiverVariableField::encode(NONE) | HasNewTargetField::encode(false) |
358 : FunctionVariableField::encode(NONE) | IsAsmModuleField::encode(false) |
359 : HasSimpleParametersField::encode(true) |
360 12551 : FunctionKindField::encode(kNormalFunction) |
361 : HasOuterScopeInfoField::encode(has_outer_scope_info) |
362 12551 : IsDebugEvaluateScopeField::encode(false);
363 : scope_info->SetFlags(flags);
364 :
365 : scope_info->SetParameterCount(0);
366 : scope_info->SetContextLocalCount(0);
367 :
368 : int index = kVariablePartIndex;
369 : DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
370 : DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
371 : DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
372 : DCHECK_EQ(index, scope_info->PositionInfoIndex());
373 : DCHECK(index == scope_info->OuterScopeInfoIndex());
374 12551 : if (has_outer_scope_info) {
375 4820 : scope_info->set(index++, *outer_scope.ToHandleChecked());
376 : }
377 : DCHECK_EQ(index, scope_info->length());
378 : DCHECK_EQ(0, scope_info->ParameterCount());
379 : DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, scope_info->ContextLength());
380 12551 : return scope_info;
381 : }
382 :
383 : // static
384 111 : Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
385 111 : return CreateForBootstrapping(isolate, SCRIPT_SCOPE);
386 : }
387 :
388 : // static
389 113 : Handle<ScopeInfo> ScopeInfo::CreateForEmptyFunction(Isolate* isolate) {
390 113 : return CreateForBootstrapping(isolate, FUNCTION_SCOPE);
391 : }
392 :
393 : // static
394 224 : Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
395 : ScopeType type) {
396 : DCHECK(type == SCRIPT_SCOPE || type == FUNCTION_SCOPE);
397 :
398 : const int parameter_count = 0;
399 224 : const bool is_empty_function = type == FUNCTION_SCOPE;
400 224 : const int context_local_count = is_empty_function ? 0 : 1;
401 : const bool has_receiver = !is_empty_function;
402 : const bool has_inferred_function_name = is_empty_function;
403 : const bool has_position_info = true;
404 224 : const int length = kVariablePartIndex + 2 * context_local_count +
405 224 : (has_receiver ? 1 : 0) +
406 224 : (is_empty_function ? kFunctionNameEntries : 0) +
407 : (has_inferred_function_name ? 1 : 0) +
408 224 : (has_position_info ? kPositionInfoEntries : 0);
409 :
410 : Factory* factory = isolate->factory();
411 224 : Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
412 :
413 : // Encode the flags.
414 : int flags =
415 : ScopeTypeField::encode(type) | CallsSloppyEvalField::encode(false) |
416 224 : LanguageModeField::encode(LanguageMode::kSloppy) |
417 224 : DeclarationScopeField::encode(true) |
418 224 : ReceiverVariableField::encode(is_empty_function ? UNUSED : CONTEXT) |
419 224 : HasNewTargetField::encode(false) |
420 448 : FunctionVariableField::encode(is_empty_function ? UNUSED : NONE) |
421 : HasInferredFunctionNameField::encode(has_inferred_function_name) |
422 224 : IsAsmModuleField::encode(false) | HasSimpleParametersField::encode(true) |
423 : FunctionKindField::encode(FunctionKind::kNormalFunction) |
424 : HasOuterScopeInfoField::encode(false) |
425 224 : IsDebugEvaluateScopeField::encode(false);
426 : scope_info->SetFlags(flags);
427 : scope_info->SetParameterCount(parameter_count);
428 : scope_info->SetContextLocalCount(context_local_count);
429 :
430 : int index = kVariablePartIndex;
431 :
432 : // Here we add info for context-allocated "this".
433 : DCHECK_EQ(index, scope_info->ContextLocalNamesIndex());
434 224 : if (context_local_count) {
435 222 : scope_info->set(index++, ReadOnlyRoots(isolate).this_string());
436 : }
437 : DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
438 224 : if (context_local_count) {
439 : const uint32_t value =
440 : VariableModeField::encode(VariableMode::kConst) |
441 : InitFlagField::encode(kCreatedInitialized) |
442 : MaybeAssignedFlagField::encode(kNotAssigned) |
443 : ParameterNumberField::encode(ParameterNumberField::kMax);
444 111 : scope_info->set(index++, Smi::FromInt(value));
445 : }
446 :
447 : // And here we record that this scopeinfo binds a receiver.
448 : DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
449 : const int receiver_index = Context::MIN_CONTEXT_SLOTS + 0;
450 224 : if (!is_empty_function) {
451 111 : scope_info->set(index++, Smi::FromInt(receiver_index));
452 : }
453 :
454 : DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
455 224 : if (is_empty_function) {
456 226 : scope_info->set(index++, *isolate->factory()->empty_string());
457 226 : scope_info->set(index++, Smi::kZero);
458 : }
459 : DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
460 224 : if (has_inferred_function_name) {
461 226 : scope_info->set(index++, *isolate->factory()->empty_string());
462 : }
463 : DCHECK_EQ(index, scope_info->PositionInfoIndex());
464 : // Store dummy position to be in sync with the {scope_type}.
465 448 : scope_info->set(index++, Smi::kZero);
466 224 : scope_info->set(index++, Smi::kZero);
467 : DCHECK_EQ(index, scope_info->OuterScopeInfoIndex());
468 : DCHECK_EQ(index, scope_info->length());
469 : DCHECK_EQ(scope_info->ParameterCount(), parameter_count);
470 : if (type == FUNCTION_SCOPE) {
471 : DCHECK_EQ(scope_info->ContextLength(), 0);
472 : } else {
473 : DCHECK_EQ(scope_info->ContextLength(), Context::MIN_CONTEXT_SLOTS + 1);
474 : }
475 :
476 224 : return scope_info;
477 : }
478 :
479 4173549 : ScopeInfo ScopeInfo::Empty(Isolate* isolate) {
480 4173549 : return ReadOnlyRoots(isolate).empty_scope_info();
481 : }
482 :
483 4773686 : ScopeType ScopeInfo::scope_type() const {
484 : DCHECK_LT(0, length());
485 19399658 : return ScopeTypeField::decode(Flags());
486 : }
487 :
488 1137939 : bool ScopeInfo::CallsSloppyEval() const {
489 : bool calls_sloppy_eval =
490 2275879 : length() > 0 && CallsSloppyEvalField::decode(Flags());
491 : DCHECK_IMPLIES(calls_sloppy_eval, is_sloppy(language_mode()));
492 : DCHECK_IMPLIES(calls_sloppy_eval, is_declaration_scope());
493 1137939 : return calls_sloppy_eval;
494 : }
495 :
496 1488646 : LanguageMode ScopeInfo::language_mode() const {
497 1488648 : return length() > 0 ? LanguageModeField::decode(Flags())
498 2977295 : : LanguageMode::kSloppy;
499 : }
500 :
501 53242 : bool ScopeInfo::is_declaration_scope() const {
502 111714 : return DeclarationScopeField::decode(Flags());
503 : }
504 :
505 1362407 : int ScopeInfo::ContextLength() const {
506 1362407 : if (length() > 0) {
507 1362409 : int context_locals = ContextLocalCount();
508 : bool function_name_context_slot =
509 1362409 : FunctionVariableField::decode(Flags()) == CONTEXT;
510 1362411 : bool force_context = ForceContextAllocationField::decode(Flags());
511 : bool has_context =
512 1407489 : context_locals > 0 || force_context || function_name_context_slot ||
513 14280 : scope_type() == WITH_SCOPE || scope_type() == CLASS_SCOPE ||
514 10456 : (scope_type() == BLOCK_SCOPE && CallsSloppyEval() &&
515 1912 : is_declaration_scope()) ||
516 2764 : (scope_type() == FUNCTION_SCOPE && CallsSloppyEval()) ||
517 1363409 : (scope_type() == FUNCTION_SCOPE && IsAsmModule()) ||
518 : scope_type() == MODULE_SCOPE;
519 :
520 1362408 : if (has_context) {
521 1362259 : return Context::MIN_CONTEXT_SLOTS + context_locals +
522 1362259 : (function_name_context_slot ? 1 : 0);
523 : }
524 : }
525 : return 0;
526 : }
527 :
528 0 : bool ScopeInfo::HasReceiver() const {
529 0 : if (length() == 0) return false;
530 0 : return NONE != ReceiverVariableField::decode(Flags());
531 : }
532 :
533 19012334 : bool ScopeInfo::HasAllocatedReceiver() const {
534 19012334 : if (length() == 0) return false;
535 19012334 : VariableAllocationInfo allocation = ReceiverVariableField::decode(Flags());
536 19012328 : return allocation == STACK || allocation == CONTEXT;
537 : }
538 :
539 0 : bool ScopeInfo::HasNewTarget() const {
540 0 : return HasNewTargetField::decode(Flags());
541 : }
542 :
543 13723851 : bool ScopeInfo::HasFunctionName() const {
544 13723851 : if (length() == 0) return false;
545 27445351 : return NONE != FunctionVariableField::decode(Flags());
546 : }
547 :
548 11358545 : bool ScopeInfo::HasInferredFunctionName() const {
549 11358545 : if (length() == 0) return false;
550 22717094 : return HasInferredFunctionNameField::decode(Flags());
551 : }
552 :
553 13452311 : bool ScopeInfo::HasPositionInfo() const {
554 13452311 : if (length() == 0) return false;
555 9812593 : return NeedsPositionInfo(scope_type());
556 : }
557 :
558 : // static
559 0 : bool ScopeInfo::NeedsPositionInfo(ScopeType type) {
560 15108188 : return type == FUNCTION_SCOPE || type == SCRIPT_SCOPE || type == EVAL_SCOPE ||
561 3066953 : type == MODULE_SCOPE;
562 : }
563 :
564 3165147 : bool ScopeInfo::HasSharedFunctionName() const {
565 6330297 : return FunctionName() != SharedFunctionInfo::kNoSharedNameSentinel;
566 : }
567 :
568 2096959 : void ScopeInfo::SetFunctionName(Object name) {
569 : DCHECK(HasFunctionName());
570 : DCHECK(name->IsString() || name == SharedFunctionInfo::kNoSharedNameSentinel);
571 2096959 : set(FunctionNameInfoIndex(), name);
572 2096960 : }
573 :
574 52684 : void ScopeInfo::SetInferredFunctionName(String name) {
575 : DCHECK(HasInferredFunctionName());
576 52684 : set(InferredFunctionNameIndex(), name);
577 52684 : }
578 :
579 3561549 : bool ScopeInfo::HasOuterScopeInfo() const {
580 3561549 : if (length() == 0) return false;
581 7123106 : return HasOuterScopeInfoField::decode(Flags());
582 : }
583 :
584 14851 : bool ScopeInfo::IsDebugEvaluateScope() const {
585 14851 : if (length() == 0) return false;
586 29702 : return IsDebugEvaluateScopeField::decode(Flags());
587 : }
588 :
589 12527 : void ScopeInfo::SetIsDebugEvaluateScope() {
590 12527 : if (length() > 0) {
591 : DCHECK_EQ(scope_type(), WITH_SCOPE);
592 12527 : SetFlags(Flags() | IsDebugEvaluateScopeField::encode(true));
593 : } else {
594 0 : UNREACHABLE();
595 : }
596 12527 : }
597 :
598 0 : bool ScopeInfo::HasContext() const { return ContextLength() > 0; }
599 :
600 6287541 : Object ScopeInfo::FunctionName() const {
601 : DCHECK(HasFunctionName());
602 12575087 : return get(FunctionNameInfoIndex());
603 : }
604 :
605 722983 : Object ScopeInfo::InferredFunctionName() const {
606 : DCHECK(HasInferredFunctionName());
607 1445966 : return get(InferredFunctionNameIndex());
608 : }
609 :
610 18676 : String ScopeInfo::FunctionDebugName() const {
611 18676 : Object name = FunctionName();
612 37352 : if (name->IsString() && String::cast(name)->length() > 0) {
613 : return String::cast(name);
614 : }
615 10264 : if (HasInferredFunctionName()) {
616 2370 : name = InferredFunctionName();
617 2370 : if (name->IsString()) return String::cast(name);
618 : }
619 : return GetReadOnlyRoots().empty_string();
620 : }
621 :
622 6466404 : int ScopeInfo::StartPosition() const {
623 : DCHECK(HasPositionInfo());
624 12932811 : return Smi::ToInt(get(PositionInfoIndex()));
625 : }
626 :
627 582929 : int ScopeInfo::EndPosition() const {
628 : DCHECK(HasPositionInfo());
629 1165858 : return Smi::ToInt(get(PositionInfoIndex() + 1));
630 : }
631 :
632 1067 : void ScopeInfo::SetPositionInfo(int start, int end) {
633 : DCHECK(HasPositionInfo());
634 : DCHECK_LE(start, end);
635 1067 : set(PositionInfoIndex(), Smi::FromInt(start));
636 1067 : set(PositionInfoIndex() + 1, Smi::FromInt(end));
637 1067 : }
638 :
639 552346 : ScopeInfo ScopeInfo::OuterScopeInfo() const {
640 : DCHECK(HasOuterScopeInfo());
641 1104697 : return ScopeInfo::cast(get(OuterScopeInfoIndex()));
642 : }
643 :
644 10894 : ModuleInfo ScopeInfo::ModuleDescriptorInfo() const {
645 : DCHECK(scope_type() == MODULE_SCOPE);
646 21788 : return ModuleInfo::cast(get(ModuleInfoIndex()));
647 : }
648 :
649 1683421 : String ScopeInfo::ContextLocalName(int var) const {
650 : DCHECK_LE(0, var);
651 : DCHECK_LT(var, ContextLocalCount());
652 1683421 : int info_index = ContextLocalNamesIndex() + var;
653 1683421 : return String::cast(get(info_index));
654 : }
655 :
656 3177299 : VariableMode ScopeInfo::ContextLocalMode(int var) const {
657 : DCHECK_LE(0, var);
658 : DCHECK_LT(var, ContextLocalCount());
659 3177300 : int info_index = ContextLocalInfosIndex() + var;
660 : int value = Smi::ToInt(get(info_index));
661 3177300 : return VariableModeField::decode(value);
662 : }
663 :
664 2218764 : InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) const {
665 : DCHECK_LE(0, var);
666 : DCHECK_LT(var, ContextLocalCount());
667 2218764 : int info_index = ContextLocalInfosIndex() + var;
668 : int value = Smi::ToInt(get(info_index));
669 4437528 : return InitFlagField::decode(value);
670 : }
671 :
672 129 : bool ScopeInfo::ContextLocalIsParameter(int var) const {
673 : DCHECK_LE(0, var);
674 : DCHECK_LT(var, ContextLocalCount());
675 129 : int info_index = ContextLocalInfosIndex() + var;
676 : int value = Smi::ToInt(get(info_index));
677 258 : return ParameterNumberField::decode(value) != ParameterNumberField::kMax;
678 : }
679 :
680 129 : uint32_t ScopeInfo::ContextLocalParameterNumber(int var) const {
681 : DCHECK(ContextLocalIsParameter(var));
682 129 : int info_index = ContextLocalInfosIndex() + var;
683 : int value = Smi::ToInt(get(info_index));
684 258 : return ParameterNumberField::decode(value);
685 : }
686 :
687 2223805 : MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) const {
688 : DCHECK_LE(0, var);
689 : DCHECK_LT(var, ContextLocalCount());
690 2223805 : int info_index = ContextLocalInfosIndex() + var;
691 : int value = Smi::ToInt(get(info_index));
692 4447610 : return MaybeAssignedFlagField::decode(value);
693 : }
694 :
695 : // static
696 7206860 : bool ScopeInfo::VariableIsSynthetic(String name) {
697 : // There's currently no flag stored on the ScopeInfo to indicate that a
698 : // variable is a compiler-introduced temporary. However, to avoid conflict
699 : // with user declarations, the current temporaries like .generator_object and
700 : // .result start with a dot, so we can use that as a flag. It's a hack!
701 21493627 : return name->length() == 0 || name->Get(0) == '.' ||
702 14289070 : name->Equals(name->GetReadOnlyRoots().this_string());
703 : }
704 :
705 2291 : int ScopeInfo::ModuleIndex(String name, VariableMode* mode,
706 : InitializationFlag* init_flag,
707 : MaybeAssignedFlag* maybe_assigned_flag) {
708 : DisallowHeapAllocation no_gc;
709 : DCHECK(name->IsInternalizedString());
710 : DCHECK_EQ(scope_type(), MODULE_SCOPE);
711 : DCHECK_NOT_NULL(mode);
712 : DCHECK_NOT_NULL(init_flag);
713 : DCHECK_NOT_NULL(maybe_assigned_flag);
714 :
715 : int module_vars_count = Smi::ToInt(get(ModuleVariableCountIndex()));
716 : int entry = ModuleVariablesIndex();
717 10955 : for (int i = 0; i < module_vars_count; ++i) {
718 5005 : String var_name = String::cast(get(entry + kModuleVariableNameOffset));
719 5005 : if (name->Equals(var_name)) {
720 : int index;
721 673 : ModuleVariable(i, nullptr, &index, mode, init_flag, maybe_assigned_flag);
722 673 : return index;
723 : }
724 4332 : entry += kModuleVariableEntryLength;
725 : }
726 :
727 : return 0;
728 : }
729 :
730 : // static
731 18999315 : int ScopeInfo::ContextSlotIndex(ScopeInfo scope_info, String name,
732 : VariableMode* mode,
733 : InitializationFlag* init_flag,
734 : MaybeAssignedFlag* maybe_assigned_flag) {
735 : DisallowHeapAllocation no_gc;
736 : DCHECK(name->IsInternalizedString());
737 : DCHECK_NOT_NULL(mode);
738 : DCHECK_NOT_NULL(init_flag);
739 : DCHECK_NOT_NULL(maybe_assigned_flag);
740 :
741 18999315 : if (scope_info->length() == 0) return -1;
742 :
743 : int start = scope_info->ContextLocalNamesIndex();
744 18999332 : int end = start + scope_info->ContextLocalCount();
745 277144776 : for (int i = start; i < end; ++i) {
746 131291490 : if (name != scope_info->get(i)) continue;
747 2218768 : int var = i - start;
748 2218768 : *mode = scope_info->ContextLocalMode(var);
749 2218764 : *init_flag = scope_info->ContextLocalInitFlag(var);
750 2218762 : *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
751 2218764 : int result = Context::MIN_CONTEXT_SLOTS + var;
752 :
753 : DCHECK_LT(result, scope_info->ContextLength());
754 2218764 : return result;
755 : }
756 :
757 : return -1;
758 : }
759 :
760 632929 : int ScopeInfo::ReceiverContextSlotIndex() const {
761 1265858 : if (length() > 0 && ReceiverVariableField::decode(Flags()) == CONTEXT) {
762 1239872 : return Smi::ToInt(get(ReceiverInfoIndex()));
763 : }
764 : return -1;
765 : }
766 :
767 3873517 : int ScopeInfo::FunctionContextSlotIndex(String name) const {
768 : DCHECK(name->IsInternalizedString());
769 3873517 : if (length() > 0) {
770 7750766 : if (FunctionVariableField::decode(Flags()) == CONTEXT &&
771 3721 : FunctionName() == name) {
772 2404 : return Smi::ToInt(get(FunctionNameInfoIndex() + 1));
773 : }
774 : }
775 : return -1;
776 : }
777 :
778 908487 : FunctionKind ScopeInfo::function_kind() const {
779 1816975 : return FunctionKindField::decode(Flags());
780 : }
781 :
782 0 : int ScopeInfo::ContextLocalNamesIndex() const {
783 : DCHECK_LT(0, length());
784 0 : return kVariablePartIndex;
785 : }
786 :
787 0 : int ScopeInfo::ContextLocalInfosIndex() const {
788 27252398 : return ContextLocalNamesIndex() + ContextLocalCount();
789 : }
790 :
791 19632272 : int ScopeInfo::ReceiverInfoIndex() const {
792 19632274 : return ContextLocalInfosIndex() + ContextLocalCount();
793 : }
794 :
795 19012337 : int ScopeInfo::FunctionNameInfoIndex() const {
796 19012337 : return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0);
797 : }
798 :
799 10626643 : int ScopeInfo::InferredFunctionNameIndex() const {
800 21253291 : return FunctionNameInfoIndex() +
801 21253290 : (HasFunctionName() ? kFunctionNameEntries : 0);
802 : }
803 :
804 9850977 : int ScopeInfo::PositionInfoIndex() const {
805 9850977 : return InferredFunctionNameIndex() + (HasInferredFunctionName() ? 1 : 0);
806 : }
807 :
808 2799509 : int ScopeInfo::OuterScopeInfoIndex() const {
809 2799509 : return PositionInfoIndex() + (HasPositionInfo() ? kPositionInfoEntries : 0);
810 : }
811 :
812 2247159 : int ScopeInfo::ModuleInfoIndex() const {
813 2247159 : return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0);
814 : }
815 :
816 753 : int ScopeInfo::ModuleVariableCountIndex() const {
817 2236270 : return ModuleInfoIndex() + 1;
818 : }
819 :
820 0 : int ScopeInfo::ModuleVariablesIndex() const {
821 2233230 : return ModuleVariableCountIndex() + 1;
822 : }
823 :
824 2288 : void ScopeInfo::ModuleVariable(int i, String* name, int* index,
825 : VariableMode* mode,
826 : InitializationFlag* init_flag,
827 : MaybeAssignedFlag* maybe_assigned_flag) {
828 : DCHECK_LE(0, i);
829 : DCHECK_LT(i, Smi::ToInt(get(ModuleVariableCountIndex())));
830 :
831 2288 : int entry = ModuleVariablesIndex() + i * kModuleVariableEntryLength;
832 2288 : int properties = Smi::ToInt(get(entry + kModuleVariablePropertiesOffset));
833 :
834 2288 : if (name != nullptr) {
835 1615 : *name = String::cast(get(entry + kModuleVariableNameOffset));
836 : }
837 2288 : if (index != nullptr) {
838 4576 : *index = Smi::ToInt(get(entry + kModuleVariableIndexOffset));
839 : DCHECK_NE(*index, 0);
840 : }
841 2288 : if (mode != nullptr) {
842 673 : *mode = VariableModeField::decode(properties);
843 : }
844 2288 : if (init_flag != nullptr) {
845 1346 : *init_flag = InitFlagField::decode(properties);
846 : }
847 2288 : if (maybe_assigned_flag != nullptr) {
848 1346 : *maybe_assigned_flag = MaybeAssignedFlagField::decode(properties);
849 : }
850 2288 : }
851 :
852 0 : std::ostream& operator<<(std::ostream& os,
853 : ScopeInfo::VariableAllocationInfo var_info) {
854 0 : switch (var_info) {
855 : case ScopeInfo::VariableAllocationInfo::NONE:
856 0 : return os << "NONE";
857 : case ScopeInfo::VariableAllocationInfo::STACK:
858 0 : return os << "STACK";
859 : case ScopeInfo::VariableAllocationInfo::CONTEXT:
860 0 : return os << "CONTEXT";
861 : case ScopeInfo::VariableAllocationInfo::UNUSED:
862 0 : return os << "UNUSED";
863 : }
864 0 : UNREACHABLE();
865 : return os;
866 : }
867 :
868 943 : Handle<ModuleInfoEntry> ModuleInfoEntry::New(Isolate* isolate,
869 : Handle<Object> export_name,
870 : Handle<Object> local_name,
871 : Handle<Object> import_name,
872 : int module_request, int cell_index,
873 : int beg_pos, int end_pos) {
874 : Handle<ModuleInfoEntry> result =
875 : Handle<ModuleInfoEntry>::cast(isolate->factory()->NewStruct(
876 943 : MODULE_INFO_ENTRY_TYPE, AllocationType::kOld));
877 943 : result->set_export_name(*export_name);
878 943 : result->set_local_name(*local_name);
879 943 : result->set_import_name(*import_name);
880 : result->set_module_request(module_request);
881 : result->set_cell_index(cell_index);
882 : result->set_beg_pos(beg_pos);
883 : result->set_end_pos(end_pos);
884 943 : return result;
885 : }
886 :
887 1257 : Handle<ModuleInfo> ModuleInfo::New(Isolate* isolate, Zone* zone,
888 : ModuleDescriptor* descr) {
889 : // Serialize module requests.
890 1257 : int size = static_cast<int>(descr->module_requests().size());
891 1257 : Handle<FixedArray> module_requests = isolate->factory()->NewFixedArray(size);
892 : Handle<FixedArray> module_request_positions =
893 1257 : isolate->factory()->NewFixedArray(size);
894 2036 : for (const auto& elem : descr->module_requests()) {
895 2337 : module_requests->set(elem.second.index, *elem.first->string());
896 779 : module_request_positions->set(elem.second.index,
897 779 : Smi::FromInt(elem.second.position));
898 : }
899 :
900 : // Serialize special exports.
901 : Handle<FixedArray> special_exports = isolate->factory()->NewFixedArray(
902 1257 : static_cast<int>(descr->special_exports().size()));
903 : {
904 : int i = 0;
905 1547 : for (auto entry : descr->special_exports()) {
906 290 : Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
907 580 : special_exports->set(i++, *serialized_entry);
908 : }
909 : }
910 :
911 : // Serialize namespace imports.
912 : Handle<FixedArray> namespace_imports = isolate->factory()->NewFixedArray(
913 1257 : static_cast<int>(descr->namespace_imports().size()));
914 : {
915 : int i = 0;
916 1397 : for (auto entry : descr->namespace_imports()) {
917 140 : Handle<ModuleInfoEntry> serialized_entry = entry->Serialize(isolate);
918 280 : namespace_imports->set(i++, *serialized_entry);
919 : }
920 : }
921 :
922 : // Serialize regular exports.
923 : Handle<FixedArray> regular_exports =
924 1257 : descr->SerializeRegularExports(isolate, zone);
925 :
926 : // Serialize regular imports.
927 : Handle<FixedArray> regular_imports = isolate->factory()->NewFixedArray(
928 1257 : static_cast<int>(descr->regular_imports().size()));
929 : {
930 : int i = 0;
931 1770 : for (const auto& elem : descr->regular_imports()) {
932 : Handle<ModuleInfoEntry> serialized_entry =
933 513 : elem.second->Serialize(isolate);
934 1026 : regular_imports->set(i++, *serialized_entry);
935 : }
936 : }
937 :
938 1257 : Handle<ModuleInfo> result = isolate->factory()->NewModuleInfo();
939 2514 : result->set(kModuleRequestsIndex, *module_requests);
940 2514 : result->set(kSpecialExportsIndex, *special_exports);
941 2514 : result->set(kRegularExportsIndex, *regular_exports);
942 2514 : result->set(kNamespaceImportsIndex, *namespace_imports);
943 2514 : result->set(kRegularImportsIndex, *regular_imports);
944 2514 : result->set(kModuleRequestPositionsIndex, *module_request_positions);
945 1257 : return result;
946 : }
947 :
948 5582 : int ModuleInfo::RegularExportCount() const {
949 : DCHECK_EQ(regular_exports()->length() % kRegularExportLength, 0);
950 5582 : return regular_exports()->length() / kRegularExportLength;
951 : }
952 :
953 0 : String ModuleInfo::RegularExportLocalName(int i) const {
954 : return String::cast(regular_exports()->get(i * kRegularExportLength +
955 0 : kRegularExportLocalNameOffset));
956 : }
957 :
958 31447 : int ModuleInfo::RegularExportCellIndex(int i) const {
959 31447 : return Smi::ToInt(regular_exports()->get(i * kRegularExportLength +
960 31447 : kRegularExportCellIndexOffset));
961 : }
962 :
963 31447 : FixedArray ModuleInfo::RegularExportExportNames(int i) const {
964 : return FixedArray::cast(regular_exports()->get(
965 62894 : i * kRegularExportLength + kRegularExportExportNamesOffset));
966 : }
967 :
968 : } // namespace internal
969 122036 : } // namespace v8
|