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