summaryrefslogtreecommitdiff
path: root/deps/v8/src/objects/scope-info.tq
blob: 3f29d9ecf307279d16ddfef0f73c5df83513f313 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

extern macro EmptyScopeInfoConstant(): ScopeInfo;
const kEmptyScopeInfo: ScopeInfo = EmptyScopeInfoConstant();

extern enum ScopeType extends uint32 {
  CLASS_SCOPE,  // Also used for the empty scope (for NativeContext & builtins).
  EVAL_SCOPE,
  FUNCTION_SCOPE,
  MODULE_SCOPE,
  SCRIPT_SCOPE,
  CATCH_SCOPE,
  BLOCK_SCOPE,
  WITH_SCOPE
}

extern enum VariableAllocationInfo extends uint32 {
  NONE,
  STACK,
  CONTEXT,
  UNUSED
}

extern enum VariableMode extends uint32 {
  kLet,
  kConst,
  kVar,
  kTemporary,
  kDynamic,
  kDynamicGlobal,
  kDynamicLocal,
  kPrivateMethod,
  kPrivateSetterOnly,
  kPrivateGetterOnly,
  kPrivateGetterAndSetter
}

extern enum InitializationFlag extends uint32 {
  kNeedsInitialization,
  kCreatedInitialized
}

extern enum IsStaticFlag extends uint32 { kNotStatic, kStatic }

extern enum MaybeAssignedFlag extends uint32 { kNotAssigned, kMaybeAssigned }

// Properties of scopes.
bitfield struct ScopeFlags extends uint31 {
  scope_type: ScopeType: 4 bit;
  sloppy_eval_can_extend_vars: bool: 1 bit;
  language_mode: LanguageMode: 1 bit;
  declaration_scope: bool: 1 bit;
  receiver_variable: VariableAllocationInfo: 2 bit;
  has_class_brand: bool: 1 bit;
  has_saved_class_variable_index: bool: 1 bit;
  has_new_target: bool: 1 bit;
  // TODO(cbruni): Combine with function variable field when only storing the
  // function name.
  function_variable: VariableAllocationInfo: 2 bit;
  has_inferred_function_name: bool: 1 bit;
  is_asm_module: bool: 1 bit;
  has_simple_parameters: bool: 1 bit;
  function_kind: FunctionKind: 5 bit;
  has_outer_scope_info: bool: 1 bit;
  is_debug_evaluate_scope: bool: 1 bit;
  force_context_allocation: bool: 1 bit;
  private_name_lookup_skips_outer_class: bool: 1 bit;
  has_context_extension_slot: bool: 1 bit;
  is_repl_mode_scope: bool: 1 bit;
  has_locals_block_list: bool: 1 bit;
  is_empty: bool: 1 bit;
}

struct PositionInfo {
  start: Smi;
  end: Smi;
}

struct FunctionVariableInfo {
  name: String|Zero;
  context_or_stack_slot_index: Smi;
}

bitfield struct VariableProperties extends uint31 {
  variable_mode: VariableMode: 4 bit;
  init_flag: InitializationFlag: 1 bit;
  maybe_assigned_flag: MaybeAssignedFlag: 1 bit;
  parameter_number: uint32: 16 bit;
  is_static_flag: IsStaticFlag: 1 bit;
}

struct ModuleVariable {
  name: String;
  index: Smi;
  properties: SmiTagged<VariableProperties>;
}

@generateBodyDescriptor
extern class ScopeInfo extends HeapObject {
  const flags: SmiTagged<ScopeFlags>;

  // The number of parameters. For non-function scopes this is 0.
  parameter_count: Smi;

  // The number of non-parameter and parameter variables allocated in the
  // context.
  const context_local_count: Smi;

  // Contains the names of local variables and parameters that are allocated
  // in the context. They are stored in increasing order of the context slot
  // index starting with Context::MIN_CONTEXT_SLOTS.
  context_local_names[context_local_count]: String;

  // Contains the variable modes and initialization flags corresponding to
  // the context locals in ContextLocalNames.
  context_local_infos[context_local_count]: SmiTagged<VariableProperties>;

  // If the scope is a class scope and it has static private methods that
  // may be accessed directly or through eval, one slot is reserved to hold
  // the context slot index for the class variable.
  saved_class_variable_info?[flags.has_saved_class_variable_index]: Smi;

  // If the scope binds a "this" value, one slot is reserved to hold the
  // context or stack slot index for the variable.
  receiver_info?[
    flags.receiver_variable ==
        FromConstexpr<VariableAllocationInfo>(VariableAllocationInfo::STACK) ||
    flags.receiver_variable ==
        FromConstexpr<VariableAllocationInfo>(VariableAllocationInfo::CONTEXT)
  ]: Smi;

  // If the scope belongs to a named function expression this part contains
  // information about the function variable. It always occupies two array
  // slots:  a. The name of the function variable.
  //         b. The context or stack slot index for the variable.
  function_variable_info?
      [flags.function_variable !=
       FromConstexpr<VariableAllocationInfo>(VariableAllocationInfo::NONE)]:
          FunctionVariableInfo;

  inferred_function_name?[flags.has_inferred_function_name]: String|Undefined;

  // Contains two slots with a) the startPosition and b) the endPosition if
  // the scope belongs to a function or script.
  position_info?
      [flags.scope_type == ScopeType::FUNCTION_SCOPE ||
       flags.scope_type == ScopeType::SCRIPT_SCOPE ||
       flags.scope_type == ScopeType::EVAL_SCOPE ||
       flags.scope_type == ScopeType::MODULE_SCOPE]: PositionInfo;

  outer_scope_info?[flags.has_outer_scope_info]: ScopeInfo|TheHole;

  // List of stack allocated local variables. Used by debug evaluate to properly
  // abort variable lookup when a name clashes with a stack allocated local that
  // can't be materialized.
  locals_block_list?[flags.has_locals_block_list]: HashTable;

  // For a module scope, this part contains the SourceTextModuleInfo, the
  // number of MODULE-allocated variables, and the metadata of those
  // variables.  For non-module scopes it is empty.
  module_info?
      [flags.scope_type == ScopeType::MODULE_SCOPE]: SourceTextModuleInfo;
  const module_variable_count?
      [flags.scope_type == ScopeType::MODULE_SCOPE]: Smi;
  module_variables[flags.scope_type == ScopeType::MODULE_SCOPE ? module_variable_count : 0]:
      ModuleVariable;
}

// Returns the index of the named local in a ScopeInfo.
// Assumes that the given name is internalized; uses pointer comparisons.
@export
macro IndexOfLocalName(scopeInfo: ScopeInfo, name: Name):
    intptr labels NotFound {
  const count: intptr = Convert<intptr>(scopeInfo.context_local_count);
  for (let i: intptr = 0; i < count; ++i) {
    if (TaggedEqual(name, scopeInfo.context_local_names[i])) {
      return i;
    }
  }
  goto NotFound;
}