• 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 // 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