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