v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
instance-type-inl.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_INL_H_
6#define V8_OBJECTS_INSTANCE_TYPE_INL_H_
7
9// Include the non-inl header before the rest of the headers.
10
11#include <optional>
12
13#include "src/base/bounds.h"
16#include "src/objects/map-inl.h"
17
18// Has to be the last include (doesn't have include guards):
20
21namespace v8::internal {
22
23namespace InstanceTypeChecker {
24
25// INSTANCE_TYPE_CHECKERS macro defines some "types" that do not have
26// respective C++ classes (see TypedArrayConstructor, FixedArrayExact) or
27// the respective C++ counterpart is actually a template (see HashTable).
28// So in order to be able to customize IsType() implementations for specific
29// types, we declare a parallel set of "types" that can be compared using
30// std::is_same<>.
31namespace InstanceTypeTraits {
32
33#define DECL_TYPE(type, ...) class type;
35TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(DECL_TYPE)
36TORQUE_INSTANCE_CHECKERS_MULTIPLE_ONLY_DECLARED(DECL_TYPE)
38#undef DECL_TYPE
39
40} // namespace InstanceTypeTraits
41
42// Instance types which are associated with one unique map.
43
44template <class type>
45V8_INLINE consteval std::optional<RootIndex> UniqueMapOfInstanceTypeCheck() {
46 return {};
47}
48
49#define INSTANCE_TYPE_MAP(V, rootIndexName, rootAccessorName, class_name) \
50 template <> \
51 V8_INLINE consteval std::optional<RootIndex> \
52 UniqueMapOfInstanceTypeCheck<InstanceTypeTraits::class_name>() { \
53 return {RootIndex::k##rootIndexName}; \
54 }
56#undef INSTANCE_TYPE_MAP
57
58V8_INLINE constexpr std::optional<RootIndex> UniqueMapOfInstanceType(
59 InstanceType type) {
60#define INSTANCE_TYPE_CHECK(it, forinstancetype) \
61 if (type == forinstancetype) { \
62 return InstanceTypeChecker::UniqueMapOfInstanceTypeCheck< \
63 InstanceTypeChecker::InstanceTypeTraits::it>(); \
64 }
66#undef INSTANCE_TYPE_CHECK
67
68 return Map::TryGetMapRootIdxFor(type);
69}
70
71// Manually curated list of instance type ranges which are associated with a
72// unique range of map addresses on the read only heap. Both ranges are
73// inclusive.
74
75using InstanceTypeRange = std::pair<InstanceType, InstanceType>;
76using TaggedAddressRange = std::pair<Tagged_t, Tagged_t>;
77
78#if V8_STATIC_ROOTS_BOOL
79constexpr std::array<std::pair<InstanceTypeRange, TaggedAddressRange>, 9>
80 kUniqueMapRangeOfInstanceTypeRangeList = {
81 {{{ALLOCATION_SITE_TYPE, ALLOCATION_SITE_TYPE},
82 {StaticReadOnlyRoot::kAllocationSiteWithWeakNextMap,
83 StaticReadOnlyRoot::kAllocationSiteWithoutWeakNextMap}},
84 {{FIRST_STRING_TYPE, LAST_STRING_TYPE},
85 {InstanceTypeChecker::kStringMapLowerBound,
86 InstanceTypeChecker::kStringMapUpperBound}},
87 {{FIRST_NAME_TYPE, LAST_NAME_TYPE},
88 {StaticReadOnlyRoot::kSeqTwoByteStringMap,
89 StaticReadOnlyRoot::kSymbolMap}},
90 {{ODDBALL_TYPE, ODDBALL_TYPE},
91 {StaticReadOnlyRoot::kUndefinedMap, StaticReadOnlyRoot::kBooleanMap}},
92 {{HEAP_NUMBER_TYPE, ODDBALL_TYPE},
93 {StaticReadOnlyRoot::kUndefinedMap,
94 StaticReadOnlyRoot::kHeapNumberMap}},
95 {{BIGINT_TYPE, HEAP_NUMBER_TYPE},
96 {StaticReadOnlyRoot::kHeapNumberMap, StaticReadOnlyRoot::kBigIntMap}},
97 {{FIRST_SMALL_ORDERED_HASH_TABLE_TYPE,
98 LAST_SMALL_ORDERED_HASH_TABLE_TYPE},
99 {StaticReadOnlyRoot::kSmallOrderedHashMapMap,
100 StaticReadOnlyRoot::kSmallOrderedNameDictionaryMap}},
101 {{FIRST_ABSTRACT_INTERNAL_CLASS_TYPE,
102 LAST_ABSTRACT_INTERNAL_CLASS_TYPE},
103 {StaticReadOnlyRoot::kAbstractInternalClassSubclass1Map,
104 StaticReadOnlyRoot::kAbstractInternalClassSubclass2Map}},
105 {{FIRST_TURBOFAN_TYPE_TYPE, LAST_TURBOFAN_TYPE_TYPE},
106 {StaticReadOnlyRoot::kTurbofanBitsetTypeMap,
107 StaticReadOnlyRoot::kTurbofanOtherNumberConstantTypeMap}}}};
108
109struct kUniqueMapRangeOfStringType {
110 static constexpr TaggedAddressRange kSeqString = {
111 InstanceTypeChecker::kStringMapLowerBound,
112 StaticReadOnlyRoot::kInternalizedOneByteStringMap};
113 static constexpr TaggedAddressRange kInternalizedString = {
114 StaticReadOnlyRoot::kInternalizedTwoByteStringMap,
115 StaticReadOnlyRoot::kUncachedExternalInternalizedOneByteStringMap};
116 static constexpr TaggedAddressRange kExternalString = {
117 StaticReadOnlyRoot::kExternalInternalizedTwoByteStringMap,
118 StaticReadOnlyRoot::kSharedExternalOneByteStringMap};
119 static constexpr TaggedAddressRange kUncachedExternalString = {
120 StaticReadOnlyRoot::kUncachedExternalInternalizedTwoByteStringMap,
121 StaticReadOnlyRoot::kSharedUncachedExternalOneByteStringMap};
122 static constexpr TaggedAddressRange kConsString = {
123 StaticReadOnlyRoot::kConsTwoByteStringMap,
124 StaticReadOnlyRoot::kConsOneByteStringMap};
125 static constexpr TaggedAddressRange kSlicedString = {
126 StaticReadOnlyRoot::kSlicedTwoByteStringMap,
127 StaticReadOnlyRoot::kSlicedOneByteStringMap};
128 static constexpr TaggedAddressRange kThinString = {
129 StaticReadOnlyRoot::kThinTwoByteStringMap,
130 StaticReadOnlyRoot::kThinOneByteStringMap};
131};
132
133// This one is very sneaky. String maps are laid out sequentially, and
134// alternate between two-byte and one-byte. Since they're sequential, each
135// address is one Map::kSize larger than the previous. This means that the LSB
136// of the map size alternates being set and unset for alternating string map
137// addresses, and therefore is on/off for all two-byte/one-byte strings. Which
138// of the two has the on-bit depends on the current RO heap layout, so just
139// sniff this by checking an arbitrary one-byte map's value.
140static constexpr int kStringMapEncodingMask =
142static constexpr int kOneByteStringMapBit =
143 StaticReadOnlyRoot::kSeqOneByteStringMap & kStringMapEncodingMask;
144static constexpr int kTwoByteStringMapBit =
145 StaticReadOnlyRoot::kSeqTwoByteStringMap & kStringMapEncodingMask;
146
147inline constexpr std::optional<TaggedAddressRange>
148UniqueMapRangeOfInstanceTypeRange(InstanceType first, InstanceType last) {
149 // Doesn't use range based for loop due to LLVM <11 bug re. constexpr
150 // functions.
151 for (size_t i = 0; i < kUniqueMapRangeOfInstanceTypeRangeList.size(); ++i) {
152 if (kUniqueMapRangeOfInstanceTypeRangeList[i].first.first == first &&
153 kUniqueMapRangeOfInstanceTypeRangeList[i].first.second == last) {
154 return {kUniqueMapRangeOfInstanceTypeRangeList[i].second};
155 }
156 }
157 return {};
158}
159
160inline constexpr std::optional<TaggedAddressRange> UniqueMapRangeOfInstanceType(
161 InstanceType type) {
162 return UniqueMapRangeOfInstanceTypeRange(type, type);
163}
164
165inline bool MayHaveMapCheckFastCase(InstanceType type) {
166 if (UniqueMapOfInstanceType(type)) return true;
167 for (auto& el : kUniqueMapRangeOfInstanceTypeRangeList) {
168 if (el.first.first <= type && type <= el.first.second) {
169 return true;
170 }
171 }
172 return false;
173}
174
175inline bool CheckInstanceMap(RootIndex expected, Tagged<Map> map) {
176 return V8HeapCompressionScheme::CompressObject(map.ptr()) ==
177 StaticReadOnlyRootsPointerTable[static_cast<size_t>(expected)];
178}
179
180inline bool CheckInstanceMapRange(TaggedAddressRange expected,
181 Tagged<Map> map) {
183 return base::IsInRange(ptr, expected.first, expected.second);
184}
185
186#else
187
188inline bool MayHaveMapCheckFastCase(InstanceType type) { return false; }
189
190#endif // V8_STATIC_ROOTS_BOOL
191
192// Define type checkers for classes with single instance type.
193// INSTANCE_TYPE_CHECKER1 is to be used if the instance type is already loaded.
194// INSTANCE_TYPE_CHECKER2 is preferred since it can sometimes avoid loading the
195// instance type from the map, if the checked instance type corresponds to a
196// known map or range of maps.
197
198#define INSTANCE_TYPE_CHECKER1(type, forinstancetype) \
199 V8_INLINE constexpr bool Is##type(InstanceType instance_type) { \
200 return instance_type == forinstancetype; \
201 }
202
203#if V8_STATIC_ROOTS_BOOL
204
205#define INSTANCE_TYPE_CHECKER2(type, forinstancetype_) \
206 V8_INLINE bool Is##type(Tagged<Map> map_object) { \
207 constexpr InstanceType forinstancetype = \
208 static_cast<InstanceType>(forinstancetype_); \
209 if constexpr (constexpr std::optional<RootIndex> index = \
210 UniqueMapOfInstanceType(forinstancetype)) { \
211 return CheckInstanceMap(*index, map_object); \
212 } \
213 if constexpr (constexpr std::optional<TaggedAddressRange> map_range = \
214 UniqueMapRangeOfInstanceType(forinstancetype)) { \
215 return CheckInstanceMapRange(*map_range, map_object); \
216 } \
217 return Is##type(map_object->instance_type()); \
218 }
219
220#else
221
222#define INSTANCE_TYPE_CHECKER2(type, forinstancetype) \
223 V8_INLINE bool Is##type(Tagged<Map> map_object) { \
224 return Is##type(map_object->instance_type()); \
225 }
226
227#endif // V8_STATIC_ROOTS_BOOL
228
231#undef INSTANCE_TYPE_CHECKER1
232#undef INSTANCE_TYPE_CHECKER2
233
234// Checks if value is in range [lower_limit, higher_limit] using a single
235// branch. Assumes that the input instance type is valid.
236template <InstanceType lower_limit, InstanceType upper_limit>
238 static constexpr bool Check(InstanceType value) {
239 return base::IsInRange(value, lower_limit, upper_limit);
240 }
241};
242template <InstanceType upper_limit>
243struct InstanceRangeChecker<FIRST_TYPE, upper_limit> {
244 static constexpr bool Check(InstanceType value) {
245 DCHECK_LE(FIRST_TYPE, value);
246 return value <= upper_limit;
247 }
248};
249template <InstanceType lower_limit>
250struct InstanceRangeChecker<lower_limit, LAST_TYPE> {
251 static constexpr bool Check(InstanceType value) {
252 DCHECK_GE(LAST_TYPE, value);
253 return value >= lower_limit;
254 }
255};
256
257// Define type checkers for classes with ranges of instance types.
258// INSTANCE_TYPE_CHECKER_RANGE1 is to be used if the instance type is already
259// loaded. INSTANCE_TYPE_CHECKER_RANGE2 is preferred since it can sometimes
260// avoid loading the instance type from the map, if the checked instance type
261// range corresponds to a known range of maps.
262
263#define INSTANCE_TYPE_CHECKER_RANGE1(type, first_instance_type, \
264 last_instance_type) \
265 V8_INLINE constexpr bool Is##type(InstanceType instance_type) { \
266 return InstanceRangeChecker<first_instance_type, \
267 last_instance_type>::Check(instance_type); \
268 }
269
270#if V8_STATIC_ROOTS_BOOL
271
272#define INSTANCE_TYPE_CHECKER_RANGE2(type, first_instance_type, \
273 last_instance_type) \
274 V8_INLINE bool Is##type(Tagged<Map> map_object) { \
275 if constexpr (constexpr std::optional<TaggedAddressRange> maybe_range = \
276 UniqueMapRangeOfInstanceTypeRange(first_instance_type, \
277 last_instance_type)) { \
278 return CheckInstanceMapRange(*maybe_range, map_object); \
279 } \
280 return Is##type(map_object->instance_type()); \
281 }
282
283#else
284
285#define INSTANCE_TYPE_CHECKER_RANGE2(type, first_instance_type, \
286 last_instance_type) \
287 V8_INLINE bool Is##type(Tagged<Map> map_object) { \
288 return Is##type(map_object->instance_type()); \
289 }
290
291#endif // V8_STATIC_ROOTS_BOOL
292
295#undef INSTANCE_TYPE_CHECKER_RANGE1
296#undef INSTANCE_TYPE_CHECKER_RANGE2
297
298V8_INLINE constexpr bool IsHeapObject(InstanceType instance_type) {
299 return true;
300}
301
302V8_INLINE constexpr bool IsInternalizedString(InstanceType instance_type) {
303 static_assert(kNotInternalizedTag != 0);
304 return (instance_type & (kIsNotStringMask | kIsNotInternalizedMask)) ==
306}
307
309#if V8_STATIC_ROOTS_BOOL
310 return CheckInstanceMapRange(kUniqueMapRangeOfStringType::kInternalizedString,
311 map_object);
312#else
313 return IsInternalizedString(map_object->instance_type());
314#endif
315}
316
317V8_INLINE constexpr bool IsSeqString(InstanceType instance_type) {
318 return (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
320}
321
323#if V8_STATIC_ROOTS_BOOL
324 return CheckInstanceMapRange(kUniqueMapRangeOfStringType::kSeqString,
325 map_object);
326#else
327 return IsSeqString(map_object->instance_type());
328#endif
329}
330
331V8_INLINE constexpr bool IsExternalString(InstanceType instance_type) {
332 return (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
334}
335
337#if V8_STATIC_ROOTS_BOOL
338 return CheckInstanceMapRange(kUniqueMapRangeOfStringType::kExternalString,
339 map_object);
340#else
341 return IsExternalString(map_object->instance_type());
342#endif
343}
344
350
352#if V8_STATIC_ROOTS_BOOL
353 return CheckInstanceMapRange(
354 kUniqueMapRangeOfStringType::kUncachedExternalString, map_object);
355#else
356 return IsUncachedExternalString(map_object->instance_type());
357#endif
358}
359
360V8_INLINE constexpr bool IsConsString(InstanceType instance_type) {
361 return (instance_type & kStringRepresentationMask) == kConsStringTag;
362}
363
365#if V8_STATIC_ROOTS_BOOL
366 return CheckInstanceMapRange(kUniqueMapRangeOfStringType::kConsString,
367 map_object);
368#else
369 return IsConsString(map_object->instance_type());
370#endif
371}
372
373V8_INLINE constexpr bool IsSlicedString(InstanceType instance_type) {
374 return (instance_type & kStringRepresentationMask) == kSlicedStringTag;
375}
376
378#if V8_STATIC_ROOTS_BOOL
379 return CheckInstanceMapRange(kUniqueMapRangeOfStringType::kSlicedString,
380 map_object);
381#else
382 return IsSlicedString(map_object->instance_type());
383#endif
384}
385
386V8_INLINE constexpr bool IsThinString(InstanceType instance_type) {
387 return (instance_type & kStringRepresentationMask) == kThinStringTag;
388}
389
391#if V8_STATIC_ROOTS_BOOL
392 return CheckInstanceMapRange(kUniqueMapRangeOfStringType::kThinString,
393 map_object);
394#else
395 return IsThinString(map_object->instance_type());
396#endif
397}
398
399V8_INLINE constexpr bool IsOneByteString(InstanceType instance_type) {
400 DCHECK(IsString(instance_type));
401 return (instance_type & kStringEncodingMask) == kOneByteStringTag;
402}
403
405#if V8_STATIC_ROOTS_BOOL
406 DCHECK(IsStringMap(map_object));
407
409 return (ptr & kStringMapEncodingMask) == kOneByteStringMapBit;
410#else
411 return IsOneByteString(map_object->instance_type());
412#endif
413}
414
415V8_INLINE constexpr bool IsTwoByteString(InstanceType instance_type) {
416 DCHECK(IsString(instance_type));
417 return (instance_type & kStringEncodingMask) == kTwoByteStringTag;
418}
419
421#if V8_STATIC_ROOTS_BOOL
422 DCHECK(IsStringMap(map_object));
423
425 return (ptr & kStringMapEncodingMask) == kTwoByteStringMapBit;
426#else
427 return IsTwoByteString(map_object->instance_type());
428#endif
429}
430
431V8_INLINE constexpr bool IsReferenceComparable(InstanceType instance_type) {
432 return !IsString(instance_type) && !IsBigInt(instance_type) &&
433 instance_type != HEAP_NUMBER_TYPE;
434}
435
436V8_INLINE constexpr bool IsGcSafeCode(InstanceType instance_type) {
437 return IsCode(instance_type);
438}
439
441 return IsCode(map_object);
442}
443
444V8_INLINE constexpr bool IsAbstractCode(InstanceType instance_type) {
445 return IsBytecodeArray(instance_type) || IsCode(instance_type);
446}
447
449 return IsAbstractCode(map_object->instance_type());
450}
451
452V8_INLINE constexpr bool IsFreeSpaceOrFiller(InstanceType instance_type) {
453 return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
454}
455
457 return IsFreeSpaceOrFiller(map_object->instance_type());
458}
459
460// These JSObject types are wrappers around a set of primitive values
461// and exist only for the purpose of passing the data across V8 Api.
462// They are not supposed to be ever leaked to user JS code and their maps
463// are not supposed to be ever extended or changed.
464V8_INLINE constexpr bool IsMaybeReadOnlyJSObject(InstanceType instance_type) {
465 return IsJSExternalObject(instance_type) || IsJSMessageObject(instance_type);
466}
467
469 return IsMaybeReadOnlyJSObject(map_object->instance_type());
470}
471
472V8_INLINE constexpr bool IsPropertyDictionary(InstanceType instance_type) {
473 return instance_type == PROPERTY_DICTIONARY_TYPE;
474}
475
477 return IsPropertyDictionary(map_object->instance_type());
478}
479
480// Returns true for those heap object types that must be tied to some native
481// context.
482V8_INLINE constexpr bool IsNativeContextSpecific(InstanceType instance_type) {
483 // All context map are tied to some native context.
484 if (IsContext(instance_type)) return true;
485 // All non-JSReceivers are never tied to any native context.
486 if (!IsJSReceiver(instance_type)) return false;
487
488 // Most of the JSReceivers are tied to some native context modulo the
489 // following exceptions.
490 if (instance_type == JS_MESSAGE_OBJECT_TYPE ||
491 instance_type == JS_EXTERNAL_OBJECT_TYPE) {
492 // These JSObject types are wrappers around a set of primitive values
493 // and exist only for the purpose of passing the data across V8 Api.
494 // Thus they are not tied to any native context.
495 return false;
496
497 } else if (InstanceTypeChecker::IsAlwaysSharedSpaceJSObject(instance_type)) {
498 // JSObjects allocated in shared space are never tied to a native context.
499 return false;
500
501#if V8_ENABLE_WEBASSEMBLY
502 } else if (InstanceTypeChecker::IsWasmObject(instance_type)) {
503 // Wasm structs/arrays are not tied to a native context.
504 return false;
505#endif
506 }
507 return true;
508}
509
511 return IsNativeContextSpecific(map_object->instance_type());
512}
513
514} // namespace InstanceTypeChecker
515
516#define TYPE_CHECKER(type, ...) \
517 bool Is##type##Map(Tagged<Map> map) { \
518 return InstanceTypeChecker::Is##type(map); \
519 }
520
522#undef TYPE_CHECKER
523
524} // namespace v8::internal
525
527
528#endif // V8_OBJECTS_INSTANCE_TYPE_INL_H_
static constexpr std::optional< RootIndex > TryGetMapRootIdxFor(InstanceType type)
Definition map.h:891
V8_INLINE constexpr StorageType ptr() const
static V8_INLINE Tagged_t CompressObject(Address tagged)
#define TYPE_CHECKER(type,...)
#define INSTANCE_TYPE_CHECKERS_SINGLE(V)
#define INSTANCE_TYPE_CHECKERS_RANGE(V)
#define INSTANCE_TYPE_CHECKERS(V)
#define DECL_TYPE(type,...)
#define INSTANCE_TYPE_CHECKER2(type, forinstancetype)
#define INSTANCE_TYPE_MAP(V, rootIndexName, rootAccessorName, class_name)
#define INSTANCE_TYPE_CHECK(it, forinstancetype)
#define INSTANCE_TYPE_CHECKER_RANGE1(type, first_instance_type, last_instance_type)
#define INSTANCE_TYPE_CHECKER1(type, forinstancetype)
#define INSTANCE_TYPE_CHECKER_RANGE2(type, first_instance_type, last_instance_type)
#define UNIQUE_INSTANCE_TYPE_MAP_LIST_GENERATOR(V, _)
#define _
constexpr unsigned CountTrailingZerosNonZero(T value)
Definition bits.h:173
constexpr bool IsInRange(T value, U lower_limit, U higher_limit)
Definition bounds.h:20
V8_INLINE constexpr bool IsSeqString(InstanceType instance_type)
V8_INLINE constexpr bool IsThinString(InstanceType instance_type)
std::pair< InstanceType, InstanceType > InstanceTypeRange
V8_INLINE constexpr bool IsGcSafeCode(InstanceType instance_type)
V8_INLINE constexpr bool IsConsString(InstanceType instance_type)
bool MayHaveMapCheckFastCase(InstanceType type)
V8_INLINE constexpr bool IsExternalString(InstanceType instance_type)
V8_INLINE constexpr bool IsOneByteString(InstanceType instance_type)
V8_INLINE constexpr bool IsInternalizedString(InstanceType instance_type)
V8_INLINE consteval std::optional< RootIndex > UniqueMapOfInstanceTypeCheck()
V8_INLINE bool IsNativeContextSpecificMap(Tagged< Map > map_object)
V8_INLINE constexpr std::optional< RootIndex > UniqueMapOfInstanceType(InstanceType type)
V8_INLINE constexpr bool IsPropertyDictionary(InstanceType instance_type)
V8_INLINE constexpr bool IsNativeContextSpecific(InstanceType instance_type)
V8_INLINE constexpr bool IsAbstractCode(InstanceType instance_type)
V8_INLINE constexpr bool IsFreeSpaceOrFiller(InstanceType instance_type)
V8_INLINE constexpr bool IsMaybeReadOnlyJSObject(InstanceType instance_type)
V8_INLINE constexpr bool IsReferenceComparable(InstanceType instance_type)
std::pair< Tagged_t, Tagged_t > TaggedAddressRange
V8_INLINE constexpr bool IsSlicedString(InstanceType instance_type)
V8_INLINE constexpr bool IsUncachedExternalString(InstanceType instance_type)
V8_INLINE constexpr bool IsTwoByteString(InstanceType instance_type)
V8_INLINE constexpr bool IsHeapObject(InstanceType instance_type)
const uint32_t kStringEncodingMask
const uint32_t kTwoByteStringTag
constexpr InstanceType LAST_STRING_TYPE
const uint32_t kUncachedExternalStringTag
static constexpr InstanceType PROPERTY_DICTIONARY_TYPE
const uint32_t kUncachedExternalStringMask
const uint32_t kNotInternalizedTag
Address Tagged_t
Definition globals.h:547
const uint32_t kStringTag
const uint32_t kOneByteStringTag
const uint32_t kStringRepresentationMask
const uint32_t kInternalizedTag
const uint32_t kIsNotInternalizedMask
const uint32_t kIsNotStringMask
#define HEAP_OBJECT_TYPE_LIST(V)
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
static constexpr bool Check(InstanceType value)
#define V8_INLINE
Definition v8config.h:500