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