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