v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
instance-type.h
Go to the documentation of this file.
1// Copyright 2018 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_INSTANCE_TYPE_H_
6#define V8_OBJECTS_INSTANCE_TYPE_H_
7
10#include "torque-generated/instance-types.h"
11
12// Has to be the last include (doesn't have include guards):
14
15namespace v8 {
16namespace internal {
17
18class Map;
19template <typename T>
20class Tagged;
21
22// We use the full 16 bits of the instance_type field to encode heap object
23// instance types. All the high-order bits (bits 7-15) are cleared if the object
24// is a string, and contain set bits if it is not a string.
25const uint32_t kIsNotStringMask = ~((1 << 7) - 1);
26const uint32_t kStringTag = 0x0;
27
28// For strings, bits 0-2 indicate the representation of the string. In
29// particular, bit 0 indicates whether the string is direct or indirect.
30const uint32_t kStringRepresentationMask = (1 << 3) - 1;
38const uint32_t kIsIndirectStringMask = 1 << 0;
39const uint32_t kIsIndirectStringTag = 1 << 0;
40static_assert((kSeqStringTag & kIsIndirectStringMask) == 0);
41static_assert((kExternalStringTag & kIsIndirectStringMask) == 0);
43static_assert((kSlicedStringTag & kIsIndirectStringMask) ==
46const uint32_t kThinStringTagBit = 1 << 2;
47// Assert that the kThinStringTagBit is only used in kThinStringTag.
48static_assert((kSeqStringTag & kThinStringTagBit) == 0);
49static_assert((kConsStringTag & kThinStringTagBit) == 0);
50static_assert((kExternalStringTag & kThinStringTagBit) == 0);
51static_assert((kSlicedStringTag & kThinStringTagBit) == 0);
53
54// For strings, bit 3 indicates whether the string consists of two-byte
55// characters or one-byte characters.
56const uint32_t kStringEncodingMask = 1 << 3;
57const uint32_t kTwoByteStringTag = 0;
58const uint32_t kOneByteStringTag = 1 << 3;
59
60// Combined tags for convenience (add more if needed).
65constexpr uint32_t kExternalOneByteStringTag =
67constexpr uint32_t kExternalTwoByteStringTag =
69
70// For strings, bit 4 indicates whether the data pointer of an external string
71// is cached. Note that the string representation is expected to be
72// kExternalStringTag.
73const uint32_t kUncachedExternalStringMask = 1 << 4;
74const uint32_t kUncachedExternalStringTag = 1 << 4;
75
76// For strings, bit 5 indicates that the string is internalized (if not set) or
77// isn't (if set).
78const uint32_t kIsNotInternalizedMask = 1 << 5;
79const uint32_t kNotInternalizedTag = 1 << 5;
80const uint32_t kInternalizedTag = 0;
81
82// For strings, bit 6 indicates that the string is accessible by more than one
83// thread. Note that a string that is allocated in the shared heap is not
84// accessible by more than one thread until it is explicitly shared (e.g. by
85// postMessage).
86//
87// Runtime code that shares strings with other threads directly need to manually
88// set this bit.
89//
90// TODO(v8:12007): External strings cannot be shared yet.
91//
92// TODO(v8:12007): This bit is currently ignored on internalized strings, which
93// are either always shared or always not shared depending on
94// v8_flags.shared_string_table. This will be hardcoded once
95// v8_flags.shared_string_table is removed.
96const uint32_t kSharedStringMask = 1 << 6;
97const uint32_t kSharedStringTag = 1 << 6;
98
101
102// A ConsString with an empty string as the right side is a candidate
103// for being shortcut by the garbage collector. We don't allocate any
104// non-flat internalized strings, so we do not shortcut them thereby
105// avoiding turning internalized strings into strings. The bit-masks
106// below contain the internalized bit as additional safety.
107// See heap.cc, mark-compact.cc and heap-visitor.cc.
108const uint32_t kShortcutTypeMask =
111
112static inline bool IsShortcutCandidate(int type) {
113 return ((type & kShortcutTypeMask) == kShortcutTypeTag);
114}
115
116enum InstanceType : uint16_t {
117 // String types.
166
167// Most instance types are defined in Torque, with the exception of the string
168// types above. They are ordered by inheritance hierarchy so that we can easily
169// use range checks to determine whether an object is an instance of a subclass
170// of any type. There are a few more constraints specified in the Torque type
171// definitions:
172// - Some instance types are exposed in v8.h, so they are locked to specific
173// values to not unnecessarily change the ABI.
174// - JSSpecialObject and JSCustomElementsObject are aligned with the beginning
175// of the JSObject range, so that we can use a larger range check from
176// FIRST_JS_RECEIVER_TYPE to the end of those ranges and include JSProxy too.
177#define MAKE_TORQUE_INSTANCE_TYPE(TYPE, value) TYPE = value,
178 TORQUE_ASSIGNED_INSTANCE_TYPES(MAKE_TORQUE_INSTANCE_TYPE)
179#undef MAKE_TORQUE_INSTANCE_TYPE
180
181 // Pseudo-types
184 FIRST_NONSTRING_TYPE = SYMBOL_TYPE,
185 // Callable JS Functions are all JS Functions except class constructors.
186 FIRST_CALLABLE_JS_FUNCTION_TYPE = FIRST_JS_FUNCTION_TYPE,
187 LAST_CALLABLE_JS_FUNCTION_TYPE = JS_CLASS_CONSTRUCTOR_TYPE - 1,
188 // Boundary for testing JSReceivers that need special property lookup handling
189 LAST_SPECIAL_RECEIVER_TYPE = LAST_JS_SPECIAL_OBJECT_TYPE,
190 // Boundary case for testing JSReceivers that may have elements while having
191 // an empty fixed array as elements backing store. This is true for string
192 // wrappers.
193 LAST_CUSTOM_ELEMENTS_RECEIVER = LAST_JS_CUSTOM_ELEMENTS_OBJECT_TYPE,
194
195 // Convenient names for things where the generated name is awkward:
196 FIRST_TYPE = FIRST_HEAP_OBJECT_TYPE,
197 LAST_TYPE = LAST_HEAP_OBJECT_TYPE,
198 BIGINT_TYPE = BIG_INT_BASE_TYPE,
199
200 // TODO(ishell): define a dedicated instance type for DependentCode to
201 // simplify CodeSerializer.
202 DEPENDENT_CODE_TYPE = WEAK_ARRAY_LIST_TYPE,
203};
204
205// This constant is defined outside of the InstanceType enum because the
206// string instance types are sparse and there's no such string instance type.
207// But it's still useful for range checks to have such a value.
209 static_cast<InstanceType>(FIRST_NONSTRING_TYPE - 1);
210
212static_assert(JS_OBJECT_TYPE == Internals::kJSObjectType);
213static_assert(FIRST_JS_API_OBJECT_TYPE == Internals::kFirstJSApiObjectType);
214static_assert(LAST_JS_API_OBJECT_TYPE == Internals::kLastJSApiObjectType);
215static_assert(JS_SPECIAL_API_OBJECT_TYPE == Internals::kJSSpecialApiObjectType);
217static_assert(ODDBALL_TYPE == Internals::kOddballType);
218static_assert(FOREIGN_TYPE == Internals::kForeignType);
219
220// Verify that string types are all less than other types.
221#define CHECK_STRING_RANGE(TYPE, ...) \
222 static_assert(TYPE < FIRST_NONSTRING_TYPE);
224#undef CHECK_STRING_RANGE
225#define CHECK_NONSTRING_RANGE(TYPE) static_assert(TYPE >= FIRST_NONSTRING_TYPE);
226TORQUE_ASSIGNED_INSTANCE_TYPE_LIST(CHECK_NONSTRING_RANGE)
227#undef CHECK_NONSTRING_RANGE
228
229// classConstructor type has to be the last one in the JS Function type range.
230static_assert(JS_CLASS_CONSTRUCTOR_TYPE == LAST_JS_FUNCTION_TYPE);
231static_assert(JS_CLASS_CONSTRUCTOR_TYPE < FIRST_CALLABLE_JS_FUNCTION_TYPE ||
232 JS_CLASS_CONSTRUCTOR_TYPE > LAST_CALLABLE_JS_FUNCTION_TYPE,
233 "JS_CLASS_CONSTRUCTOR_TYPE must not be in the callable JS "
234 "function type range");
235
236// Two ranges don't cleanly follow the inheritance hierarchy. Here we ensure
237// that only expected types fall within these ranges.
238// - From FIRST_JS_RECEIVER_TYPE to LAST_SPECIAL_RECEIVER_TYPE should correspond
239// to the union type JSProxy | JSSpecialObject.
240// - From FIRST_JS_RECEIVER_TYPE to LAST_CUSTOM_ELEMENTS_RECEIVER should
241// correspond to the union type JSProxy | JSCustomElementsObject.
242// Note in particular that these ranges include all subclasses of JSReceiver
243// that are not also subclasses of JSObject (currently only JSProxy).
244// clang-format off
245#define CHECK_INSTANCE_TYPE(TYPE) \
246 static_assert((TYPE >= FIRST_JS_RECEIVER_TYPE && \
247 TYPE <= LAST_SPECIAL_RECEIVER_TYPE) == \
248 (IF_WASM(EXPAND, TYPE == WASM_STRUCT_TYPE || \
249 TYPE == WASM_ARRAY_TYPE ||) \
250 TYPE == JS_PROXY_TYPE || TYPE == JS_GLOBAL_OBJECT_TYPE || \
251 TYPE == JS_GLOBAL_PROXY_TYPE || \
252 TYPE == JS_MODULE_NAMESPACE_TYPE || \
253 TYPE == JS_SPECIAL_API_OBJECT_TYPE)); \
254 static_assert((TYPE >= FIRST_JS_RECEIVER_TYPE && \
255 TYPE <= LAST_CUSTOM_ELEMENTS_RECEIVER) == \
256 (IF_WASM(EXPAND, TYPE == WASM_STRUCT_TYPE || \
257 TYPE == WASM_ARRAY_TYPE ||) \
258 TYPE == JS_PROXY_TYPE || TYPE == JS_GLOBAL_OBJECT_TYPE || \
259 TYPE == JS_GLOBAL_PROXY_TYPE || \
260 TYPE == JS_MODULE_NAMESPACE_TYPE || \
261 TYPE == JS_SPECIAL_API_OBJECT_TYPE || \
262 TYPE == JS_PRIMITIVE_WRAPPER_TYPE));
263// clang-format on
264TORQUE_ASSIGNED_INSTANCE_TYPE_LIST(CHECK_INSTANCE_TYPE)
265#undef CHECK_INSTANCE_TYPE
266
267// Make sure it doesn't matter whether we sign-extend or zero-extend these
268// values, because Torque treats InstanceType as signed.
269static_assert(LAST_TYPE < 1 << 15);
270
271V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
272 InstanceType instance_type);
273
274V8_EXPORT_PRIVATE std::string ToString(InstanceType instance_type);
275
276// This list must contain only maps that are shared by all objects of their
277// instance type AND respective object must not represent a parent class for
278// multiple instance types (e.g. DescriptorArray has a unique map, but it has
279// a subclass StrongDescriptorArray which is included into the "DescriptorArray"
280// range of instance types).
281#define UNIQUE_LEAF_INSTANCE_TYPE_MAP_LIST_GENERATOR(V, _) \
282 V(_, AccessorInfoMap, accessor_info_map, AccessorInfo) \
283 V(_, AccessorPairMap, accessor_pair_map, AccessorPair) \
284 V(_, AllocationMementoMap, allocation_memento_map, AllocationMemento) \
285 V(_, ArrayBoilerplateDescriptionMap, array_boilerplate_description_map, \
286 ArrayBoilerplateDescription) \
287 V(_, BreakPointMap, break_point_map, BreakPoint) \
288 V(_, BreakPointInfoMap, break_point_info_map, BreakPointInfo) \
289 V(_, BytecodeArrayMap, bytecode_array_map, BytecodeArray) \
290 V(_, CellMap, cell_map, Cell) \
291 V(_, WeakCellMap, weak_cell_map, WeakCell) \
292 V(_, InstructionStreamMap, instruction_stream_map, InstructionStream) \
293 V(_, CodeMap, code_map, Code) \
294 V(_, CoverageInfoMap, coverage_info_map, CoverageInfo) \
295 V(_, DebugInfoMap, debug_info_map, DebugInfo) \
296 V(_, FreeSpaceMap, free_space_map, FreeSpace) \
297 V(_, FeedbackVectorMap, feedback_vector_map, FeedbackVector) \
298 V(_, FixedDoubleArrayMap, fixed_double_array_map, FixedDoubleArray) \
299 V(_, InterpreterDataMap, interpreter_data_map, InterpreterData) \
300 V(_, MegaDomHandlerMap, mega_dom_handler_map, MegaDomHandler) \
301 V(_, PreparseDataMap, preparse_data_map, PreparseData) \
302 V(_, PropertyArrayMap, property_array_map, PropertyArray) \
303 V(_, PrototypeInfoMap, prototype_info_map, PrototypeInfo) \
304 V(_, SharedFunctionInfoMap, shared_function_info_map, SharedFunctionInfo) \
305 V(_, SmallOrderedHashSetMap, small_ordered_hash_set_map, \
306 SmallOrderedHashSet) \
307 V(_, SmallOrderedHashMapMap, small_ordered_hash_map_map, \
308 SmallOrderedHashMap) \
309 V(_, SmallOrderedNameDictionaryMap, small_ordered_name_dictionary_map, \
310 SmallOrderedNameDictionary) \
311 V(_, SwissNameDictionaryMap, swiss_name_dictionary_map, SwissNameDictionary) \
312 V(_, SymbolMap, symbol_map, Symbol) \
313 V(_, TransitionArrayMap, transition_array_map, TransitionArray) \
314 V(_, Tuple2Map, tuple2_map, Tuple2)
315
316// This list must contain only maps that are shared by all objects of their
317// instance type.
318#define UNIQUE_INSTANCE_TYPE_MAP_LIST_GENERATOR(V, _) \
319 UNIQUE_LEAF_INSTANCE_TYPE_MAP_LIST_GENERATOR(V, _) \
320 V(_, ByteArrayMap, byte_array_map, ByteArray) \
321 V(_, NameDictionaryMap, name_dictionary_map, NameDictionary) \
322 V(_, OrderedNameDictionaryMap, ordered_name_dictionary_map, \
323 OrderedNameDictionary) \
324 V(_, GlobalDictionaryMap, global_dictionary_map, GlobalDictionary) \
325 V(_, GlobalPropertyCellMap, global_property_cell_map, PropertyCell) \
326 V(_, GlobalContextSidePropertyCellMap, \
327 global_context_side_property_cell_map, ContextSidePropertyCell) \
328 V(_, HeapNumberMap, heap_number_map, HeapNumber) \
329 V(_, WeakFixedArrayMap, weak_fixed_array_map, WeakFixedArray) \
330 V(_, ScopeInfoMap, scope_info_map, ScopeInfo) \
331 V(_, WeakArrayListMap, weak_array_list_map, WeakArrayList) \
332 TORQUE_DEFINED_MAP_CSA_LIST_GENERATOR(V, _)
333
334#ifdef V8_ENABLE_SWISS_NAME_DICTIONARY
335static constexpr InstanceType PROPERTY_DICTIONARY_TYPE =
336 SWISS_NAME_DICTIONARY_TYPE;
337#else
338static constexpr InstanceType PROPERTY_DICTIONARY_TYPE = NAME_DICTIONARY_TYPE;
339#endif
340
341namespace InstanceTypeChecker {
348} // namespace InstanceTypeChecker
349
350} // namespace internal
351} // namespace v8
352
354
355#endif // V8_OBJECTS_INSTANCE_TYPE_H_
static const int kOddballType
static const int kForeignType
static const int kJSObjectType
static const int kLastJSApiObjectType
static const int kFirstNonstringType
static const int kFirstJSApiObjectType
static const int kJSSpecialApiObjectType
#define CHECK_STRING_RANGE(TYPE,...)
#define MAKE_TORQUE_INSTANCE_TYPE(TYPE, value)
#define CHECK_NONSTRING_RANGE(TYPE)
#define CHECK_INSTANCE_TYPE(TYPE)
V8_INLINE constexpr bool IsSeqString(InstanceType instance_type)
V8_INLINE constexpr bool IsThinString(InstanceType instance_type)
V8_INLINE constexpr bool IsConsString(InstanceType instance_type)
V8_INLINE constexpr bool IsOneByteString(InstanceType instance_type)
V8_INLINE constexpr bool IsSlicedString(InstanceType instance_type)
V8_INLINE constexpr bool IsTwoByteString(InstanceType instance_type)
const uint32_t kSharedStringTag
const uint32_t kStringEncodingMask
constexpr const char * ToString(DeoptimizeKind kind)
Definition globals.h:880
const uint32_t kTwoByteStringTag
constexpr uint32_t kStringRepresentationAndEncodingMask
constexpr uint32_t kSeqOneByteStringTag
constexpr InstanceType LAST_STRING_TYPE
const uint32_t kShortcutTypeMask
const uint32_t kUncachedExternalStringTag
static constexpr InstanceType PROPERTY_DICTIONARY_TYPE
Tagged(T object) -> Tagged< T >
const uint32_t kThinStringTagBit
const uint32_t kUncachedExternalStringMask
const uint32_t kNotInternalizedTag
const uint32_t kStringTag
const uint32_t kOneByteStringTag
std::ostream & operator<<(std::ostream &os, AtomicMemoryOrder order)
static bool IsShortcutCandidate(int type)
constexpr uint32_t kExternalTwoByteStringTag
constexpr uint32_t kStringRepresentationEncodingAndSharedMask
const uint32_t kStringRepresentationMask
@ UNCACHED_EXTERNAL_INTERNALIZED_ONE_BYTE_STRING_TYPE
@ SHARED_SEQ_ONE_BYTE_STRING_TYPE
@ SHARED_SEQ_TWO_BYTE_STRING_TYPE
@ UNCACHED_EXTERNAL_TWO_BYTE_STRING_TYPE
@ SHARED_EXTERNAL_TWO_BYTE_STRING_TYPE
@ UNCACHED_EXTERNAL_INTERNALIZED_TWO_BYTE_STRING_TYPE
@ SLICED_TWO_BYTE_STRING_TYPE
@ LAST_CALLABLE_JS_FUNCTION_TYPE
@ UNCACHED_EXTERNAL_ONE_BYTE_STRING_TYPE
@ LAST_CUSTOM_ELEMENTS_RECEIVER
@ SHARED_UNCACHED_EXTERNAL_TWO_BYTE_STRING_TYPE
@ SLICED_ONE_BYTE_STRING_TYPE
@ EXTERNAL_TWO_BYTE_STRING_TYPE
@ SHARED_UNCACHED_EXTERNAL_ONE_BYTE_STRING_TYPE
@ EXTERNAL_INTERNALIZED_TWO_BYTE_STRING_TYPE
@ SHARED_EXTERNAL_ONE_BYTE_STRING_TYPE
@ FIRST_CALLABLE_JS_FUNCTION_TYPE
@ EXTERNAL_INTERNALIZED_ONE_BYTE_STRING_TYPE
@ EXTERNAL_ONE_BYTE_STRING_TYPE
@ INTERNALIZED_ONE_BYTE_STRING_TYPE
@ INTERNALIZED_TWO_BYTE_STRING_TYPE
const uint32_t kShortcutTypeTag
const uint32_t kIsIndirectStringTag
const uint32_t kInternalizedTag
const uint32_t kSharedStringMask
const uint32_t kIsNotInternalizedMask
constexpr uint32_t kExternalOneByteStringTag
const uint32_t kIsNotStringMask
constexpr uint32_t kSeqTwoByteStringTag
const uint32_t kIsIndirectStringMask
#define STRING_TYPE_LIST(V)
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define V8_INLINE
Definition v8config.h:500