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