• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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