• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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 #ifndef V8_OBJECTS_SCOPE_INFO_H_
6 #define V8_OBJECTS_SCOPE_INFO_H_
7 
8 #include "src/common/globals.h"
9 #include "src/objects/fixed-array.h"
10 #include "src/objects/function-kind.h"
11 #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 // Has to be the last include (doesn't have include guards):
17 #include "src/objects/object-macros.h"
18 
19 namespace v8 {
20 namespace internal {
21 
22 // scope-info-tq.inc uses NameToIndexHashTable.
23 class NameToIndexHashTable;
24 
25 #include "torque-generated/src/objects/scope-info-tq.inc"
26 
27 template <typename T>
28 class Handle;
29 class Isolate;
30 template <typename T>
31 class MaybeHandle;
32 class SourceTextModuleInfo;
33 class Scope;
34 class StringSet;
35 class Zone;
36 
37 struct VariableLookupResult {
38   int context_index;
39   int slot_index;
40   // repl_mode flag is needed to disable inlining of 'const' variables in REPL
41   // mode.
42   bool is_repl_mode;
43   IsStaticFlag is_static_flag;
44   VariableMode mode;
45   InitializationFlag init_flag;
46   MaybeAssignedFlag maybe_assigned_flag;
47 };
48 
49 // ScopeInfo represents information about different scopes of a source
50 // program  and the allocation of the scope's variables. Scope information
51 // is stored in a compressed form in ScopeInfo objects and is used
52 // at runtime (stack dumps, deoptimization, etc.).
53 
54 // This object provides quick access to scope info details for runtime
55 // routines.
56 class ScopeInfo : public TorqueGeneratedScopeInfo<ScopeInfo, HeapObject> {
57  public:
58   DEFINE_TORQUE_GENERATED_SCOPE_FLAGS()
59 
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   // Return the number of context slots for code if a context is allocated. This
76   // number consists of three parts:
77   //  1. Size of header for every context.
78   //  2. One context slot per context allocated local.
79   //  3. One context slot for the function name if it is context allocated.
80   // Parameters allocated in the context count as context allocated locals. If
81   // no contexts are allocated for this scope ContextLength returns 0.
82   int ContextLength() const;
83   int ContextHeaderLength() const;
84 
85   bool HasContextExtensionSlot() const;
86 
87   // Does this scope declare a "this" binding?
88   bool HasReceiver() const;
89 
90   // Does this scope declare a "this" binding, and the "this" binding is stack-
91   // or context-allocated?
92   bool HasAllocatedReceiver() const;
93 
94   // Does this scope has class brand (for private methods)? If it's a class
95   // scope, this indicates whether the class has a private brand. If it's a
96   // constructor scope, this indicates whther it needs to initialize the
97   // brand.
98   bool ClassScopeHasPrivateBrand() const;
99 
100   // Does this scope contain a saved class variable for checking receivers of
101   // static private methods?
102   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   bool HasContextAllocatedFunctionName() const;
111 
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   // Does this scope belong to a function?
121   bool HasPositionInfo() const;
122 
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   // The function's name if it is non-empty, otherwise the inferred name or an
135   // empty string.
136   String FunctionDebugName() const;
137 
138   // Return the function's inferred name if present.
139   // See SharedFunctionInfo::function_identifier.
140   V8_EXPORT_PRIVATE Object InferredFunctionName() const;
141 
142   // Position information accessors.
143   int StartPosition() const;
144   int EndPosition() const;
145   void SetPositionInfo(int start, int end);
146 
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       Handle<ScopeInfo> scope_info);
157 
158   static inline LocalNamesRange<ScopeInfo*> IterateLocalNames(
159       ScopeInfo* scope_info, const DisallowGarbageCollection& no_gc);
160 
161   // Return the name of a given context local.
162   // It should only be used if inlined local names.
163   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   // Return whether the given context local variable is static.
170   IsStaticFlag ContextLocalIsStaticFlag(int var) const;
171 
172   // Return the initialization flag of the given context local.
173   InitializationFlag ContextLocalInitFlag(int var) const;
174 
175   bool ContextLocalIsParameter(int var) const;
176   uint32_t ContextLocalParameterNumber(int var) const;
177 
178   // Return the initialization flag of the given context local.
179   MaybeAssignedFlag ContextLocalMaybeAssignedFlag(int var) const;
180 
181   // Return true if this local was introduced by the compiler, and should not be
182   // exposed to the user in a debugger.
183   static bool VariableIsSynthetic(String name);
184 
185   // Lookup support for serialized scope info. Returns the local context slot
186   // index for a given slot name if the slot is present; otherwise
187   // 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   int ContextSlotIndex(Handle<String> name);
191   int ContextSlotIndex(Handle<String> name,
192                        VariableLookupResult* lookup_result);
193 
194   // Lookup metadata of a MODULE-allocated variable.  Return 0 if there is no
195   // module variable with the given name (the index value of a MODULE variable
196   // is never 0).
197   int ModuleIndex(String name, VariableMode* mode,
198                   InitializationFlag* init_flag,
199                   MaybeAssignedFlag* maybe_assigned_flag);
200 
201   int ModuleVariableCount() const;
202 
203   // Lookup support for serialized scope info. Returns the function context
204   // slot index if the function name is present and context-allocated (named
205   // function expressions, only), otherwise returns a value < 0. The name
206   // must be an internalized string.
207   int FunctionContextSlotIndex(String name) const;
208 
209   // Lookup support for serialized scope info.  Returns the receiver context
210   // slot index if scope has a "this" binding, and the binding is
211   // context-allocated.  Otherwise returns a value < 0.
212   int ReceiverContextSlotIndex() const;
213 
214   // Returns the first parameter context slot index.
215   int ParametersStartIndex() const;
216 
217   // Lookup support for serialized scope info.  Returns the name and index of
218   // 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   // Can be used to mark a ScopeInfo that looks like a with-scope as actually
231   // being a debug-evaluate scope.
232   void SetIsDebugEvaluateScope();
233 
234   // Return the outer ScopeInfo if present.
235   ScopeInfo OuterScopeInfo() const;
236 
237   bool is_script_scope() const;
238 
239   // Returns true if this ScopeInfo has a blocklist attached containing stack
240   // allocated local variables.
241   V8_EXPORT_PRIVATE bool HasLocalsBlockList() const;
242   // Returns a list of stack-allocated locals of parent scopes.
243   // Used during local debug-evalute to decide whether a context lookup
244   // can continue upwards after checking this scope.
245   V8_EXPORT_PRIVATE StringSet LocalsBlockList() const;
246 
247   // Returns true if this ScopeInfo was created for a scope that skips the
248   // closest outer class when resolving private names.
249   bool PrivateNameLookupSkipsOuterClass() const;
250 
251   // REPL mode scopes allow re-declaraction of let and const variables. They
252   // come from debug evaluate but are different to IsDebugEvaluateScope().
253   bool IsReplModeScope() const;
254 
255 #ifdef DEBUG
256   bool Equals(ScopeInfo other) const;
257 #endif
258 
259   template <typename IsolateT>
260   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   V8_EXPORT_PRIVATE static Handle<ScopeInfo> CreateForEmptyFunction(
265       Isolate* isolate);
266   static Handle<ScopeInfo> CreateForNativeContext(Isolate* isolate);
267   static Handle<ScopeInfo> CreateGlobalThisBinding(Isolate* isolate);
268 
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
271   // for a blocklist reserved.
272   V8_EXPORT_PRIVATE static Handle<ScopeInfo> RecreateWithBlockList(
273       Isolate* isolate, Handle<ScopeInfo> original,
274       Handle<StringSet> blocklist);
275 
276   // Serializes empty scope info.
277   V8_EXPORT_PRIVATE static ScopeInfo Empty(Isolate* isolate);
278 
279 #define FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(V) \
280   V(Flags)                                   \
281   V(ParameterCount)                          \
282   V(ContextLocalCount)
283 
284 #define FIELD_ACCESSORS(name)       \
285   inline int name() const;
286   FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
287 #undef FIELD_ACCESSORS
288 
289   enum Fields {
290 #define DECL_INDEX(name) k##name,
291     FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(DECL_INDEX)
292 #undef DECL_INDEX
293         kVariablePartIndex
294   };
295 
296   STATIC_ASSERT(LanguageModeSize == 1 << LanguageModeBit::kSize);
297   STATIC_ASSERT(FunctionKind::kLastFunctionKind <= FunctionKindBits::kMax);
298 
299   bool IsEmpty() const;
300 
301   // Returns the size in bytes for a ScopeInfo with |length| slots.
SizeFor(int length)302   static constexpr int SizeFor(int length) { return OffsetOfElementAt(length); }
303 
304   // Gives access to raw memory which stores the ScopeInfo's data.
305   inline ObjectSlot data_start();
306 
307  private:
308   friend class WebSnapshotDeserializer;
309 
310   int InlinedLocalNamesLookup(String name);
311 
312   int ContextLocalNamesIndex() const;
313   int ContextLocalInfosIndex() const;
314   int SavedClassVariableInfoIndex() const;
315   int FunctionVariableInfoIndex() const;
316   int InferredFunctionNameIndex() const;
317   int PositionInfoIndex() const;
318   int OuterScopeInfoIndex() const;
319   V8_EXPORT_PRIVATE int LocalsBlockListIndex() const;
320   int ModuleInfoIndex() const;
321   int ModuleVariableCountIndex() const;
322   int ModuleVariablesIndex() const;
323 
324   static bool NeedsPositionInfo(ScopeType type);
325 
326   // Raw access by slot index. These functions rely on the fact that everything
327   // in ScopeInfo is tagged. Each slot is tagged-pointer sized. Slot 0 is
328   // 'flags', the first field defined by ScopeInfo after the standard-size
329   // HeapObject header.
330   V8_EXPORT_PRIVATE Object get(int index) const;
331   Object get(PtrComprCageBase cage_base, int index) const;
332   // Setter that doesn't need write barrier.
333   void set(int index, Smi value);
334   // Setter with explicit barrier mode.
335   void set(int index, Object value,
336            WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
337   void CopyElements(Isolate* isolate, int dst_index, ScopeInfo src,
338                     int src_index, int len, WriteBarrierMode mode);
339   ObjectSlot RawFieldOfElementAt(int index);
340   // The number of tagged-pointer-sized slots in the ScopeInfo after its
341   // standard HeapObject header.
342   V8_EXPORT_PRIVATE int length() const;
343 
344   // Conversions between offset (bytes from the beginning of the object) and
345   // index (number of tagged-pointer-sized slots starting after the standard
346   // HeapObject header).
OffsetOfElementAt(int index)347   static constexpr int OffsetOfElementAt(int index) {
348     return HeapObject::kHeaderSize + index * kTaggedSize;
349   }
ConvertOffsetToIndex(int offset)350   static constexpr int ConvertOffsetToIndex(int offset) {
351     int index = (offset - HeapObject::kHeaderSize) / kTaggedSize;
352     DCHECK_EQ(OffsetOfElementAt(index), offset);
353     return index;
354   }
355 
356   enum class BootstrappingType { kScript, kFunction, kNative };
357   static Handle<ScopeInfo> CreateForBootstrapping(Isolate* isolate,
358                                                   BootstrappingType type);
359 
360   int Lookup(Handle<String> name, int start, int end, VariableMode* mode,
361              VariableLocation* location, InitializationFlag* init_flag,
362              MaybeAssignedFlag* maybe_assigned_flag);
363 
364   // Get metadata of i-th MODULE-allocated variable, where 0 <= i <
365   // ModuleVariableCount.  The metadata is returned via out-arguments, which may
366   // be nullptr if the corresponding information is not requested
367   void ModuleVariable(int i, String* name, int* index,
368                       VariableMode* mode = nullptr,
369                       InitializationFlag* init_flag = nullptr,
370                       MaybeAssignedFlag* maybe_assigned_flag = nullptr);
371 
372   static const int kFunctionNameEntries =
373       TorqueGeneratedFunctionVariableInfoOffsets::kSize / kTaggedSize;
374   static const int kPositionInfoEntries =
375       TorqueGeneratedPositionInfoOffsets::kSize / kTaggedSize;
376   static const int kModuleVariableEntryLength =
377       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)
386   FRIEND_TEST(TestWithNativeContext, RecreateScopeInfoWithLocalsBlocklistWorks);
387 };
388 
389 std::ostream& operator<<(std::ostream& os, VariableAllocationInfo var);
390 
391 }  // namespace internal
392 }  // namespace v8
393 
394 #include "src/objects/object-macros-undef.h"
395 
396 #endif  // V8_OBJECTS_SCOPE_INFO_H_
397