1 // Copyright 2017 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_NAME_H_ 6 #define V8_OBJECTS_NAME_H_ 7 8 #include "src/base/bit-field.h" 9 #include "src/objects/objects.h" 10 #include "src/objects/primitive-heap-object.h" 11 #include "torque-generated/bit-fields.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 #include "torque-generated/src/objects/name-tq.inc" 20 21 class SharedStringAccessGuardIfNeeded; 22 23 // The Name abstract class captures anything that can be used as a property 24 // name, i.e., strings and symbols. All names store a hash value. 25 class Name : public TorqueGeneratedName<Name, PrimitiveHeapObject> { 26 public: 27 // Tells whether the hash code has been computed. 28 inline bool HasHashCode() const; 29 30 // Returns a hash value used for the property table. Ensures that the hash 31 // value is computed. 32 // 33 // The overload without SharedStringAccessGuardIfNeeded can only be called on 34 // the main thread. 35 inline uint32_t EnsureHash(); 36 inline uint32_t EnsureHash(const SharedStringAccessGuardIfNeeded&); 37 raw_hash_field()38 inline uint32_t raw_hash_field() const { 39 return RELAXED_READ_UINT32_FIELD(*this, kRawHashFieldOffset); 40 } 41 set_raw_hash_field(uint32_t hash)42 inline void set_raw_hash_field(uint32_t hash) { 43 RELAXED_WRITE_UINT32_FIELD(*this, kRawHashFieldOffset, hash); 44 } 45 46 // Returns a hash value used for the property table (same as Hash()), assumes 47 // the hash is already computed. 48 inline uint32_t hash() const; 49 50 // Equality operations. 51 inline bool Equals(Name other); 52 inline static bool Equals(Isolate* isolate, Handle<Name> one, 53 Handle<Name> two); 54 55 // Conversion. 56 inline bool AsArrayIndex(uint32_t* index); 57 inline bool AsIntegerIndex(size_t* index); 58 59 // An "interesting symbol" is a well-known symbol, like @@toStringTag, 60 // that's often looked up on random objects but is usually not present. 61 // We optimize this by setting a flag on the object's map when such 62 // symbol properties are added, so we can optimize lookups on objects 63 // that don't have the flag. 64 DECL_GETTER(IsInterestingSymbol, bool) 65 66 // If the name is private, it can only name own properties. 67 DECL_GETTER(IsPrivate, bool) 68 69 // If the name is a private name, it should behave like a private 70 // symbol but also throw on property access miss. 71 DECL_GETTER(IsPrivateName, bool) 72 73 // If the name is a private brand, it should behave like a private name 74 // symbol but is filtered out when generating list of private fields. 75 DECL_GETTER(IsPrivateBrand, bool) 76 77 DECL_GETTER(IsUniqueName, bool) 78 79 static inline bool ContainsCachedArrayIndex(uint32_t hash); 80 81 // Return a string version of this name that is converted according to the 82 // rules described in ES6 section 9.2.11. 83 V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToFunctionName( 84 Isolate* isolate, Handle<Name> name); 85 V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToFunctionName( 86 Isolate* isolate, Handle<Name> name, Handle<String> prefix); 87 88 DECL_PRINTER(Name) 89 void NameShortPrint(); 90 int NameShortPrint(base::Vector<char> str); 91 92 // Mask constant for checking if a name has a computed hash code and the type 93 // of information stored in the hash field. The least significant bit 94 // indicates whether the value can be used as a hash (i.e. different values 95 // imply different strings). 96 enum class HashFieldType : uint32_t { 97 kHash = 0b10, 98 kIntegerIndex = 0b00, 99 kForwardingIndex = 0b01, 100 kEmpty = 0b11 101 }; 102 103 using HashFieldTypeBits = base::BitField<HashFieldType, 0, 2>; 104 using HashBits = 105 HashFieldTypeBits::Next<uint32_t, kBitsPerInt - HashFieldTypeBits::kSize>; 106 107 static constexpr int kHashNotComputedMask = 1; 108 // Value of empty hash field indicating that the hash is not computed. 109 static constexpr int kEmptyHashField = 110 HashFieldTypeBits::encode(HashFieldType::kEmpty); 111 112 // Empty hash and forwarding indices can not be used as hash. 113 STATIC_ASSERT((kEmptyHashField & kHashNotComputedMask) != 0); 114 STATIC_ASSERT((HashFieldTypeBits::encode(HashFieldType::kForwardingIndex) & 115 kHashNotComputedMask) != 0); 116 117 // Array index strings this short can keep their index in the hash field. 118 static const int kMaxCachedArrayIndexLength = 7; 119 120 // Maximum number of characters to consider when trying to convert a string 121 // value into an array index. 122 static const int kMaxArrayIndexSize = 10; 123 // Maximum number of characters in a string that can possibly be an 124 // "integer index" in the spec sense, i.e. a canonical representation of a 125 // number in the range up to MAX_SAFE_INTEGER. We parse these into a size_t, 126 // so the size of that type also factors in as a limit: 10 characters per 127 // 32 bits of size_t width. 128 static const int kMaxIntegerIndexSize = 129 std::min(16, int{10 * (sizeof(size_t) / 4)}); 130 131 // For strings which are array indexes the hash value has the string length 132 // mixed into the hash, mainly to avoid a hash value of zero which would be 133 // the case for the string '0'. 24 bits are used for the array index value. 134 static const int kArrayIndexValueBits = 24; 135 static const int kArrayIndexLengthBits = 136 kBitsPerInt - kArrayIndexValueBits - HashFieldTypeBits::kSize; 137 138 STATIC_ASSERT(kArrayIndexLengthBits > 0); 139 STATIC_ASSERT(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits)); 140 141 using ArrayIndexValueBits = 142 HashFieldTypeBits::Next<unsigned int, kArrayIndexValueBits>; 143 using ArrayIndexLengthBits = 144 ArrayIndexValueBits::Next<unsigned int, kArrayIndexLengthBits>; 145 146 // Check that kMaxCachedArrayIndexLength + 1 is a power of two so we 147 // could use a mask to test if the length of string is less than or equal to 148 // kMaxCachedArrayIndexLength. 149 static_assert(base::bits::IsPowerOfTwo(kMaxCachedArrayIndexLength + 1), 150 "(kMaxCachedArrayIndexLength + 1) must be power of two"); 151 152 // When any of these bits is set then the hash field does not contain a cached 153 // array index. 154 STATIC_ASSERT(HashFieldTypeBits::encode(HashFieldType::kIntegerIndex) == 0); 155 static const unsigned int kDoesNotContainCachedArrayIndexMask = 156 (~static_cast<unsigned>(kMaxCachedArrayIndexLength) 157 << ArrayIndexLengthBits::kShift) | 158 HashFieldTypeBits::kMask; 159 160 static inline bool IsHashFieldComputed(uint32_t raw_hash_field); 161 static inline bool IsHash(uint32_t raw_hash_field); 162 static inline bool IsIntegerIndex(uint32_t raw_hash_field); 163 static inline bool IsForwardingIndex(uint32_t raw_hash_field); 164 165 static inline uint32_t CreateHashFieldValue(uint32_t hash, 166 HashFieldType type); 167 168 TQ_OBJECT_CONSTRUCTORS(Name) 169 }; 170 171 // ES6 symbols. 172 class Symbol : public TorqueGeneratedSymbol<Symbol, Name> { 173 public: 174 DEFINE_TORQUE_GENERATED_SYMBOL_FLAGS() 175 176 // [is_private]: Whether this is a private symbol. Private symbols can only 177 // be used to designate own properties of objects. 178 DECL_BOOLEAN_ACCESSORS(is_private) 179 180 // [is_well_known_symbol]: Whether this is a spec-defined well-known symbol, 181 // or not. Well-known symbols do not throw when an access check fails during 182 // a load. 183 DECL_BOOLEAN_ACCESSORS(is_well_known_symbol) 184 185 // [is_interesting_symbol]: Whether this is an "interesting symbol", which 186 // is a well-known symbol like @@toStringTag that's often looked up on 187 // random objects but is usually not present. See Name::IsInterestingSymbol() 188 // for a detailed description. 189 DECL_BOOLEAN_ACCESSORS(is_interesting_symbol) 190 191 // [is_in_public_symbol_table]: Whether this is a symbol created by 192 // Symbol.for. Calling Symbol.keyFor on such a symbol simply needs 193 // to return the attached name. 194 DECL_BOOLEAN_ACCESSORS(is_in_public_symbol_table) 195 196 // [is_private_name]: Whether this is a private name. Private names 197 // are the same as private symbols except they throw on missing 198 // property access. 199 // 200 // This also sets the is_private bit. 201 inline bool is_private_name() const; 202 inline void set_is_private_name(); 203 204 // [is_private_name]: Whether this is a brand symbol. Brand symbols are 205 // private name symbols that are used for validating access to 206 // private methods and storing information about the private methods. 207 // 208 // This also sets the is_private bit. 209 inline bool is_private_brand() const; 210 inline void set_is_private_brand(); 211 212 // Dispatched behavior. 213 DECL_PRINTER(Symbol) 214 DECL_VERIFIER(Symbol) 215 216 using BodyDescriptor = FixedBodyDescriptor<kDescriptionOffset, kSize, kSize>; 217 218 void SymbolShortPrint(std::ostream& os); 219 220 private: 221 const char* PrivateSymbolToName() const; 222 223 // TODO(cbruni): remove once the new maptracer is in place. 224 friend class Name; // For PrivateSymbolToName. 225 226 TQ_OBJECT_CONSTRUCTORS(Symbol) 227 }; 228 229 } // namespace internal 230 } // namespace v8 231 232 #include "src/objects/object-macros-undef.h" 233 234 #endif // V8_OBJECTS_NAME_H_ 235