Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(166)

Side by Side Diff: src/ast/scopeinfo.cc

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

Powered by Google App Engine
This is Rietveld 408576698