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