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