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