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