scope-info.h 14.4 KB
Newer Older
1 2 3 4 5 6 7
// 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_

8
#include "src/common/globals.h"
9
#include "src/objects/fixed-array.h"
10 11
#include "src/objects/function-kind.h"
#include "src/objects/objects.h"
12
#include "src/utils/utils.h"
13
#include "testing/gtest/include/gtest/gtest_prod.h"  // nogncheck
14
#include "torque-generated/bit-fields.h"
15

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

19 20 21
namespace v8 {
namespace internal {

22 23 24
// scope-info-tq.inc uses NameToIndexHashTable.
class NameToIndexHashTable;

25 26
#include "torque-generated/src/objects/scope-info-tq.inc"

marja's avatar
marja committed
27 28
template <typename T>
class Handle;
29
class Isolate;
marja's avatar
marja committed
30 31
template <typename T>
class MaybeHandle;
32
class SourceTextModuleInfo;
33
class Scope;
34
class StringSet;
35 36
class Zone;

37 38 39 40 41 42 43 44 45 46 47 48
struct VariableLookupResult {
  int context_index;
  int slot_index;
  // repl_mode flag is needed to disable inlining of 'const' variables in REPL
  // mode.
  bool is_repl_mode;
  IsStaticFlag is_static_flag;
  VariableMode mode;
  InitializationFlag init_flag;
  MaybeAssignedFlag maybe_assigned_flag;
};

49 50 51 52 53 54 55
// 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.
56
class ScopeInfo : public TorqueGeneratedScopeInfo<ScopeInfo, HeapObject> {
57
 public:
58 59
  DEFINE_TORQUE_GENERATED_SCOPE_FLAGS()

60
  DECL_PRINTER(ScopeInfo)
61
  class BodyDescriptor;
62 63

  // Return the type of this scope.
64
  ScopeType scope_type() const;
65 66

  // Return the language mode of this scope.
67
  LanguageMode language_mode() const;
68 69

  // True if this scope is a (var) declaration scope.
70
  bool is_declaration_scope() const;
71 72

  // Does this scope make a sloppy eval call?
73
  bool SloppyEvalCanExtendVars() const;
74 75 76

  // Return the number of context slots for code if a context is allocated. This
  // number consists of three parts:
77
  //  1. Size of header for every context.
78 79 80 81
  //  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.
82
  int ContextLength() const;
83
  int ContextHeaderLength() const;
84

85 86
  bool HasContextExtensionSlot() const;

87
  // Does this scope declare a "this" binding?
88
  bool HasReceiver() const;
89 90 91

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

94 95 96 97 98
  // Does this scope has class brand (for private methods)? If it's a class
  // scope, this indicates whether the class has a private brand. If it's a
  // constructor scope, this indicates whther it needs to initialize the
  // brand.
  bool ClassScopeHasPrivateBrand() const;
99

100 101 102
  // Does this scope contain a saved class variable for checking receivers of
  // static private methods?
  bool HasSavedClassVariable() const;
103

104
  // Does this scope declare a "new.target" binding?
105
  bool HasNewTarget() const;
106 107

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

110 111
  bool HasContextAllocatedFunctionName() const;

112
  // See SharedFunctionInfo::HasSharedName.
113
  V8_EXPORT_PRIVATE bool HasSharedFunctionName() const;
114

115
  V8_EXPORT_PRIVATE bool HasInferredFunctionName() const;
116

117
  void SetFunctionName(Object name);
118
  void SetInferredFunctionName(String name);
119

120 121 122
  // Does this scope belong to a function?
  bool HasPositionInfo() const;

123
  // Return if contexts are allocated for this scope.
124
  bool HasContext() const;
125 126

  // Return if this is a function scope with "use asm".
127
  inline bool IsAsmModule() const;
128

129
  inline bool HasSimpleParameters() const;
130 131

  // Return the function_name if present.
132
  V8_EXPORT_PRIVATE Object FunctionName() const;
133

134 135
  // The function's name if it is non-empty, otherwise the inferred name or an
  // empty string.
136
  String FunctionDebugName() const;
137

138 139
  // Return the function's inferred name if present.
  // See SharedFunctionInfo::function_identifier.
140
  V8_EXPORT_PRIVATE Object InferredFunctionName() const;
141

142
  // Position information accessors.
143 144
  int StartPosition() const;
  int EndPosition() const;
145 146
  void SetPositionInfo(int start, int end);

147
  SourceTextModuleInfo ModuleDescriptorInfo() const;
148

149
  // Return true if the local names are inlined in the scope info object.
150
  inline bool HasInlinedLocalNames() const;
151

152
  template <typename ScopeInfoPtr>
153
  class LocalNamesRange;
154

155
  static inline LocalNamesRange<Handle<ScopeInfo>> IterateLocalNames(
156 157
      Handle<ScopeInfo> scope_info);

158
  static inline LocalNamesRange<ScopeInfo*> IterateLocalNames(
159 160 161 162 163
      ScopeInfo* scope_info, const DisallowGarbageCollection& no_gc);

  // Return the name of a given context local.
  // It should only be used if inlined local names.
  String ContextInlinedLocalName(int var) const;
164
  String ContextInlinedLocalName(PtrComprCageBase cage_base, int var) const;
165 166

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

169 170 171
  // Return whether the given context local variable is static.
  IsStaticFlag ContextLocalIsStaticFlag(int var) const;

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

175 176 177
  bool ContextLocalIsParameter(int var) const;
  uint32_t ContextLocalParameterNumber(int var) const;

178
  // Return the initialization flag of the given context local.
179
  MaybeAssignedFlag ContextLocalMaybeAssignedFlag(int var) const;
180 181 182

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

  // 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.
188
  // If the slot is present and mode != nullptr, sets *mode to the corresponding
189
  // mode for that variable.
190 191 192
  int ContextSlotIndex(Handle<String> name);
  int ContextSlotIndex(Handle<String> name,
                       VariableLookupResult* lookup_result);
193 194 195 196

  // 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).
197
  int ModuleIndex(String name, VariableMode* mode,
198 199 200
                  InitializationFlag* init_flag,
                  MaybeAssignedFlag* maybe_assigned_flag);

201 202
  int ModuleVariableCount() const;

203 204 205 206
  // 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.
207
  int FunctionContextSlotIndex(String name) const;
208 209 210 211

  // 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.
212
  int ReceiverContextSlotIndex() const;
213

214 215 216
  // Returns the first parameter context slot index.
  int ParametersStartIndex() const;

217 218
  // Lookup support for serialized scope info.  Returns the name and index of
  // the saved class variable in context local slots if scope is a class scope
219
  // and it contains static private methods that may be accessed.
220
  std::pair<String, int> SavedClassVariable() const;
221

222
  FunctionKind function_kind() const;
223 224

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

  // Returns true if this ScopeInfo was created for a debug-evaluate scope.
228
  bool IsDebugEvaluateScope() const;
229 230 231 232 233 234

  // 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.
235
  ScopeInfo OuterScopeInfo() const;
236

237 238
  bool is_script_scope() const;

Dan Elphick's avatar
Dan Elphick committed
239 240 241
  // Returns true if this ScopeInfo has a blocklist attached containing stack
  // allocated local variables.
  V8_EXPORT_PRIVATE bool HasLocalsBlockList() const;
242 243 244
  // Returns a list of stack-allocated locals of parent scopes.
  // Used during local debug-evalute to decide whether a context lookup
  // can continue upwards after checking this scope.
Dan Elphick's avatar
Dan Elphick committed
245
  V8_EXPORT_PRIVATE StringSet LocalsBlockList() const;
246

247 248 249 250
  // Returns true if this ScopeInfo was created for a scope that skips the
  // closest outer class when resolving private names.
  bool PrivateNameLookupSkipsOuterClass() const;

251 252
  // REPL mode scopes allow re-declaraction of let and const variables. They
  // come from debug evaluate but are different to IsDebugEvaluateScope().
Simon Zünd's avatar
Simon Zünd committed
253 254
  bool IsReplModeScope() const;

255
#ifdef DEBUG
256
  bool Equals(ScopeInfo other) const;
257 258
#endif

259 260
  template <typename IsolateT>
  static Handle<ScopeInfo> Create(IsolateT* isolate, Zone* zone, Scope* scope,
261
                                  MaybeHandle<ScopeInfo> outer_scope);
262
  V8_EXPORT_PRIVATE static Handle<ScopeInfo> CreateForWithScope(
263
      Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope);
264 265
  V8_EXPORT_PRIVATE static Handle<ScopeInfo> CreateForEmptyFunction(
      Isolate* isolate);
266
  static Handle<ScopeInfo> CreateForNativeContext(Isolate* isolate);
267 268
  static Handle<ScopeInfo> CreateGlobalThisBinding(Isolate* isolate);

Dan Elphick's avatar
Dan Elphick committed
269
  // Creates a copy of a {ScopeInfo} but with the provided locals blocklist
270
  // attached. Does nothing if the original {ScopeInfo} already has a field
Dan Elphick's avatar
Dan Elphick committed
271 272
  // for a blocklist reserved.
  V8_EXPORT_PRIVATE static Handle<ScopeInfo> RecreateWithBlockList(
273
      Isolate* isolate, Handle<ScopeInfo> original,
Dan Elphick's avatar
Dan Elphick committed
274
      Handle<StringSet> blocklist);
275

276
  // Serializes empty scope info.
277
  V8_EXPORT_PRIVATE static ScopeInfo Empty(Isolate* isolate);
278 279 280 281 282 283

#define FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(V) \
  V(Flags)                                   \
  V(ParameterCount)                          \
  V(ContextLocalCount)

284
#define FIELD_ACCESSORS(name)       \
285
  inline int name() const;
286 287 288
  FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
#undef FIELD_ACCESSORS

289
  enum Fields {
290 291 292 293 294 295
#define DECL_INDEX(name) k##name,
    FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(DECL_INDEX)
#undef DECL_INDEX
        kVariablePartIndex
  };

296
  STATIC_ASSERT(LanguageModeSize == 1 << LanguageModeBit::kSize);
297
  STATIC_ASSERT(FunctionKind::kLastFunctionKind <= FunctionKindBits::kMax);
298

299 300
  bool IsEmpty() const;

301 302 303 304 305 306
  // Returns the size in bytes for a ScopeInfo with |length| slots.
  static constexpr int SizeFor(int length) { return OffsetOfElementAt(length); }

  // Gives access to raw memory which stores the ScopeInfo's data.
  inline ObjectSlot data_start();

307
 private:
308 309
  friend class WebSnapshotDeserializer;

310 311
  int InlinedLocalNamesLookup(String name);

312 313
  int ContextLocalNamesIndex() const;
  int ContextLocalInfosIndex() const;
314
  int SavedClassVariableInfoIndex() const;
315
  int FunctionVariableInfoIndex() const;
316
  int InferredFunctionNameIndex() const;
317
  int PositionInfoIndex() const;
318
  int OuterScopeInfoIndex() const;
Dan Elphick's avatar
Dan Elphick committed
319
  V8_EXPORT_PRIVATE int LocalsBlockListIndex() const;
320 321 322
  int ModuleInfoIndex() const;
  int ModuleVariableCountIndex() const;
  int ModuleVariablesIndex() const;
323

324
  static bool NeedsPositionInfo(ScopeType type);
325

326 327 328 329 330
  // Raw access by slot index. These functions rely on the fact that everything
  // in ScopeInfo is tagged. Each slot is tagged-pointer sized. Slot 0 is
  // 'flags', the first field defined by ScopeInfo after the standard-size
  // HeapObject header.
  V8_EXPORT_PRIVATE Object get(int index) const;
331
  Object get(PtrComprCageBase cage_base, int index) const;
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
  // Setter that doesn't need write barrier.
  void set(int index, Smi value);
  // Setter with explicit barrier mode.
  void set(int index, Object value,
           WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
  void CopyElements(Isolate* isolate, int dst_index, ScopeInfo src,
                    int src_index, int len, WriteBarrierMode mode);
  ObjectSlot RawFieldOfElementAt(int index);
  // The number of tagged-pointer-sized slots in the ScopeInfo after its
  // standard HeapObject header.
  V8_EXPORT_PRIVATE int length() const;

  // Conversions between offset (bytes from the beginning of the object) and
  // index (number of tagged-pointer-sized slots starting after the standard
  // HeapObject header).
  static constexpr int OffsetOfElementAt(int index) {
348
    return HeapObject::kHeaderSize + index * kTaggedSize;
349
  }
350
  static constexpr int ConvertOffsetToIndex(int offset) {
351
    int index = (offset - HeapObject::kHeaderSize) / kTaggedSize;
352
    DCHECK_EQ(OffsetOfElementAt(index), offset);
353 354 355
    return index;
  }

356
  enum class BootstrappingType { kScript, kFunction, kNative };
357
  static Handle<ScopeInfo> CreateForBootstrapping(Isolate* isolate,
358
                                                  BootstrappingType type);
359

360 361 362 363 364 365 366
  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
367
  void ModuleVariable(int i, String* name, int* index,
368 369 370 371
                      VariableMode* mode = nullptr,
                      InitializationFlag* init_flag = nullptr,
                      MaybeAssignedFlag* maybe_assigned_flag = nullptr);

372 373 374 375 376 377
  static const int kFunctionNameEntries =
      TorqueGeneratedFunctionVariableInfoOffsets::kSize / kTaggedSize;
  static const int kPositionInfoEntries =
      TorqueGeneratedPositionInfoOffsets::kSize / kTaggedSize;
  static const int kModuleVariableEntryLength =
      TorqueGeneratedModuleVariableOffsets::kSize / kTaggedSize;
378

379
  // Properties of variables.
380
  DEFINE_TORQUE_GENERATED_VARIABLE_PROPERTIES()
381 382

  friend class ScopeIterator;
383
  friend std::ostream& operator<<(std::ostream& os, VariableAllocationInfo var);
384

385
  TQ_OBJECT_CONSTRUCTORS(ScopeInfo)
Dan Elphick's avatar
Dan Elphick committed
386
  FRIEND_TEST(TestWithNativeContext, RecreateScopeInfoWithLocalsBlocklistWorks);
387 388
};

389
std::ostream& operator<<(std::ostream& os, VariableAllocationInfo var);
390

391 392 393 394 395 396
}  // namespace internal
}  // namespace v8

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

#endif  // V8_OBJECTS_SCOPE_INFO_H_