summaryrefslogtreecommitdiff
path: root/deps/v8/src/objects/scope-info.h
blob: 75a374d5d88d50b6ed70b989ebc4a8d512a11883 (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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
// Copyright 2015 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.

#ifndef V8_OBJECTS_SCOPE_INFO_H_
#define V8_OBJECTS_SCOPE_INFO_H_

#include "src/globals.h"
#include "src/objects.h"
#include "src/utils.h"

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {

template <typename T>
class Handle;
class Isolate;
template <typename T>
class MaybeHandle;
class Scope;
class Zone;

// ScopeInfo represents information about different scopes of a source
// program  and the allocation of the scope's variables. Scope information
// is stored in a compressed form in ScopeInfo objects and is used
// at runtime (stack dumps, deoptimization, etc.).

// This object provides quick access to scope info details for runtime
// routines.
class ScopeInfo : public FixedArray {
 public:
  DECLARE_CAST(ScopeInfo)

  // Return the type of this scope.
  ScopeType scope_type();

  // Does this scope call eval?
  bool CallsEval();

  // Return the language mode of this scope.
  LanguageMode language_mode();

  // True if this scope is a (var) declaration scope.
  bool is_declaration_scope();

  // Does this scope make a sloppy eval call?
  bool CallsSloppyEval() { return CallsEval() && is_sloppy(language_mode()); }

  // Return the total number of locals allocated on the stack and in the
  // context. This includes the parameters that are allocated in the context.
  int LocalCount();

  // Return the number of stack slots for code. This number consists of two
  // parts:
  //  1. One stack slot per stack allocated local.
  //  2. One stack slot for the function name if it is stack allocated.
  int StackSlotCount();

  // Return the number of context slots for code if a context is allocated. This
  // number consists of three parts:
  //  1. Size of fixed header for every context: Context::MIN_CONTEXT_SLOTS
  //  2. One context slot per context allocated local.
  //  3. One context slot for the function name if it is context allocated.
  // Parameters allocated in the context count as context allocated locals. If
  // no contexts are allocated for this scope ContextLength returns 0.
  int ContextLength();

  // Does this scope declare a "this" binding?
  bool HasReceiver();

  // Does this scope declare a "this" binding, and the "this" binding is stack-
  // or context-allocated?
  bool HasAllocatedReceiver();

  // Does this scope declare a "new.target" binding?
  bool HasNewTarget();

  // Is this scope the scope of a named function expression?
  bool HasFunctionName();

  // Return if this has context allocated locals.
  bool HasHeapAllocatedLocals();

  // Return if contexts are allocated for this scope.
  bool HasContext();

  // Return if this is a function scope with "use asm".
  inline bool IsAsmModule() { return AsmModuleField::decode(Flags()); }

  // Return if this is a nested function within an asm module scope.
  inline bool IsAsmFunction() { return AsmFunctionField::decode(Flags()); }

  inline bool HasSimpleParameters() {
    return HasSimpleParametersField::decode(Flags());
  }

  // Return the function_name if present.
  String* FunctionName();

  ModuleInfo* ModuleDescriptorInfo();

  // Return the name of the given parameter.
  String* ParameterName(int var);

  // Return the name of the given local.
  String* LocalName(int var);

  // Return the name of the given stack local.
  String* StackLocalName(int var);

  // Return the name of the given stack local.
  int StackLocalIndex(int var);

  // Return the name of the given context local.
  String* ContextLocalName(int var);

  // Return the mode of the given context local.
  VariableMode ContextLocalMode(int var);

  // Return the initialization flag of the given context local.
  InitializationFlag ContextLocalInitFlag(int var);

  // Return the initialization flag of the given context local.
  MaybeAssignedFlag ContextLocalMaybeAssignedFlag(int var);

  // Return true if this local was introduced by the compiler, and should not be
  // exposed to the user in a debugger.
  static bool VariableIsSynthetic(String* name);

  // Lookup support for serialized scope info. Returns the
  // the stack slot index for a given slot name if the slot is
  // present; otherwise returns a value < 0. The name must be an internalized
  // string.
  int StackSlotIndex(String* name);

  // Lookup support for serialized scope info. Returns the local context slot
  // index for a given slot name if the slot is present; otherwise
  // returns a value < 0. The name must be an internalized string.
  // If the slot is present and mode != NULL, sets *mode to the corresponding
  // mode for that variable.
  static int ContextSlotIndex(Handle<ScopeInfo> scope_info, Handle<String> name,
                              VariableMode* mode, InitializationFlag* init_flag,
                              MaybeAssignedFlag* maybe_assigned_flag);

  // Lookup metadata of a MODULE-allocated variable.  Return 0 if there is no
  // module variable with the given name (the index value of a MODULE variable
  // is never 0).
  int ModuleIndex(Handle<String> name, VariableMode* mode,
                  InitializationFlag* init_flag,
                  MaybeAssignedFlag* maybe_assigned_flag);

  // Lookup the name of a certain context slot by its index.
  String* ContextSlotName(int slot_index);

  // Lookup support for serialized scope info. Returns the
  // parameter index for a given parameter name if the parameter is present;
  // otherwise returns a value < 0. The name must be an internalized string.
  int ParameterIndex(String* name);

  // Lookup support for serialized scope info. Returns the function context
  // slot index if the function name is present and context-allocated (named
  // function expressions, only), otherwise returns a value < 0. The name
  // must be an internalized string.
  int FunctionContextSlotIndex(String* name);

  // Lookup support for serialized scope info.  Returns the receiver context
  // slot index if scope has a "this" binding, and the binding is
  // context-allocated.  Otherwise returns a value < 0.
  int ReceiverContextSlotIndex();

  FunctionKind function_kind();

  // Returns true if this ScopeInfo is linked to a outer ScopeInfo.
  bool HasOuterScopeInfo();

  // Returns true if this ScopeInfo was created for a debug-evaluate scope.
  bool IsDebugEvaluateScope();

  // Can be used to mark a ScopeInfo that looks like a with-scope as actually
  // being a debug-evaluate scope.
  void SetIsDebugEvaluateScope();

  // Return the outer ScopeInfo if present.
  ScopeInfo* OuterScopeInfo();

#ifdef DEBUG
  bool Equals(ScopeInfo* other) const;
#endif

  static Handle<ScopeInfo> Create(Isolate* isolate, Zone* zone, Scope* scope,
                                  MaybeHandle<ScopeInfo> outer_scope);
  static Handle<ScopeInfo> CreateForWithScope(
      Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope);
  static Handle<ScopeInfo> CreateGlobalThisBinding(Isolate* isolate);

  // Serializes empty scope info.
  V8_EXPORT_PRIVATE static ScopeInfo* Empty(Isolate* isolate);

#ifdef DEBUG
  void Print();
#endif

// The layout of the static part of a ScopeInfo is as follows. Each entry is
// numeric and occupies one array slot.
// 1. A set of properties of the scope.
// 2. The number of parameters. For non-function scopes this is 0.
// 3. The number of non-parameter variables allocated on the stack.
// 4. The number of non-parameter and parameter variables allocated in the
//    context.
#define FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(V) \
  V(Flags)                                   \
  V(ParameterCount)                          \
  V(StackLocalCount)                         \
  V(ContextLocalCount)

#define FIELD_ACCESSORS(name)                                             \
  inline void Set##name(int value) { set(k##name, Smi::FromInt(value)); } \
  inline int name() {                                                     \
    if (length() > 0) {                                                   \
      return Smi::cast(get(k##name))->value();                            \
    } else {                                                              \
      return 0;                                                           \
    }                                                                     \
  }

  FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
#undef FIELD_ACCESSORS

  enum {
#define DECL_INDEX(name) k##name,
    FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(DECL_INDEX)
#undef DECL_INDEX
        kVariablePartIndex
  };

 private:
  // The layout of the variable part of a ScopeInfo is as follows:
  // 1. ParameterNames:
  //    This part stores the names of the parameters for function scopes. One
  //    slot is used per parameter, so in total this part occupies
  //    ParameterCount() slots in the array. For other scopes than function
  //    scopes ParameterCount() is 0.
  // 2. StackLocalFirstSlot:
  //    Index of a first stack slot for stack local. Stack locals belonging to
  //    this scope are located on a stack at slots starting from this index.
  // 3. StackLocalNames:
  //    Contains the names of local variables that are allocated on the stack,
  //    in increasing order of the stack slot index. First local variable has a
  //    stack slot index defined in StackLocalFirstSlot (point 2 above).
  //    One slot is used per stack local, so in total this part occupies
  //    StackLocalCount() slots in the array.
  // 4. ContextLocalNames:
  //    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. One slot is used per
  //    context local, so in total this part occupies ContextLocalCount() slots
  //    in the array.
  // 5. ContextLocalInfos:
  //    Contains the variable modes and initialization flags corresponding to
  //    the context locals in ContextLocalNames. One slot is used per
  //    context local, so in total this part occupies ContextLocalCount()
  //    slots in the array.
  // 6. ReceiverInfo:
  //    If the scope binds a "this" value, one slot is reserved to hold the
  //    context or stack slot index for the variable.
  // 7. FunctionNameInfo:
  //    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.
  // 8. OuterScopeInfoIndex:
  //    The outer scope's ScopeInfo or the hole if there's none.
  // 9. ModuleInfo, ModuleVariableCount, and ModuleVariables:
  //    For a module scope, this part contains the ModuleInfo, the number of
  //    MODULE-allocated variables, and the metadata of those variables.  For
  //    non-module scopes it is empty.
  int ParameterNamesIndex();
  int StackLocalFirstSlotIndex();
  int StackLocalNamesIndex();
  int ContextLocalNamesIndex();
  int ContextLocalInfosIndex();
  int ReceiverInfoIndex();
  int FunctionNameInfoIndex();
  int OuterScopeInfoIndex();
  int ModuleInfoIndex();
  int ModuleVariableCountIndex();
  int ModuleVariablesIndex();

  int Lookup(Handle<String> name, int start, int end, VariableMode* mode,
             VariableLocation* location, InitializationFlag* init_flag,
             MaybeAssignedFlag* maybe_assigned_flag);

  // Get metadata of i-th MODULE-allocated variable, where 0 <= i <
  // ModuleVariableCount.  The metadata is returned via out-arguments, which may
  // be nullptr if the corresponding information is not requested
  void ModuleVariable(int i, String** name, int* index,
                      VariableMode* mode = nullptr,
                      InitializationFlag* init_flag = nullptr,
                      MaybeAssignedFlag* maybe_assigned_flag = nullptr);

  // Used for the function name variable for named function expressions, and for
  // the receiver.
  enum VariableAllocationInfo { NONE, STACK, CONTEXT, UNUSED };

  // Properties of scopes.
  class ScopeTypeField : public BitField<ScopeType, 0, 4> {};
  class CallsEvalField : public BitField<bool, ScopeTypeField::kNext, 1> {};
  STATIC_ASSERT(LANGUAGE_END == 2);
  class LanguageModeField
      : public BitField<LanguageMode, CallsEvalField::kNext, 1> {};
  class DeclarationScopeField
      : public BitField<bool, LanguageModeField::kNext, 1> {};
  class ReceiverVariableField
      : public BitField<VariableAllocationInfo, DeclarationScopeField::kNext,
                        2> {};
  class HasNewTargetField
      : public BitField<bool, ReceiverVariableField::kNext, 1> {};
  class FunctionVariableField
      : public BitField<VariableAllocationInfo, HasNewTargetField::kNext, 2> {};
  class AsmModuleField
      : public BitField<bool, FunctionVariableField::kNext, 1> {};
  class AsmFunctionField : public BitField<bool, AsmModuleField::kNext, 1> {};
  class HasSimpleParametersField
      : public BitField<bool, AsmFunctionField::kNext, 1> {};
  class FunctionKindField
      : public BitField<FunctionKind, HasSimpleParametersField::kNext, 10> {};
  class HasOuterScopeInfoField
      : public BitField<bool, FunctionKindField::kNext, 1> {};
  class IsDebugEvaluateScopeField
      : public BitField<bool, HasOuterScopeInfoField::kNext, 1> {};

  // Properties of variables.
  class VariableModeField : public BitField<VariableMode, 0, 3> {};
  class InitFlagField : public BitField<InitializationFlag, 3, 1> {};
  class MaybeAssignedFlagField : public BitField<MaybeAssignedFlag, 4, 1> {};

  friend class ScopeIterator;
};

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_SCOPE_INFO_H_