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