Flutter Engine
The Flutter Engine
class_id.h
Go to the documentation of this file.
1// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_CLASS_ID_H_
6#define RUNTIME_VM_CLASS_ID_H_
7
8// This header defines the list of VM implementation classes and their ids.
9//
10// Note: we assume that all builds of Dart VM use exactly the same class ids
11// for these classes.
12
13#include "platform/assert.h"
14#include "vm/globals.h"
15
16namespace dart {
17
18// Large enough to contain the class-id part of the object header. See
19// UntaggedObject. Signed to be comparable to intptr_t.
20typedef int32_t ClassIdTagType;
21
22static constexpr intptr_t kClassIdTagMax = (1 << 20) - 1;
23
24// Classes that are not subclasses of Instance and only handled by the VM,
25// but do not require any special handling other than being a predefined class.
26#define CLASS_LIST_INTERNAL_ONLY(V) \
27 V(Class) \
28 V(PatchClass) \
29 V(Function) \
30 V(TypeParameters) \
31 V(ClosureData) \
32 V(FfiTrampolineData) \
33 V(Field) \
34 V(Script) \
35 V(Library) \
36 V(Namespace) \
37 V(KernelProgramInfo) \
38 V(WeakSerializationReference) \
39 V(WeakArray) \
40 V(Code) \
41 V(Instructions) \
42 V(InstructionsSection) \
43 V(InstructionsTable) \
44 V(ObjectPool) \
45 V(PcDescriptors) \
46 V(CodeSourceMap) \
47 V(CompressedStackMaps) \
48 V(LocalVarDescriptors) \
49 V(ExceptionHandlers) \
50 V(Context) \
51 V(ContextScope) \
52 V(Sentinel) \
53 V(SingleTargetCache) \
54 V(UnlinkedCall) \
55 V(MonomorphicSmiableCall) \
56 V(CallSiteData) \
57 V(ICData) \
58 V(MegamorphicCache) \
59 V(SubtypeTestCache) \
60 V(LoadingUnit) \
61 V(Error) \
62 V(ApiError) \
63 V(LanguageError) \
64 V(UnhandledException) \
65 V(UnwindError)
66
67// Classes that are subclasses of Instance and neither part of a specific cid
68// grouping like strings, arrays, etc. nor require special handling outside of
69// being a predefined class.
70#define CLASS_LIST_INSTANCE_SINGLETONS(V) \
71 V(Instance) \
72 V(LibraryPrefix) \
73 V(TypeArguments) \
74 V(AbstractType) \
75 V(Type) \
76 V(FunctionType) \
77 V(RecordType) \
78 V(TypeParameter) \
79 V(FinalizerBase) \
80 V(Finalizer) \
81 V(NativeFinalizer) \
82 V(FinalizerEntry) \
83 V(Closure) \
84 V(Number) \
85 V(Integer) \
86 V(Smi) \
87 V(Mint) \
88 V(Double) \
89 V(Bool) \
90 V(Float32x4) \
91 V(Int32x4) \
92 V(Float64x2) \
93 V(Record) \
94 V(TypedDataBase) \
95 V(TypedData) \
96 V(ExternalTypedData) \
97 V(TypedDataView) \
98 V(Pointer) \
99 V(DynamicLibrary) \
100 V(Capability) \
101 V(ReceivePort) \
102 V(SendPort) \
103 V(StackTrace) \
104 V(SuspendState) \
105 V(RegExp) \
106 V(WeakProperty) \
107 V(WeakReference) \
108 V(MirrorReference) \
109 V(FutureOr) \
110 V(UserTag) \
111 V(TransferableTypedData)
112
113#define CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(V) \
114 CLASS_LIST_INTERNAL_ONLY(V) CLASS_LIST_INSTANCE_SINGLETONS(V)
115
116#define CLASS_LIST_MAPS(V) \
117 V(Map) \
118 V(ConstMap)
119
120#define CLASS_LIST_SETS(V) \
121 V(Set) \
122 V(ConstSet)
123
124#define CLASS_LIST_FIXED_LENGTH_ARRAYS(V) \
125 V(Array) \
126 V(ImmutableArray)
127
128#define CLASS_LIST_ARRAYS(V) \
129 CLASS_LIST_FIXED_LENGTH_ARRAYS(V) \
130 V(GrowableObjectArray)
131
132#define CLASS_LIST_STRINGS(V) \
133 V(String) \
134 V(OneByteString) \
135 V(TwoByteString)
136
137#define CLASS_LIST_TYPED_DATA(V) \
138 V(Int8Array) \
139 V(Uint8Array) \
140 V(Uint8ClampedArray) \
141 V(Int16Array) \
142 V(Uint16Array) \
143 V(Int32Array) \
144 V(Uint32Array) \
145 V(Int64Array) \
146 V(Uint64Array) \
147 V(Float32Array) \
148 V(Float64Array) \
149 V(Float32x4Array) \
150 V(Int32x4Array) \
151 V(Float64x2Array)
152
153#define CLASS_LIST_FFI_NUMERIC_FIXED_SIZE(V) \
154 V(Int8) \
155 V(Int16) \
156 V(Int32) \
157 V(Int64) \
158 V(Uint8) \
159 V(Uint16) \
160 V(Uint32) \
161 V(Uint64) \
162 V(Float) \
163 V(Double)
164
165#define CLASS_LIST_FFI_TYPE_MARKER(V) \
166 CLASS_LIST_FFI_NUMERIC_FIXED_SIZE(V) \
167 V(Void) \
168 V(Handle) \
169 V(Bool)
170
171#define CLASS_LIST_FFI(V) \
172 V(NativeFunction) \
173 CLASS_LIST_FFI_TYPE_MARKER(V) \
174 V(NativeType) \
175 V(Struct)
176
177#define DART_CLASS_LIST_TYPED_DATA(V) \
178 V(Int8) \
179 V(Uint8) \
180 V(Uint8Clamped) \
181 V(Int16) \
182 V(Uint16) \
183 V(Int32) \
184 V(Uint32) \
185 V(Int64) \
186 V(Uint64) \
187 V(Float32) \
188 V(Float64) \
189 V(Float32x4) \
190 V(Int32x4) \
191 V(Float64x2)
192
193#define CLASS_LIST_FOR_HANDLES(V) \
194 CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(V) \
195 V(Map) \
196 V(Set) \
197 V(Array) \
198 V(GrowableObjectArray) \
199 V(String)
200
201#define CLASS_LIST_NO_OBJECT(V) \
202 CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(V) \
203 CLASS_LIST_MAPS(V) \
204 CLASS_LIST_SETS(V) \
205 CLASS_LIST_ARRAYS(V) \
206 CLASS_LIST_STRINGS(V)
207
208#define CLASS_LIST(V) \
209 V(Object) \
210 CLASS_LIST_NO_OBJECT(V)
211
212enum ClassId : intptr_t {
213 // Illegal class id.
215
216 // Pseudo class id for native pointers, the heap should never see an
217 // object with this class id.
219
220 // The following entries describes classes for pseudo-objects in the heap
221 // that should never be reachable from live objects. Free list elements
222 // maintain the free list for old space, and forwarding corpses are used to
223 // implement one-way become.
226
227// List of Ids for predefined classes.
228#define DEFINE_OBJECT_KIND(clazz) k##clazz##Cid,
230#undef DEFINE_OBJECT_KIND
231
232// clang-format off
233#define DEFINE_OBJECT_KIND(clazz) kFfi##clazz##Cid,
235#undef DEFINE_OBJECT_KIND
236
237#define DEFINE_OBJECT_KIND(clazz) \
238 kTypedData##clazz##Cid, \
239 kTypedData##clazz##ViewCid, \
240 kExternalTypedData##clazz##Cid, \
241 kUnmodifiableTypedData##clazz##ViewCid,
243#undef DEFINE_OBJECT_KIND
246
248 // clang-format on
249
250 // The following entries do not describe a predefined class, but instead
251 // are class indexes for pre-allocated instances (Null, dynamic, void, Never).
256
258};
259
260// Keep these in sync with the cid numbering above.
266
267// Class Id predicates.
268
269bool IsInternalOnlyClassId(intptr_t index);
270bool IsErrorClassId(intptr_t index);
271bool IsNumberClassId(intptr_t index);
272bool IsIntegerClassId(intptr_t index);
273bool IsStringClassId(intptr_t index);
274bool IsOneByteStringClassId(intptr_t index);
275bool IsBuiltinListClassId(intptr_t index);
276bool IsTypeClassId(intptr_t index);
277bool IsTypedDataBaseClassId(intptr_t index);
278bool IsTypedDataClassId(intptr_t index);
279bool IsTypedDataViewClassId(intptr_t index);
280bool IsExternalTypedDataClassId(intptr_t index);
281bool IsFfiPointerClassId(intptr_t index);
282bool IsFfiTypeClassId(intptr_t index);
283bool IsFfiDynamicLibraryClassId(intptr_t index);
284bool IsInternalVMdefinedClassId(intptr_t index);
285bool IsImplicitFieldClassId(intptr_t index);
286
287// Should be used for looping over non-Object internal-only cids.
288constexpr intptr_t kFirstInternalOnlyCid = kClassCid;
289constexpr intptr_t kLastInternalOnlyCid = kUnwindErrorCid;
290// Use the currently surrounding cids to check that no new classes have been
291// added to the beginning or end of CLASS_LIST_INTERNAL_ONLY without adjusting
292// the above definitions.
295
296// Returns true for any class id that either does not correspond to a real
297// class, like kIllegalCid or kForwardingCorpse, or that is internal to the VM
298// and should not be exposed directly to user code.
299inline bool IsInternalOnlyClassId(intptr_t index) {
300 // Fix the condition below if these become non-contiguous.
304 kIllegalCid + 4 == kObjectCid &&
306 return index <= kLastInternalOnlyCid;
307}
308
309// Make sure this function is updated when new Error types are added.
310static const ClassId kFirstErrorCid = kErrorCid;
311static const ClassId kLastErrorCid = kUnwindErrorCid;
313 kApiErrorCid == kFirstErrorCid + 1 &&
314 kLanguageErrorCid == kFirstErrorCid + 2 &&
315 kUnhandledExceptionCid == kFirstErrorCid + 3 &&
316 kUnwindErrorCid == kFirstErrorCid + 4 &&
317 kLastErrorCid == kUnwindErrorCid &&
318 // Change if needed for detecting a new error added at the end.
320
321inline bool IsErrorClassId(intptr_t index) {
322 return (index >= kFirstErrorCid && index <= kLastErrorCid);
323}
324
325inline bool IsConcreteTypeClassId(intptr_t index) {
326 // Make sure to update when new AbstractType subclasses are added.
327 COMPILE_ASSERT(kFunctionTypeCid == kTypeCid + 1 &&
328 kRecordTypeCid == kTypeCid + 2 &&
329 kTypeParameterCid == kTypeCid + 3);
330 return (index >= kTypeCid && index <= kTypeParameterCid);
331}
332
333inline bool IsNumberClassId(intptr_t index) {
334 // Make sure this function is updated when new Number types are added.
335 COMPILE_ASSERT(kIntegerCid == kNumberCid + 1 && kSmiCid == kNumberCid + 2 &&
336 kMintCid == kNumberCid + 3 && kDoubleCid == kNumberCid + 4);
337 return (index >= kNumberCid && index <= kDoubleCid);
338}
339
340inline bool IsIntegerClassId(intptr_t index) {
341 // Make sure this function is updated when new Integer types are added.
342 COMPILE_ASSERT(kSmiCid == kIntegerCid + 1 && kMintCid == kIntegerCid + 2);
343 return (index >= kIntegerCid && index <= kMintCid);
344}
345
346// Make sure this check is updated when new StringCid types are added.
347COMPILE_ASSERT(kOneByteStringCid == kStringCid + 1 &&
348 kTwoByteStringCid == kStringCid + 2);
349
350inline bool IsStringClassId(intptr_t index) {
351 return (index >= kStringCid && index <= kTwoByteStringCid);
352}
353
354inline bool IsOneByteStringClassId(intptr_t index) {
355 return (index == kOneByteStringCid);
356}
357
358inline bool IsArrayClassId(intptr_t index) {
359 COMPILE_ASSERT(kImmutableArrayCid == kArrayCid + 1);
360 COMPILE_ASSERT(kGrowableObjectArrayCid == kArrayCid + 2);
361 return (index >= kArrayCid && index <= kGrowableObjectArrayCid);
362}
363
364inline bool IsBuiltinListClassId(intptr_t index) {
365 // Make sure this function is updated when new builtin List types are added.
366 return (IsArrayClassId(index) || IsTypedDataBaseClassId(index) ||
367 (index == kByteBufferCid));
368}
369
370inline bool IsTypeClassId(intptr_t index) {
371 // Only Type, FunctionType and RecordType can be encountered as instance
372 // types at runtime.
373 return index == kTypeCid || index == kFunctionTypeCid ||
374 index == kRecordTypeCid;
375}
376
377static const ClassId kFirstTypedDataCid = kTypedDataInt8ArrayCid;
379 kUnmodifiableTypedDataFloat64x2ArrayViewCid;
380
381// Make sure the following checks are updated when adding new TypedData types.
382
383// The following asserts assume this.
385// Ensure that each typed data type comes in internal/view/external variants
386// next to each other.
388 kTypedDataInt8ArrayViewCid);
389COMPILE_ASSERT(kTypedDataInt8ArrayCid + kTypedDataCidRemainderExternal ==
390 kExternalTypedDataInt8ArrayCid);
391COMPILE_ASSERT(kTypedDataInt8ArrayCid + kTypedDataCidRemainderUnmodifiable ==
392 kUnmodifiableTypedDataInt8ArrayViewCid);
393// Ensure the order of the typed data members in 3-step.
394COMPILE_ASSERT(kFirstTypedDataCid == kTypedDataInt8ArrayCid);
396 kTypedDataUint8ArrayCid);
398 kTypedDataUint8ClampedArrayCid);
400 kTypedDataInt16ArrayCid);
402 kTypedDataUint16ArrayCid);
404 kTypedDataInt32ArrayCid);
406 kTypedDataUint32ArrayCid);
408 kTypedDataInt64ArrayCid);
410 kTypedDataUint64ArrayCid);
412 kTypedDataFloat32ArrayCid);
414 kTypedDataFloat64ArrayCid);
416 kTypedDataFloat32x4ArrayCid);
418 kTypedDataInt32x4ArrayCid);
420 kTypedDataFloat64x2ArrayCid);
424// Checks for possible new typed data entries added before or after the current
425// entries.
426COMPILE_ASSERT(kFfiStructCid + 1 == kFirstTypedDataCid);
428
429inline bool IsTypedDataBaseClassId(intptr_t index) {
430 return index >= kFirstTypedDataCid && index <= kLastTypedDataCid;
431}
432
433inline bool IsTypedDataClassId(intptr_t index) {
434 return IsTypedDataBaseClassId(index) &&
437}
438
439inline bool IsTypedDataViewClassId(intptr_t index) {
440 const bool is_byte_data_view = index == kByteDataViewCid;
441 return is_byte_data_view ||
442 (IsTypedDataBaseClassId(index) &&
445}
446
447inline bool IsExternalTypedDataClassId(intptr_t index) {
448 return IsTypedDataBaseClassId(index) &&
451}
452
453inline bool IsUnmodifiableTypedDataViewClassId(intptr_t index) {
454 const bool is_byte_data_view = index == kUnmodifiableByteDataViewCid;
455 return is_byte_data_view ||
456 (IsTypedDataBaseClassId(index) &&
459}
460
461inline bool IsClampedTypedDataBaseClassId(intptr_t index) {
462 if (!IsTypedDataBaseClassId(index)) return false;
463 const intptr_t internal_cid =
464 index - ((index - kFirstTypedDataCid) % kNumTypedDataCidRemainders) +
466 // Currently, the only clamped typed data arrays are Uint8.
467 return internal_cid == kTypedDataUint8ClampedArrayCid;
468}
469
470// Whether the given cid is an external array cid, that is, an array where
471// the payload is not in GC-managed memory.
473 return cid == kPointerCid || IsExternalTypedDataClassId(cid);
474}
475
476// For predefined cids only. Refer to Class::is_deeply_immutable for
477// instances of non-predefined classes.
478//
479// Having the `@pragma('vm:deeply-immutable')`, which means statically proven
480// deeply immutable, implies true for this function. The other way around is not
481// guaranteed, predefined classes can be marked deeply immutable in the VM while
482// not having their subtypes or super type being deeply immutable.
483//
484// Keep consistent with runtime/docs/deeply_immutable.md.
485inline bool IsDeeplyImmutableCid(intptr_t predefined_cid) {
486 ASSERT(predefined_cid < kNumPredefinedCids);
487 return IsStringClassId(predefined_cid) || predefined_cid == kNumberCid ||
488 predefined_cid == kIntegerCid || predefined_cid == kSmiCid ||
489 predefined_cid == kMintCid || predefined_cid == kNeverCid ||
490 predefined_cid == kSentinelCid || predefined_cid == kStackTraceCid ||
491 predefined_cid == kDoubleCid || predefined_cid == kFloat32x4Cid ||
492 predefined_cid == kFloat64x2Cid || predefined_cid == kInt32x4Cid ||
493 predefined_cid == kSendPortCid || predefined_cid == kCapabilityCid ||
494 predefined_cid == kRegExpCid || predefined_cid == kBoolCid ||
495 predefined_cid == kNullCid || predefined_cid == kPointerCid ||
496 predefined_cid == kTypeCid || predefined_cid == kRecordTypeCid ||
497 predefined_cid == kFunctionTypeCid;
498}
499
500inline bool IsShallowlyImmutableCid(intptr_t predefined_cid) {
501 ASSERT(predefined_cid < kNumPredefinedCids);
502 // TODO(https://dartbug.com/55136): Mark kClosureCid as shallowly imutable.
503 return IsUnmodifiableTypedDataViewClassId(predefined_cid);
504}
505
506// See documentation on ImmutableBit in raw_object.h
507inline bool ShouldHaveImmutabilityBitSetCid(intptr_t predefined_cid) {
508 ASSERT(predefined_cid < kNumPredefinedCids);
509 return IsDeeplyImmutableCid(predefined_cid) ||
510 IsShallowlyImmutableCid(predefined_cid);
511}
512
513inline bool IsFfiTypeClassId(intptr_t index) {
514 switch (index) {
515 case kPointerCid:
516 case kFfiNativeFunctionCid:
517#define CASE_FFI_CID(name) case kFfi##name##Cid:
519#undef CASE_FFI_CID
520 return true;
521 default:
522 return false;
523 }
524 UNREACHABLE();
525}
526
527inline bool IsFfiPredefinedClassId(classid_t class_id) {
528 switch (class_id) {
529 case kPointerCid:
530 case kDynamicLibraryCid:
531#define CASE_FFI_CID(name) case kFfi##name##Cid:
533#undef CASE_FFI_CID
534 return true;
535 default:
536 return false;
537 }
538 UNREACHABLE();
539}
540
541inline bool IsFfiPointerClassId(intptr_t index) {
542 return index == kPointerCid;
543}
544
545inline bool IsFfiDynamicLibraryClassId(intptr_t index) {
546 return index == kDynamicLibraryCid;
547}
548
549inline bool IsInternalVMdefinedClassId(intptr_t index) {
550 return ((index < kNumPredefinedCids) && !IsImplicitFieldClassId(index));
551}
552
553// This is a set of classes that are not Dart classes whose representation
554// is defined by the VM but are used in the VM code by computing the
555// implicit field offsets of the various fields in the dart object.
556inline bool IsImplicitFieldClassId(intptr_t index) {
557 return index == kByteBufferCid;
558}
559
561
562} // namespace dart
563
564#endif // RUNTIME_VM_CLASS_ID_H_
#define UNREACHABLE()
Definition: assert.h:248
#define DEFINE_OBJECT_KIND(clazz)
Definition: class_id.h:237
#define CASE_FFI_CID(name)
#define CLASS_LIST_FFI(V)
Definition: class_id.h:171
#define CLASS_LIST_FFI_TYPE_MARKER(V)
Definition: class_id.h:165
#define CLASS_LIST_TYPED_DATA(V)
Definition: class_id.h:137
#define CLASS_LIST(V)
Definition: class_id.h:208
#define ASSERT(E)
Definition: dart_vm.cc:33
const int kNumTypedDataCidRemainders
Definition: class_id.h:265
static const ClassId kLastTypedDataCid
Definition: class_id.h:378
bool IsTypedDataViewClassId(intptr_t index)
Definition: class_id.h:439
bool IsTypedDataClassId(intptr_t index)
Definition: class_id.h:433
bool IsFfiPredefinedClassId(classid_t class_id)
Definition: class_id.h:527
bool IsOneByteStringClassId(intptr_t index)
Definition: class_id.h:354
bool IsFfiDynamicLibraryClassId(intptr_t index)
Definition: class_id.h:545
bool IsShallowlyImmutableCid(intptr_t predefined_cid)
Definition: class_id.h:500
bool IsConcreteTypeClassId(intptr_t index)
Definition: class_id.h:325
const int kTypedDataCidRemainderUnmodifiable
Definition: class_id.h:264
bool IsTypedDataBaseClassId(intptr_t index)
Definition: class_id.h:429
bool IsImplicitFieldClassId(intptr_t index)
Definition: class_id.h:556
bool IsNumberClassId(intptr_t index)
Definition: class_id.h:333
bool IsTypeClassId(intptr_t index)
Definition: class_id.h:370
const int kTypedDataCidRemainderInternal
Definition: class_id.h:261
bool IsArrayClassId(intptr_t index)
Definition: class_id.h:358
int32_t classid_t
Definition: globals.h:524
static const ClassId kLastErrorCid
Definition: class_id.h:311
bool IsErrorClassId(intptr_t index)
Definition: class_id.h:321
bool IsUnmodifiableTypedDataViewClassId(intptr_t index)
Definition: class_id.h:453
ClassId
Definition: class_id.h:212
@ kForwardingCorpse
Definition: class_id.h:225
@ kIllegalCid
Definition: class_id.h:214
@ kNullCid
Definition: class_id.h:252
@ kNumPredefinedCids
Definition: class_id.h:257
@ kNativePointer
Definition: class_id.h:218
@ kByteDataViewCid
Definition: class_id.h:244
@ kVoidCid
Definition: class_id.h:254
@ kByteBufferCid
Definition: class_id.h:247
@ kDynamicCid
Definition: class_id.h:253
@ kNeverCid
Definition: class_id.h:255
@ kFreeListElement
Definition: class_id.h:224
@ kUnmodifiableByteDataViewCid
Definition: class_id.h:245
bool IsFfiTypeClassId(intptr_t index)
Definition: class_id.h:513
static const ClassId kFirstErrorCid
Definition: class_id.h:310
bool IsClampedTypedDataBaseClassId(intptr_t index)
Definition: class_id.h:461
const int kTypedDataCidRemainderExternal
Definition: class_id.h:263
static const ClassId kFirstTypedDataCid
Definition: class_id.h:377
const int kTypedDataCidRemainderView
Definition: class_id.h:262
bool IsExternalPayloadClassId(classid_t cid)
Definition: class_id.h:472
bool ShouldHaveImmutabilityBitSetCid(intptr_t predefined_cid)
Definition: class_id.h:507
constexpr intptr_t kFirstInternalOnlyCid
Definition: class_id.h:288
bool IsInternalVMdefinedClassId(intptr_t index)
Definition: class_id.h:549
const intptr_t cid
int32_t ClassIdTagType
Definition: class_id.h:20
bool IsFfiPointerClassId(intptr_t index)
Definition: class_id.h:541
bool IsIntegerClassId(intptr_t index)
Definition: class_id.h:340
bool IsInternalOnlyClassId(intptr_t index)
Definition: class_id.h:299
bool IsDeeplyImmutableCid(intptr_t predefined_cid)
Definition: class_id.h:485
bool IsBuiltinListClassId(intptr_t index)
Definition: class_id.h:364
static constexpr intptr_t kClassIdTagMax
Definition: class_id.h:22
bool IsExternalTypedDataClassId(intptr_t index)
Definition: class_id.h:447
COMPILE_ASSERT(kUnreachableReference==WeakTable::kNoValue)
constexpr intptr_t kLastInternalOnlyCid
Definition: class_id.h:289
bool IsStringClassId(intptr_t index)
Definition: class_id.h:350