• 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 template <typename T>
23 class Handle;
24 class Isolate;
25 template <typename T>
26 class MaybeHandle;
27 class SourceTextModuleInfo;
28 class Scope;
29 class StringSet;
30 class Zone;
31 
32 // ScopeInfo represents information about different scopes of a source
33 // program  and the allocation of the scope's variables. Scope information
34 // is stored in a compressed form in ScopeInfo objects and is used
35 // at runtime (stack dumps, deoptimization, etc.).
36 
37 // This object provides quick access to scope info details for runtime
38 // routines.
39 class ScopeInfo : public FixedArray {
40  public:
41   DEFINE_TORQUE_GENERATED_SCOPE_FLAGS()
42 
43   DECL_CAST(ScopeInfo)
44   DECL_PRINTER(ScopeInfo)
45 
46   // Return the type of this scope.
47   ScopeType scope_type() const;
48 
49   // Return the language mode of this scope.
50   LanguageMode language_mode() const;
51 
52   // True if this scope is a (var) declaration scope.
53   bool is_declaration_scope() const;
54 
55   // True if this scope is a class scope.
56   bool is_class_scope() const;
57 
58   // Does this scope make a sloppy eval call?
59   bool SloppyEvalCanExtendVars() const;
60 
61   // Return the number of context slots for code if a context is allocated. This
62   // number consists of three parts:
63   //  1. Size of header for every context.
64   //  2. One context slot per context allocated local.
65   //  3. One context slot for the function name if it is context allocated.
66   // Parameters allocated in the context count as context allocated locals. If
67   // no contexts are allocated for this scope ContextLength returns 0.
68   int ContextLength() const;
69   int ContextHeaderLength() const;
70 
71   bool HasContextExtensionSlot() const;
72 
73   // Does this scope declare a "this" binding?
74   bool HasReceiver() const;
75 
76   // Does this scope declare a "this" binding, and the "this" binding is stack-
77   // or context-allocated?
78   bool HasAllocatedReceiver() const;
79 
80   // Does this scope has class brand (for private methods)?
81   bool HasClassBrand() const;
82 
83   // Does this scope contains a saved class variable context local slot index
84   // for checking receivers of static private methods?
85   bool HasSavedClassVariableIndex() const;
86 
87   // Does this scope declare a "new.target" binding?
88   bool HasNewTarget() const;
89 
90   // Is this scope the scope of a named function expression?
91   V8_EXPORT_PRIVATE bool HasFunctionName() const;
92 
93   // See SharedFunctionInfo::HasSharedName.
94   V8_EXPORT_PRIVATE bool HasSharedFunctionName() const;
95 
96   V8_EXPORT_PRIVATE bool HasInferredFunctionName() const;
97 
98   void SetFunctionName(Object name);
99   void SetInferredFunctionName(String name);
100 
101   // Does this scope belong to a function?
102   bool HasPositionInfo() const;
103 
104   // Return if contexts are allocated for this scope.
105   bool HasContext() const;
106 
107   // Return if this is a function scope with "use asm".
108   inline bool IsAsmModule() const;
109 
110   inline bool HasSimpleParameters() const;
111 
112   // Return the function_name if present.
113   V8_EXPORT_PRIVATE Object FunctionName() const;
114 
115   // The function's name if it is non-empty, otherwise the inferred name or an
116   // empty string.
117   String FunctionDebugName() const;
118 
119   // Return the function's inferred name if present.
120   // See SharedFunctionInfo::function_identifier.
121   V8_EXPORT_PRIVATE Object InferredFunctionName() const;
122 
123   // Position information accessors.
124   int StartPosition() const;
125   int EndPosition() const;
126   void SetPositionInfo(int start, int end);
127 
128   SourceTextModuleInfo ModuleDescriptorInfo() const;
129 
130   // Return the name of the given context local.
131   String ContextLocalName(int var) const;
132 
133   // Return the mode of the given context local.
134   VariableMode ContextLocalMode(int var) const;
135 
136   // Return whether the given context local variable is static.
137   IsStaticFlag ContextLocalIsStaticFlag(int var) const;
138 
139   // Return the initialization flag of the given context local.
140   InitializationFlag ContextLocalInitFlag(int var) const;
141 
142   bool ContextLocalIsParameter(int var) const;
143   uint32_t ContextLocalParameterNumber(int var) const;
144 
145   // Return the initialization flag of the given context local.
146   MaybeAssignedFlag ContextLocalMaybeAssignedFlag(int var) const;
147 
148   // Return true if this local was introduced by the compiler, and should not be
149   // exposed to the user in a debugger.
150   static bool VariableIsSynthetic(String name);
151 
152   // Lookup support for serialized scope info. Returns the local context slot
153   // index for a given slot name if the slot is present; otherwise
154   // returns a value < 0. The name must be an internalized string.
155   // If the slot is present and mode != nullptr, sets *mode to the corresponding
156   // mode for that variable.
157   static int ContextSlotIndex(ScopeInfo scope_info, String name,
158                               VariableMode* mode, InitializationFlag* init_flag,
159                               MaybeAssignedFlag* maybe_assigned_flag,
160                               IsStaticFlag* is_static_flag);
161 
162   // Lookup metadata of a MODULE-allocated variable.  Return 0 if there is no
163   // module variable with the given name (the index value of a MODULE variable
164   // is never 0).
165   int ModuleIndex(String name, VariableMode* mode,
166                   InitializationFlag* init_flag,
167                   MaybeAssignedFlag* maybe_assigned_flag);
168 
169   // Lookup support for serialized scope info. Returns the function context
170   // slot index if the function name is present and context-allocated (named
171   // function expressions, only), otherwise returns a value < 0. The name
172   // must be an internalized string.
173   int FunctionContextSlotIndex(String name) const;
174 
175   // Lookup support for serialized scope info.  Returns the receiver context
176   // slot index if scope has a "this" binding, and the binding is
177   // context-allocated.  Otherwise returns a value < 0.
178   int ReceiverContextSlotIndex() const;
179 
180   // Lookup support for serialized scope info.  Returns the index of the
181   // saved class variable in context local slots if scope is a class scope
182   // and it contains static private methods that may be accessed.
183   // Otherwise returns a value < 0.
184   int SavedClassVariableContextLocalIndex() const;
185 
186   FunctionKind function_kind() const;
187 
188   // Returns true if this ScopeInfo is linked to a outer ScopeInfo.
189   bool HasOuterScopeInfo() const;
190 
191   // Returns true if this ScopeInfo was created for a debug-evaluate scope.
192   bool IsDebugEvaluateScope() const;
193 
194   // Can be used to mark a ScopeInfo that looks like a with-scope as actually
195   // being a debug-evaluate scope.
196   void SetIsDebugEvaluateScope();
197 
198   // Return the outer ScopeInfo if present.
199   ScopeInfo OuterScopeInfo() const;
200 
201   bool is_script_scope() const;
202 
203   // Returns true if this ScopeInfo has a blocklist attached containing stack
204   // allocated local variables.
205   V8_EXPORT_PRIVATE bool HasLocalsBlockList() const;
206   // Returns a list of stack-allocated locals of parent scopes.
207   // Used during local debug-evalute to decide whether a context lookup
208   // can continue upwards after checking this scope.
209   V8_EXPORT_PRIVATE StringSet LocalsBlockList() const;
210 
211   // Returns true if this ScopeInfo was created for a scope that skips the
212   // closest outer class when resolving private names.
213   bool PrivateNameLookupSkipsOuterClass() const;
214 
215   // REPL mode scopes allow re-declaraction of let variables. They come from
216   // debug evaluate but are different to IsDebugEvaluateScope().
217   bool IsReplModeScope() const;
218 
219 #ifdef DEBUG
220   bool Equals(ScopeInfo other) const;
221 #endif
222 
223   template <typename LocalIsolate>
224   static Handle<ScopeInfo> Create(LocalIsolate* isolate, Zone* zone,
225                                   Scope* scope,
226                                   MaybeHandle<ScopeInfo> outer_scope);
227   static Handle<ScopeInfo> CreateForWithScope(
228       Isolate* isolate, MaybeHandle<ScopeInfo> outer_scope);
229   V8_EXPORT_PRIVATE static Handle<ScopeInfo> CreateForEmptyFunction(
230       Isolate* isolate);
231   static Handle<ScopeInfo> CreateForNativeContext(Isolate* isolate);
232   static Handle<ScopeInfo> CreateGlobalThisBinding(Isolate* isolate);
233 
234   // Creates a copy of a {ScopeInfo} but with the provided locals blocklist
235   // attached. Does nothing if the original {ScopeInfo} already has a field
236   // for a blocklist reserved.
237   V8_EXPORT_PRIVATE static Handle<ScopeInfo> RecreateWithBlockList(
238       Isolate* isolate, Handle<ScopeInfo> original,
239       Handle<StringSet> blocklist);
240 
241   // Serializes empty scope info.
242   V8_EXPORT_PRIVATE static ScopeInfo Empty(Isolate* isolate);
243 
244 // The layout of the static part of a ScopeInfo is as follows. Each entry is
245 // numeric and occupies one array slot.
246 // 1. A set of properties of the scope.
247 // 2. The number of parameters. For non-function scopes this is 0.
248 // 3. The number of non-parameter and parameter variables allocated in the
249 //    context.
250 #define FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(V) \
251   V(Flags)                                   \
252   V(ParameterCount)                          \
253   V(ContextLocalCount)
254 
255 #define FIELD_ACCESSORS(name)       \
256   inline void Set##name(int value); \
257   inline int name() const;
258   FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
259 #undef FIELD_ACCESSORS
260 
261   enum Fields {
262 #define DECL_INDEX(name) k##name,
263     FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(DECL_INDEX)
264 #undef DECL_INDEX
265         kVariablePartIndex
266   };
267 
268   static const int kFlagsOffset = OffsetOfElementAt(Fields::kFlags);
269 
270   STATIC_ASSERT(LanguageModeSize == 1 << LanguageModeBit::kSize);
271   STATIC_ASSERT(kLastFunctionKind <= FunctionKindBits::kMax);
272 
273  private:
274   // The layout of the variable part of a ScopeInfo is as follows:
275   // 1. ContextLocalNames:
276   //    Contains the names of local variables and parameters that are allocated
277   //    in the context. They are stored in increasing order of the context slot
278   //    index starting with Context::MIN_CONTEXT_SLOTS. One slot is used per
279   //    context local, so in total this part occupies ContextLocalCount() slots
280   //    in the array.
281   // 2. ContextLocalInfos:
282   //    Contains the variable modes and initialization flags corresponding to
283   //    the context locals in ContextLocalNames. One slot is used per
284   //    context local, so in total this part occupies ContextLocalCount()
285   //    slots in the array.
286   // 3. SavedClassVariableInfo:
287   //    If the scope is a class scope and it has static private methods that
288   //    may be accessed directly or through eval, one slot is reserved to hold
289   //    the context slot index for the class variable.
290   // 4. ReceiverInfo:
291   //    If the scope binds a "this" value, one slot is reserved to hold the
292   //    context or stack slot index for the variable.
293   // 5. FunctionNameInfo:
294   //    If the scope belongs to a named function expression this part contains
295   //    information about the function variable. It always occupies two array
296   //    slots:  a. The name of the function variable.
297   //            b. The context or stack slot index for the variable.
298   // 6. InferredFunctionName:
299   //    Contains the function's inferred name.
300   // 7. SourcePosition:
301   //    Contains two slots with a) the startPosition and b) the endPosition if
302   //    the scope belongs to a function or script.
303   // 8. OuterScopeInfoIndex:
304   //    The outer scope's ScopeInfo or the hole if there's none.
305   // 9. LocalsBlockList: List of stack allocated local variables. Used by
306   //    debug evaluate to properly abort variable lookup when a name clashes
307   //    with a stack allocated local that can't be materialized.
308   // 10. SourceTextModuleInfo, ModuleVariableCount, and ModuleVariables:
309   //     For a module scope, this part contains the SourceTextModuleInfo, the
310   //     number of MODULE-allocated variables, and the metadata of those
311   //     variables.  For non-module scopes it is empty.
312   int ContextLocalNamesIndex() const;
313   int ContextLocalInfosIndex() const;
314   int SavedClassVariableInfoIndex() const;
315   int ReceiverInfoIndex() const;
316   int FunctionNameInfoIndex() const;
317   int InferredFunctionNameIndex() const;
318   int PositionInfoIndex() const;
319   int OuterScopeInfoIndex() const;
320   V8_EXPORT_PRIVATE int LocalsBlockListIndex() const;
321   int ModuleInfoIndex() const;
322   int ModuleVariableCountIndex() const;
323   int ModuleVariablesIndex() const;
324 
325   static bool NeedsPositionInfo(ScopeType type);
326 
327   enum class BootstrappingType { kScript, kFunction, kNative };
328   static Handle<ScopeInfo> CreateForBootstrapping(Isolate* isolate,
329                                                   BootstrappingType type);
330 
331   int Lookup(Handle<String> name, int start, int end, VariableMode* mode,
332              VariableLocation* location, InitializationFlag* init_flag,
333              MaybeAssignedFlag* maybe_assigned_flag);
334 
335   // Get metadata of i-th MODULE-allocated variable, where 0 <= i <
336   // ModuleVariableCount.  The metadata is returned via out-arguments, which may
337   // be nullptr if the corresponding information is not requested
338   void ModuleVariable(int i, String* name, int* index,
339                       VariableMode* mode = nullptr,
340                       InitializationFlag* init_flag = nullptr,
341                       MaybeAssignedFlag* maybe_assigned_flag = nullptr);
342 
343   static const int kFunctionNameEntries = 2;
344   static const int kPositionInfoEntries = 2;
345 
346   // Properties of variables.
347   using VariableModeField = base::BitField<VariableMode, 0, 4>;
348   using InitFlagField = VariableModeField::Next<InitializationFlag, 1>;
349   using MaybeAssignedFlagField = InitFlagField::Next<MaybeAssignedFlag, 1>;
350   using ParameterNumberField = MaybeAssignedFlagField::Next<uint32_t, 16>;
351   using IsStaticFlagField = ParameterNumberField::Next<IsStaticFlag, 1>;
352 
353   friend class ScopeIterator;
354   friend std::ostream& operator<<(std::ostream& os, VariableAllocationInfo var);
355 
356   OBJECT_CONSTRUCTORS(ScopeInfo, FixedArray);
357   FRIEND_TEST(TestWithNativeContext, RecreateScopeInfoWithLocalsBlocklistWorks);
358 };
359 
360 std::ostream& operator<<(std::ostream& os, VariableAllocationInfo var);
361 
362 }  // namespace internal
363 }  // namespace v8
364 
365 #include "src/objects/object-macros-undef.h"
366 
367 #endif  // V8_OBJECTS_SCOPE_INFO_H_
368