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 | |
15 | namespace dart { |
16 | |
17 | // Size of the class-id part of the object header. See ObjectLayout. |
18 | typedef 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 | |
186 | enum 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. |
233 | const int kTypedDataCidRemainderInternal = 0; |
234 | const int kTypedDataCidRemainderView = 1; |
235 | const int kTypedDataCidRemainderExternal = 2; |
236 | |
237 | // Class Id predicates. |
238 | |
239 | bool IsErrorClassId(intptr_t index); |
240 | bool IsNumberClassId(intptr_t index); |
241 | bool IsIntegerClassId(intptr_t index); |
242 | bool IsStringClassId(intptr_t index); |
243 | bool IsOneByteStringClassId(intptr_t index); |
244 | bool IsTwoByteStringClassId(intptr_t index); |
245 | bool IsExternalStringClassId(intptr_t index); |
246 | bool IsBuiltinListClassId(intptr_t index); |
247 | bool IsTypedDataBaseClassId(intptr_t index); |
248 | bool IsTypedDataClassId(intptr_t index); |
249 | bool IsTypedDataViewClassId(intptr_t index); |
250 | bool IsExternalTypedDataClassId(intptr_t index); |
251 | bool IsFfiNativeTypeTypeClassId(intptr_t index); |
252 | bool IsFfiPointerClassId(intptr_t index); |
253 | bool IsFfiTypeClassId(intptr_t index); |
254 | bool IsFfiTypeIntClassId(intptr_t index); |
255 | bool IsFfiTypeDoubleClassId(intptr_t index); |
256 | bool IsFfiTypeVoidClassId(intptr_t index); |
257 | bool IsFfiTypeNativeFunctionClassId(intptr_t index); |
258 | bool IsFfiDynamicLibraryClassId(intptr_t index); |
259 | bool IsFfiClassId(intptr_t index); |
260 | bool IsInternalVMdefinedClassId(intptr_t index); |
261 | bool IsVariableSizeClassId(intptr_t index); |
262 | bool IsImplicitFieldClassId(intptr_t index); |
263 | intptr_t NumberOfTypedDataClasses(); |
264 | |
265 | inline 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 | |
274 | inline 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 | |
281 | inline 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 | |
287 | inline 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 | |
296 | inline 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 | |
305 | inline 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 | |
314 | inline 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 | |
324 | inline 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 | |
332 | inline 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 | |
338 | inline 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 | |
345 | inline 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 | |
355 | inline 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 | |
364 | inline bool IsFfiNativeTypeTypeClassId(intptr_t index) { |
365 | return index == kFfiNativeTypeCid; |
366 | } |
367 | |
368 | inline 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 | |
386 | inline bool IsFfiTypeIntClassId(intptr_t index) { |
387 | return (index >= kFfiInt8Cid && index <= kFfiIntPtrCid); |
388 | } |
389 | |
390 | inline bool IsFfiTypeDoubleClassId(intptr_t index) { |
391 | return (index >= kFfiFloatCid && index <= kFfiDoubleCid); |
392 | } |
393 | |
394 | inline bool IsFfiPointerClassId(intptr_t index) { |
395 | return index == kFfiPointerCid; |
396 | } |
397 | |
398 | inline bool IsFfiTypeVoidClassId(intptr_t index) { |
399 | return index == kFfiVoidCid; |
400 | } |
401 | |
402 | inline bool IsFfiTypeNativeFunctionClassId(intptr_t index) { |
403 | return index == kFfiNativeFunctionCid; |
404 | } |
405 | |
406 | inline bool IsFfiClassId(intptr_t index) { |
407 | return (index >= kFfiPointerCid && index <= kFfiVoidCid); |
408 | } |
409 | |
410 | inline bool IsFfiDynamicLibraryClassId(intptr_t index) { |
411 | return index == kFfiDynamicLibraryCid; |
412 | } |
413 | |
414 | inline bool IsInternalVMdefinedClassId(intptr_t index) { |
415 | return ((index < kNumPredefinedCids) && !IsImplicitFieldClassId(index)); |
416 | } |
417 | |
418 | inline 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. |
435 | inline bool IsImplicitFieldClassId(intptr_t index) { |
436 | return index == kByteBufferCid; |
437 | } |
438 | |
439 | inline 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 | |