1// Copyright 2019 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 5extern macro EmptyScopeInfoConstant(): ScopeInfo; 6const kEmptyScopeInfo: ScopeInfo = EmptyScopeInfoConstant(); 7 8extern enum ScopeType extends uint32 { 9 // The empty scope info for builtins and NativeContexts is allocated 10 // in a way that it gets the first scope type in line, see 11 // Heap::CreateInitialMaps(). It's always guarded with the IsEmpty 12 // bit, so it doesn't matter what scope type it gets. 13 CLASS_SCOPE, 14 EVAL_SCOPE, 15 FUNCTION_SCOPE, 16 MODULE_SCOPE, 17 SCRIPT_SCOPE, 18 CATCH_SCOPE, 19 BLOCK_SCOPE, 20 WITH_SCOPE 21} 22 23extern enum VariableAllocationInfo extends uint32 { 24 NONE, 25 STACK, 26 CONTEXT, 27 UNUSED 28} 29 30extern enum VariableMode extends uint32 { 31 kLet, 32 kConst, 33 kVar, 34 kTemporary, 35 kDynamic, 36 kDynamicGlobal, 37 kDynamicLocal, 38 kPrivateMethod, 39 kPrivateSetterOnly, 40 kPrivateGetterOnly, 41 kPrivateGetterAndSetter 42} 43 44extern enum InitializationFlag extends uint32 { 45 kNeedsInitialization, 46 kCreatedInitialized 47} 48 49extern enum IsStaticFlag extends uint32 { kNotStatic, kStatic } 50 51extern enum MaybeAssignedFlag extends uint32 { kNotAssigned, kMaybeAssigned } 52 53// Properties of scopes. 54bitfield struct ScopeFlags extends uint31 { 55 scope_type: ScopeType: 4 bit; 56 sloppy_eval_can_extend_vars: bool: 1 bit; 57 language_mode: LanguageMode: 1 bit; 58 declaration_scope: bool: 1 bit; 59 receiver_variable: VariableAllocationInfo: 2 bit; 60 // In class scope, this indicates whether the class has a private brand. 61 // In constructor scope, this indicates whether the constructor needs 62 // private brand initialization. 63 class_scope_has_private_brand: bool: 1 bit; 64 has_saved_class_variable: bool: 1 bit; 65 has_new_target: bool: 1 bit; 66 // TODO(cbruni): Combine with function variable field when only storing the 67 // function name. 68 function_variable: VariableAllocationInfo: 2 bit; 69 has_inferred_function_name: bool: 1 bit; 70 is_asm_module: bool: 1 bit; 71 has_simple_parameters: bool: 1 bit; 72 function_kind: FunctionKind: 5 bit; 73 has_outer_scope_info: bool: 1 bit; 74 is_debug_evaluate_scope: bool: 1 bit; 75 force_context_allocation: bool: 1 bit; 76 private_name_lookup_skips_outer_class: bool: 1 bit; 77 has_context_extension_slot: bool: 1 bit; 78 is_repl_mode_scope: bool: 1 bit; 79 has_locals_block_list: bool: 1 bit; 80 is_empty: bool: 1 bit; 81} 82 83struct PositionInfo { 84 start: Smi; 85 end: Smi; 86} 87 88struct FunctionVariableInfo { 89 name: String|Zero; 90 context_or_stack_slot_index: Smi; 91} 92 93bitfield struct VariableProperties extends uint31 { 94 variable_mode: VariableMode: 4 bit; 95 init_flag: InitializationFlag: 1 bit; 96 maybe_assigned_flag: MaybeAssignedFlag: 1 bit; 97 parameter_number: uint32: 16 bit; 98 is_static_flag: IsStaticFlag: 1 bit; 99} 100 101struct ModuleVariable { 102 name: String; 103 index: Smi; 104 properties: SmiTagged<VariableProperties>; 105} 106 107const kMaxInlinedLocalNamesSize: 108 constexpr int32 generates 'kScopeInfoMaxInlinedLocalNamesSize'; 109 110@generateBodyDescriptor 111extern class ScopeInfo extends HeapObject { 112 const flags: SmiTagged<ScopeFlags>; 113 114 // The number of parameters. For non-function scopes this is 0. 115 parameter_count: Smi; 116 117 // The number of non-parameter and parameter variables allocated in the 118 // context. 119 const context_local_count: Smi; 120 121 // Contains the names of inlined local variables and parameters that are 122 // allocated in the context. They are stored in increasing order of the 123 // context slot index starting with Context::MIN_CONTEXT_SLOTS. 124 context_local_names[Convert<intptr>(context_local_count) < kMaxInlinedLocalNamesSize ? context_local_count : 0]: 125 String; 126 127 // Contains a hash_map from local names to context slot index. 128 // This is only used when local names are not inlined in the scope info. 129 context_local_names_hashtable? 130 [kMaxInlinedLocalNamesSize <= Convert<intptr>(context_local_count)]: 131 NameToIndexHashTable; 132 133 // Contains the variable modes and initialization flags corresponding to 134 // the context locals in ContextLocalNames. 135 context_local_infos[context_local_count]: SmiTagged<VariableProperties>; 136 137 // If the scope is a class scope and it has static private methods that 138 // may be accessed directly or through eval, one slot is reserved to hold 139 // the offset in the field storage of the hash table (or the slot index if 140 // local names are inlined) for the class variable. 141 saved_class_variable_info?[flags.has_saved_class_variable]: Smi; 142 143 // If the scope belongs to a named function expression this part contains 144 // information about the function variable. It always occupies two array 145 // slots: a. The name of the function variable. 146 // b. The context or stack slot index for the variable. 147 function_variable_info? 148 [flags.function_variable != 149 FromConstexpr<VariableAllocationInfo>(VariableAllocationInfo::NONE)]: 150 FunctionVariableInfo; 151 152 inferred_function_name?[flags.has_inferred_function_name]: String|Undefined; 153 154 // Contains two slots with a) the startPosition and b) the endPosition if 155 // the scope belongs to a function or script. 156 position_info? 157 [flags.scope_type == ScopeType::FUNCTION_SCOPE || 158 flags.scope_type == ScopeType::SCRIPT_SCOPE || 159 flags.scope_type == ScopeType::EVAL_SCOPE || 160 flags.scope_type == ScopeType::MODULE_SCOPE || 161 (flags.is_empty ? false : flags.scope_type == ScopeType::CLASS_SCOPE)]: 162 PositionInfo; 163 164 outer_scope_info?[flags.has_outer_scope_info]: ScopeInfo|TheHole; 165 166 // List of stack allocated local variables. Used by debug evaluate to properly 167 // abort variable lookup when a name clashes with a stack allocated local that 168 // can't be materialized. 169 locals_block_list?[flags.has_locals_block_list]: HashTable; 170 171 // For a module scope, this part contains the SourceTextModuleInfo, the 172 // number of MODULE-allocated variables, and the metadata of those 173 // variables. For non-module scopes it is empty. 174 module_info? 175 [flags.scope_type == ScopeType::MODULE_SCOPE]: SourceTextModuleInfo; 176 const module_variable_count? 177 [flags.scope_type == ScopeType::MODULE_SCOPE]: Smi; 178 module_variables[flags.scope_type == ScopeType::MODULE_SCOPE ? module_variable_count : 0]: 179 ModuleVariable; 180} 181 182extern macro NameToIndexHashTableLookup( 183 NameToIndexHashTable, Name): intptr labels NotFound; 184 185macro IndexOfInlinedLocalName( 186 scopeInfo: ScopeInfo, name: Name): intptr labels NotFound { 187 const count: intptr = Convert<intptr>(scopeInfo.context_local_count); 188 for (let i: intptr = 0; i < count; ++i) { 189 if (TaggedEqual(name, scopeInfo.context_local_names[i])) { 190 return i; 191 } 192 } 193 goto NotFound; 194} 195 196// Returns the index of the named local in a ScopeInfo. 197// Assumes that the given name is internalized; uses pointer comparisons. 198@export 199macro IndexOfLocalName(scopeInfo: ScopeInfo, name: Name): 200 intptr labels NotFound { 201 const count: intptr = Convert<intptr>(scopeInfo.context_local_count); 202 if (count < kMaxInlinedLocalNamesSize) { 203 return IndexOfInlinedLocalName(scopeInfo, name) otherwise goto NotFound; 204 } else { 205 return NameToIndexHashTableLookup( 206 scopeInfo.context_local_names_hashtable, name) otherwise goto NotFound; 207 } 208} 209