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/objects.h" 9 10 // Has to be the last include (doesn't have include guards): 11 #include "src/objects/object-macros.h" 12 13 namespace v8 { 14 namespace internal { 15 16 // The Name abstract class captures anything that can be used as a property 17 // name, i.e., strings and symbols. All names store a hash value. 18 class Name : public HeapObject { 19 public: 20 // Get and set the hash field of the name. 21 inline uint32_t hash_field(); 22 inline void set_hash_field(uint32_t value); 23 24 // Tells whether the hash code has been computed. 25 inline bool HasHashCode(); 26 27 // Returns a hash value used for the property table 28 inline uint32_t Hash(); 29 30 // Equality operations. 31 inline bool Equals(Name* other); 32 inline static bool Equals(Handle<Name> one, Handle<Name> two); 33 34 // Conversion. 35 inline bool AsArrayIndex(uint32_t* index); 36 37 // An "interesting symbol" is a well-known symbol, like @@toStringTag, 38 // that's often looked up on random objects but is usually not present. 39 // We optimize this by setting a flag on the object's map when such 40 // symbol properties are added, so we can optimize lookups on objects 41 // that don't have the flag. 42 inline bool IsInterestingSymbol() const; 43 44 // If the name is private, it can only name own properties. 45 inline bool IsPrivate(); 46 47 // If the name is a private field, it should behave like a private 48 // symbol but also throw on property access miss. 49 inline bool IsPrivateField(); 50 51 inline bool IsUniqueName() const; 52 53 static inline bool ContainsCachedArrayIndex(uint32_t hash); 54 55 // Return a string version of this name that is converted according to the 56 // rules described in ES6 section 9.2.11. 57 V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToFunctionName( 58 Handle<Name> name); 59 V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToFunctionName( 60 Handle<Name> name, Handle<String> prefix); 61 62 DECL_CAST(Name) 63 64 DECL_PRINTER(Name) 65 void NameShortPrint(); 66 int NameShortPrint(Vector<char> str); 67 68 // Layout description. 69 static const int kHashFieldSlot = HeapObject::kHeaderSize; 70 #if V8_TARGET_LITTLE_ENDIAN || !V8_HOST_ARCH_64_BIT 71 static const int kHashFieldOffset = kHashFieldSlot; 72 #else 73 static const int kHashFieldOffset = kHashFieldSlot + kInt32Size; 74 #endif 75 static const int kSize = kHashFieldSlot + kPointerSize; 76 77 // Mask constant for checking if a name has a computed hash code 78 // and if it is a string that is an array index. The least significant bit 79 // indicates whether a hash code has been computed. If the hash code has 80 // been computed the 2nd bit tells whether the string can be used as an 81 // array index. 82 static const int kHashNotComputedMask = 1; 83 static const int kIsNotArrayIndexMask = 1 << 1; 84 static const int kNofHashBitFields = 2; 85 86 // Shift constant retrieving hash code from hash field. 87 static const int kHashShift = kNofHashBitFields; 88 89 // Only these bits are relevant in the hash, since the top two are shifted 90 // out. 91 static const uint32_t kHashBitMask = 0xffffffffu >> kHashShift; 92 93 // Array index strings this short can keep their index in the hash field. 94 static const int kMaxCachedArrayIndexLength = 7; 95 96 // Maximum number of characters to consider when trying to convert a string 97 // value into an array index. 98 static const int kMaxArrayIndexSize = 10; 99 100 // For strings which are array indexes the hash value has the string length 101 // mixed into the hash, mainly to avoid a hash value of zero which would be 102 // the case for the string '0'. 24 bits are used for the array index value. 103 static const int kArrayIndexValueBits = 24; 104 static const int kArrayIndexLengthBits = 105 kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields; 106 107 STATIC_ASSERT(kArrayIndexLengthBits > 0); 108 STATIC_ASSERT(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits)); 109 110 class ArrayIndexValueBits 111 : public BitField<unsigned int, kNofHashBitFields, kArrayIndexValueBits> { 112 }; // NOLINT 113 class ArrayIndexLengthBits 114 : public BitField<unsigned int, kNofHashBitFields + kArrayIndexValueBits, 115 kArrayIndexLengthBits> {}; // NOLINT 116 117 // Check that kMaxCachedArrayIndexLength + 1 is a power of two so we 118 // could use a mask to test if the length of string is less than or equal to 119 // kMaxCachedArrayIndexLength. 120 static_assert(base::bits::IsPowerOfTwo(kMaxCachedArrayIndexLength + 1), 121 "(kMaxCachedArrayIndexLength + 1) must be power of two"); 122 123 // When any of these bits is set then the hash field does not contain a cached 124 // array index. 125 static const unsigned int kDoesNotContainCachedArrayIndexMask = 126 (~static_cast<unsigned>(kMaxCachedArrayIndexLength) 127 << ArrayIndexLengthBits::kShift) | 128 kIsNotArrayIndexMask; 129 130 // Value of empty hash field indicating that the hash is not computed. 131 static const int kEmptyHashField = 132 kIsNotArrayIndexMask | kHashNotComputedMask; 133 134 protected: 135 static inline bool IsHashFieldComputed(uint32_t field); 136 137 private: 138 DISALLOW_IMPLICIT_CONSTRUCTORS(Name); 139 }; 140 141 // ES6 symbols. 142 class Symbol : public Name { 143 public: 144 // [name]: The print name of a symbol, or undefined if none. 145 DECL_ACCESSORS(name, Object) 146 147 DECL_INT_ACCESSORS(flags) 148 149 // [is_private]: Whether this is a private symbol. Private symbols can only 150 // be used to designate own properties of objects. 151 DECL_BOOLEAN_ACCESSORS(is_private) 152 153 // [is_well_known_symbol]: Whether this is a spec-defined well-known symbol, 154 // or not. Well-known symbols do not throw when an access check fails during 155 // a load. 156 DECL_BOOLEAN_ACCESSORS(is_well_known_symbol) 157 158 // [is_interesting_symbol]: Whether this is an "interesting symbol", which 159 // is a well-known symbol like @@toStringTag that's often looked up on 160 // random objects but is usually not present. See Name::IsInterestingSymbol() 161 // for a detailed description. 162 DECL_BOOLEAN_ACCESSORS(is_interesting_symbol) 163 164 // [is_public]: Whether this is a symbol created by Symbol.for. Calling 165 // Symbol.keyFor on such a symbol simply needs to return the attached name. 166 DECL_BOOLEAN_ACCESSORS(is_public) 167 168 // [is_private_field]: Whether this is a private field. Private fields 169 // are the same as private symbols except they throw on missing 170 // property access. 171 // 172 // This also sets the is_private bit. 173 inline bool is_private_field() const; 174 inline void set_is_private_field(); 175 176 DECL_CAST(Symbol) 177 178 // Dispatched behavior. 179 DECL_PRINTER(Symbol) 180 DECL_VERIFIER(Symbol) 181 182 // Layout description. 183 static const int kNameOffset = Name::kSize; 184 static const int kFlagsOffset = kNameOffset + kPointerSize; 185 static const int kSize = kFlagsOffset + kPointerSize; 186 187 // Flags layout. 188 static const int kPrivateBit = 0; 189 static const int kWellKnownSymbolBit = 1; 190 static const int kPublicBit = 2; 191 static const int kInterestingSymbolBit = 3; 192 static const int kPrivateFieldBit = 4; 193 194 typedef FixedBodyDescriptor<kNameOffset, kFlagsOffset, kSize> BodyDescriptor; 195 // No weak fields. 196 typedef BodyDescriptor BodyDescriptorWeak; 197 198 void SymbolShortPrint(std::ostream& os); 199 200 private: 201 const char* PrivateSymbolToName() const; 202 203 // TODO(cbruni): remove once the new maptracer is in place. 204 friend class Name; // For PrivateSymbolToName. 205 206 DISALLOW_IMPLICIT_CONSTRUCTORS(Symbol); 207 }; 208 209 } // namespace internal 210 } // namespace v8 211 212 #include "src/objects/object-macros-undef.h" 213 214 #endif // V8_OBJECTS_NAME_H_ 215