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
15namespace dart {
16
17// Size of the class-id part of the object header. See ObjectLayout.
18typedef uint16_t ClassIdTagType;
19
20#define CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V) \
21 V(Class) \
22 V(PatchClass) \
23 V(Function) \
24 V(ClosureData) \
25 V(SignatureData) \
26 V(RedirectionData) \
27 V(FfiTrampolineData) \
28 V(Field) \
29 V(Script) \
30 V(Library) \
31 V(Namespace) \
32 V(KernelProgramInfo) \
33 V(Code) \
34 V(Bytecode) \
35 V(Instructions) \
36 V(InstructionsSection) \
37 V(ObjectPool) \
38 V(PcDescriptors) \
39 V(CodeSourceMap) \
40 V(CompressedStackMaps) \
41 V(LocalVarDescriptors) \
42 V(ExceptionHandlers) \
43 V(Context) \
44 V(ContextScope) \
45 V(ParameterTypeCheck) \
46 V(SingleTargetCache) \
47 V(UnlinkedCall) \
48 V(MonomorphicSmiableCall) \
49 V(CallSiteData) \
50 V(ICData) \
51 V(MegamorphicCache) \
52 V(SubtypeTestCache) \
53 V(LoadingUnit) \
54 V(Error) \
55 V(ApiError) \
56 V(LanguageError) \
57 V(UnhandledException) \
58 V(UnwindError) \
59 V(Instance) \
60 V(LibraryPrefix) \
61 V(TypeArguments) \
62 V(AbstractType) \
63 V(Type) \
64 V(TypeRef) \
65 V(TypeParameter) \
66 V(Closure) \
67 V(Number) \
68 V(Integer) \
69 V(Smi) \
70 V(Mint) \
71 V(Double) \
72 V(Bool) \
73 V(GrowableObjectArray) \
74 V(Float32x4) \
75 V(Int32x4) \
76 V(Float64x2) \
77 V(TypedDataBase) \
78 V(TypedData) \
79 V(ExternalTypedData) \
80 V(TypedDataView) \
81 V(Pointer) \
82 V(DynamicLibrary) \
83 V(Capability) \
84 V(ReceivePort) \
85 V(SendPort) \
86 V(StackTrace) \
87 V(RegExp) \
88 V(WeakProperty) \
89 V(MirrorReference) \
90 V(LinkedHashMap) \
91 V(FutureOr) \
92 V(UserTag) \
93 V(TransferableTypedData) \
94 V(WeakSerializationReference)
95
96#define CLASS_LIST_ARRAYS(V) \
97 V(Array) \
98 V(ImmutableArray)
99
100#define CLASS_LIST_STRINGS(V) \
101 V(String) \
102 V(OneByteString) \
103 V(TwoByteString) \
104 V(ExternalOneByteString) \
105 V(ExternalTwoByteString)
106
107#define CLASS_LIST_TYPED_DATA(V) \
108 V(Int8Array) \
109 V(Uint8Array) \
110 V(Uint8ClampedArray) \
111 V(Int16Array) \
112 V(Uint16Array) \
113 V(Int32Array) \
114 V(Uint32Array) \
115 V(Int64Array) \
116 V(Uint64Array) \
117 V(Float32Array) \
118 V(Float64Array) \
119 V(Float32x4Array) \
120 V(Int32x4Array) \
121 V(Float64x2Array)
122
123#define CLASS_LIST_FFI_NUMERIC(V) \
124 V(Int8) \
125 V(Int16) \
126 V(Int32) \
127 V(Int64) \
128 V(Uint8) \
129 V(Uint16) \
130 V(Uint32) \
131 V(Uint64) \
132 V(IntPtr) \
133 V(Float) \
134 V(Double)
135
136#define CLASS_LIST_FFI_TYPE_MARKER(V) \
137 CLASS_LIST_FFI_NUMERIC(V) \
138 V(Void) \
139 V(Handle)
140
141#define CLASS_LIST_FFI(V) \
142 V(Pointer) \
143 V(NativeFunction) \
144 CLASS_LIST_FFI_TYPE_MARKER(V) \
145 V(NativeType) \
146 V(DynamicLibrary) \
147 V(Struct)
148
149#define CLASS_LIST_WASM(V) \
150 V(WasmInt32) \
151 V(WasmInt64) \
152 V(WasmFloat) \
153 V(WasmDouble) \
154 V(WasmVoid)
155
156#define DART_CLASS_LIST_TYPED_DATA(V) \
157 V(Int8) \
158 V(Uint8) \
159 V(Uint8Clamped) \
160 V(Int16) \
161 V(Uint16) \
162 V(Int32) \
163 V(Uint32) \
164 V(Int64) \
165 V(Uint64) \
166 V(Float32) \
167 V(Float64) \
168 V(Float32x4) \
169 V(Int32x4) \
170 V(Float64x2)
171
172#define CLASS_LIST_FOR_HANDLES(V) \
173 CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V) \
174 V(Array) \
175 V(String)
176
177#define CLASS_LIST_NO_OBJECT(V) \
178 CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V) \
179 CLASS_LIST_ARRAYS(V) \
180 CLASS_LIST_STRINGS(V)
181
182#define CLASS_LIST(V) \
183 V(Object) \
184 CLASS_LIST_NO_OBJECT(V)
185
186enum ClassId : intptr_t {
187 // Illegal class id.
188 kIllegalCid = 0,
189
190 // The following entries describes classes for pseudo-objects in the heap
191 // that should never be reachable from live objects. Free list elements
192 // maintain the free list for old space, and forwarding corpses are used to
193 // implement one-way become.
194 kFreeListElement,
195 kForwardingCorpse,
196
197// List of Ids for predefined classes.
198#define DEFINE_OBJECT_KIND(clazz) k##clazz##Cid,
199 CLASS_LIST(DEFINE_OBJECT_KIND)
200#undef DEFINE_OBJECT_KIND
201
202// clang-format off
203#define DEFINE_OBJECT_KIND(clazz) kFfi##clazz##Cid,
204 CLASS_LIST_FFI(DEFINE_OBJECT_KIND)
205#undef DEFINE_OBJECT_KIND
206
207#define DEFINE_OBJECT_KIND(clazz) k##clazz##Cid,
208 CLASS_LIST_WASM(DEFINE_OBJECT_KIND)
209#undef DEFINE_OBJECT_KIND
210
211#define DEFINE_OBJECT_KIND(clazz) \
212 kTypedData##clazz##Cid, \
213 kTypedData##clazz##ViewCid, \
214 kExternalTypedData##clazz##Cid,
215 CLASS_LIST_TYPED_DATA(DEFINE_OBJECT_KIND)
216#undef DEFINE_OBJECT_KIND
217 kByteDataViewCid,
218
219 kByteBufferCid,
220 // clang-format on
221
222 // The following entries do not describe a predefined class, but instead
223 // are class indexes for pre-allocated instances (Null, dynamic, void, Never).
224 kNullCid,
225 kDynamicCid,
226 kVoidCid,
227 kNeverCid,
228
229 kNumPredefinedCids,
230};
231
232// Keep these in sync with the cid numbering above.
233const int kTypedDataCidRemainderInternal = 0;
234const int kTypedDataCidRemainderView = 1;
235const int kTypedDataCidRemainderExternal = 2;
236
237// Class Id predicates.
238
239bool IsErrorClassId(intptr_t index);
240bool IsNumberClassId(intptr_t index);
241bool IsIntegerClassId(intptr_t index);
242bool IsStringClassId(intptr_t index);
243bool IsOneByteStringClassId(intptr_t index);
244bool IsTwoByteStringClassId(intptr_t index);
245bool IsExternalStringClassId(intptr_t index);
246bool IsBuiltinListClassId(intptr_t index);
247bool IsTypedDataBaseClassId(intptr_t index);
248bool IsTypedDataClassId(intptr_t index);
249bool IsTypedDataViewClassId(intptr_t index);
250bool IsExternalTypedDataClassId(intptr_t index);
251bool IsFfiNativeTypeTypeClassId(intptr_t index);
252bool IsFfiPointerClassId(intptr_t index);
253bool IsFfiTypeClassId(intptr_t index);
254bool IsFfiTypeIntClassId(intptr_t index);
255bool IsFfiTypeDoubleClassId(intptr_t index);
256bool IsFfiTypeVoidClassId(intptr_t index);
257bool IsFfiTypeNativeFunctionClassId(intptr_t index);
258bool IsFfiDynamicLibraryClassId(intptr_t index);
259bool IsFfiClassId(intptr_t index);
260bool IsInternalVMdefinedClassId(intptr_t index);
261bool IsVariableSizeClassId(intptr_t index);
262bool IsImplicitFieldClassId(intptr_t index);
263intptr_t NumberOfTypedDataClasses();
264
265inline bool IsErrorClassId(intptr_t index) {
266 // Make sure this function is updated when new Error types are added.
267 COMPILE_ASSERT(
268 kApiErrorCid == kErrorCid + 1 && kLanguageErrorCid == kErrorCid + 2 &&
269 kUnhandledExceptionCid == kErrorCid + 3 &&
270 kUnwindErrorCid == kErrorCid + 4 && kInstanceCid == kErrorCid + 5);
271 return (index >= kErrorCid && index < kInstanceCid);
272}
273
274inline bool IsNumberClassId(intptr_t index) {
275 // Make sure this function is updated when new Number types are added.
276 COMPILE_ASSERT(kIntegerCid == kNumberCid + 1 && kSmiCid == kNumberCid + 2 &&
277 kMintCid == kNumberCid + 3 && kDoubleCid == kNumberCid + 4);
278 return (index >= kNumberCid && index <= kDoubleCid);
279}
280
281inline bool IsIntegerClassId(intptr_t index) {
282 // Make sure this function is updated when new Integer types are added.
283 COMPILE_ASSERT(kSmiCid == kIntegerCid + 1 && kMintCid == kIntegerCid + 2);
284 return (index >= kIntegerCid && index <= kMintCid);
285}
286
287inline bool IsStringClassId(intptr_t index) {
288 // Make sure this function is updated when new StringCid types are added.
289 COMPILE_ASSERT(kOneByteStringCid == kStringCid + 1 &&
290 kTwoByteStringCid == kStringCid + 2 &&
291 kExternalOneByteStringCid == kStringCid + 3 &&
292 kExternalTwoByteStringCid == kStringCid + 4);
293 return (index >= kStringCid && index <= kExternalTwoByteStringCid);
294}
295
296inline bool IsOneByteStringClassId(intptr_t index) {
297 // Make sure this function is updated when new StringCid types are added.
298 COMPILE_ASSERT(kOneByteStringCid == kStringCid + 1 &&
299 kTwoByteStringCid == kStringCid + 2 &&
300 kExternalOneByteStringCid == kStringCid + 3 &&
301 kExternalTwoByteStringCid == kStringCid + 4);
302 return (index == kOneByteStringCid || index == kExternalOneByteStringCid);
303}
304
305inline bool IsTwoByteStringClassId(intptr_t index) {
306 // Make sure this function is updated when new StringCid types are added.
307 COMPILE_ASSERT(kOneByteStringCid == kStringCid + 1 &&
308 kTwoByteStringCid == kStringCid + 2 &&
309 kExternalOneByteStringCid == kStringCid + 3 &&
310 kExternalTwoByteStringCid == kStringCid + 4);
311 return (index == kTwoByteStringCid || index == kExternalTwoByteStringCid);
312}
313
314inline bool IsExternalStringClassId(intptr_t index) {
315 // Make sure this function is updated when new StringCid types are added.
316 COMPILE_ASSERT(kOneByteStringCid == kStringCid + 1 &&
317 kTwoByteStringCid == kStringCid + 2 &&
318 kExternalOneByteStringCid == kStringCid + 3 &&
319 kExternalTwoByteStringCid == kStringCid + 4);
320 return (index == kExternalOneByteStringCid ||
321 index == kExternalTwoByteStringCid);
322}
323
324inline bool IsBuiltinListClassId(intptr_t index) {
325 // Make sure this function is updated when new builtin List types are added.
326 COMPILE_ASSERT(kImmutableArrayCid == kArrayCid + 1);
327 return ((index >= kArrayCid && index <= kImmutableArrayCid) ||
328 (index == kGrowableObjectArrayCid) || IsTypedDataBaseClassId(index) ||
329 (index == kByteBufferCid));
330}
331
332inline bool IsTypedDataBaseClassId(intptr_t index) {
333 // Make sure this is updated when new TypedData types are added.
334 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 3 == kTypedDataUint8ArrayCid);
335 return index >= kTypedDataInt8ArrayCid && index < kByteDataViewCid;
336}
337
338inline bool IsTypedDataClassId(intptr_t index) {
339 // Make sure this is updated when new TypedData types are added.
340 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 3 == kTypedDataUint8ArrayCid);
341 return IsTypedDataBaseClassId(index) && ((index - kTypedDataInt8ArrayCid) %
342 3) == kTypedDataCidRemainderInternal;
343}
344
345inline bool IsTypedDataViewClassId(intptr_t index) {
346 // Make sure this is updated when new TypedData types are added.
347 COMPILE_ASSERT(kTypedDataInt8ArrayViewCid + 3 == kTypedDataUint8ArrayViewCid);
348
349 const bool is_byte_data_view = index == kByteDataViewCid;
350 return is_byte_data_view ||
351 (IsTypedDataBaseClassId(index) &&
352 ((index - kTypedDataInt8ArrayCid) % 3) == kTypedDataCidRemainderView);
353}
354
355inline bool IsExternalTypedDataClassId(intptr_t index) {
356 // Make sure this is updated when new TypedData types are added.
357 COMPILE_ASSERT(kExternalTypedDataInt8ArrayCid + 3 ==
358 kExternalTypedDataUint8ArrayCid);
359
360 return IsTypedDataBaseClassId(index) && ((index - kTypedDataInt8ArrayCid) %
361 3) == kTypedDataCidRemainderExternal;
362}
363
364inline bool IsFfiNativeTypeTypeClassId(intptr_t index) {
365 return index == kFfiNativeTypeCid;
366}
367
368inline bool IsFfiTypeClassId(intptr_t index) {
369 // Make sure this is updated when new Ffi types are added.
370 COMPILE_ASSERT(kFfiNativeFunctionCid == kFfiPointerCid + 1 &&
371 kFfiInt8Cid == kFfiPointerCid + 2 &&
372 kFfiInt16Cid == kFfiPointerCid + 3 &&
373 kFfiInt32Cid == kFfiPointerCid + 4 &&
374 kFfiInt64Cid == kFfiPointerCid + 5 &&
375 kFfiUint8Cid == kFfiPointerCid + 6 &&
376 kFfiUint16Cid == kFfiPointerCid + 7 &&
377 kFfiUint32Cid == kFfiPointerCid + 8 &&
378 kFfiUint64Cid == kFfiPointerCid + 9 &&
379 kFfiIntPtrCid == kFfiPointerCid + 10 &&
380 kFfiFloatCid == kFfiPointerCid + 11 &&
381 kFfiDoubleCid == kFfiPointerCid + 12 &&
382 kFfiVoidCid == kFfiPointerCid + 13);
383 return (index >= kFfiPointerCid && index <= kFfiVoidCid);
384}
385
386inline bool IsFfiTypeIntClassId(intptr_t index) {
387 return (index >= kFfiInt8Cid && index <= kFfiIntPtrCid);
388}
389
390inline bool IsFfiTypeDoubleClassId(intptr_t index) {
391 return (index >= kFfiFloatCid && index <= kFfiDoubleCid);
392}
393
394inline bool IsFfiPointerClassId(intptr_t index) {
395 return index == kFfiPointerCid;
396}
397
398inline bool IsFfiTypeVoidClassId(intptr_t index) {
399 return index == kFfiVoidCid;
400}
401
402inline bool IsFfiTypeNativeFunctionClassId(intptr_t index) {
403 return index == kFfiNativeFunctionCid;
404}
405
406inline bool IsFfiClassId(intptr_t index) {
407 return (index >= kFfiPointerCid && index <= kFfiVoidCid);
408}
409
410inline bool IsFfiDynamicLibraryClassId(intptr_t index) {
411 return index == kFfiDynamicLibraryCid;
412}
413
414inline bool IsInternalVMdefinedClassId(intptr_t index) {
415 return ((index < kNumPredefinedCids) && !IsImplicitFieldClassId(index));
416}
417
418inline bool IsVariableSizeClassId(intptr_t index) {
419 return (index == kArrayCid) || (index == kImmutableArrayCid) ||
420 IsOneByteStringClassId(index) || IsTwoByteStringClassId(index) ||
421 IsTypedDataClassId(index) || (index == kContextCid) ||
422 (index == kTypeArgumentsCid) || (index == kInstructionsCid) ||
423 (index == kInstructionsSectionCid) || (index == kObjectPoolCid) ||
424 (index == kPcDescriptorsCid) || (index == kCodeSourceMapCid) ||
425 (index == kCompressedStackMapsCid) ||
426 (index == kLocalVarDescriptorsCid) ||
427 (index == kExceptionHandlersCid) || (index == kCodeCid) ||
428 (index == kContextScopeCid) || (index == kInstanceCid) ||
429 (index == kRegExpCid);
430}
431
432// This is a set of classes that are not Dart classes whose representation
433// is defined by the VM but are used in the VM code by computing the
434// implicit field offsets of the various fields in the dart object.
435inline bool IsImplicitFieldClassId(intptr_t index) {
436 return index == kByteBufferCid;
437}
438
439inline intptr_t NumberOfTypedDataClasses() {
440 // Make sure this is updated when new TypedData types are added.
441
442 // Ensure that each typed data type comes in internal/view/external variants
443 // next to each other.
444 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 1 == kTypedDataInt8ArrayViewCid);
445 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 2 == kExternalTypedDataInt8ArrayCid);
446
447 // Ensure the order of the typed data members in 3-step.
448 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 1 * 3 == kTypedDataUint8ArrayCid);
449 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 2 * 3 ==
450 kTypedDataUint8ClampedArrayCid);
451 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 3 * 3 == kTypedDataInt16ArrayCid);
452 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 4 * 3 == kTypedDataUint16ArrayCid);
453 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 5 * 3 == kTypedDataInt32ArrayCid);
454 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 6 * 3 == kTypedDataUint32ArrayCid);
455 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 7 * 3 == kTypedDataInt64ArrayCid);
456 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 8 * 3 == kTypedDataUint64ArrayCid);
457 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 9 * 3 == kTypedDataFloat32ArrayCid);
458 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 10 * 3 == kTypedDataFloat64ArrayCid);
459 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 11 * 3 ==
460 kTypedDataFloat32x4ArrayCid);
461 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 12 * 3 == kTypedDataInt32x4ArrayCid);
462 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 13 * 3 ==
463 kTypedDataFloat64x2ArrayCid);
464 COMPILE_ASSERT(kTypedDataInt8ArrayCid + 14 * 3 == kByteDataViewCid);
465 COMPILE_ASSERT(kByteBufferCid + 1 == kNullCid);
466 return (kNullCid - kTypedDataInt8ArrayCid);
467}
468
469} // namespace dart
470
471#endif // RUNTIME_VM_CLASS_ID_H_
472