| // Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| #ifndef RUNTIME_VM_CLASS_ID_H_ | |
| #define RUNTIME_VM_CLASS_ID_H_ | |
| // This header defines the list of VM implementation classes and their ids. | |
| // | |
| // Note: we assume that all builds of Dart VM use exactly the same class ids | |
| // for these classes. | |
| #include "platform/assert.h" | |
| #include "vm/globals.h" | |
| namespace dart { | |
| // Large enough to contain the class-id part of the object header. See | |
| // UntaggedObject. Signed to be comparable to intptr_t. | |
| typedef int32_t ClassIdTagType; | |
| static constexpr intptr_t kClassIdTagMax = (1 << 20) - 1; | |
| // Classes that are not subclasses of Instance and only handled by the VM, | |
| // but do not require any special handling other than being a predefined class. | |
| #define CLASS_LIST_INTERNAL_ONLY(V) \ | |
| V(Class) \ | |
| V(PatchClass) \ | |
| V(Function) \ | |
| V(TypeParameters) \ | |
| V(ClosureData) \ | |
| V(FfiTrampolineData) \ | |
| V(Field) \ | |
| V(Script) \ | |
| V(Library) \ | |
| V(Namespace) \ | |
| V(KernelProgramInfo) \ | |
| V(WeakSerializationReference) \ | |
| V(WeakArray) \ | |
| V(Code) \ | |
| V(Bytecode) \ | |
| V(Instructions) \ | |
| V(InstructionsSection) \ | |
| V(InstructionsTable) \ | |
| V(ObjectPool) \ | |
| V(PcDescriptors) \ | |
| V(CodeSourceMap) \ | |
| V(CompressedStackMaps) \ | |
| V(LocalVarDescriptors) \ | |
| V(LocalVarDescriptor) \ | |
| V(ExceptionHandlers) \ | |
| V(Context) \ | |
| V(ContextScope) \ | |
| V(Sentinel) \ | |
| V(SingleTargetCache) \ | |
| V(MonomorphicSmiableCall) \ | |
| V(CallSiteData) \ | |
| V(UnlinkedCall) \ | |
| V(ICData) \ | |
| V(MegamorphicCache) \ | |
| V(SubtypeTestCache) \ | |
| V(LoadingUnit) \ | |
| V(Error) \ | |
| V(ApiError) \ | |
| V(LanguageError) \ | |
| V(UnhandledException) \ | |
| V(UnwindError) | |
| // Classes that are subclasses of Instance and neither part of a specific cid | |
| // grouping like strings, arrays, etc. nor require special handling outside of | |
| // being a predefined class. | |
| #define CLASS_LIST_INSTANCE_SINGLETONS(V) \ | |
| V(Instance) \ | |
| V(LibraryPrefix) \ | |
| V(TypeArguments) \ | |
| V(AbstractType) \ | |
| V(Type) \ | |
| V(FunctionType) \ | |
| V(RecordType) \ | |
| V(TypeParameter) \ | |
| V(FinalizerBase) \ | |
| V(Finalizer) \ | |
| V(NativeFinalizer) \ | |
| V(FinalizerEntry) \ | |
| V(Closure) \ | |
| V(Number) \ | |
| V(Integer) \ | |
| V(Smi) \ | |
| V(Mint) \ | |
| V(Double) \ | |
| V(Bool) \ | |
| V(Float32x4) \ | |
| V(Int32x4) \ | |
| V(Float64x2) \ | |
| V(Record) \ | |
| V(TypedDataBase) \ | |
| V(TypedData) \ | |
| V(ExternalTypedData) \ | |
| V(TypedDataView) \ | |
| V(Pointer) \ | |
| V(DynamicLibrary) \ | |
| V(Capability) \ | |
| V(ReceivePort) \ | |
| V(SendPort) \ | |
| V(StackTrace) \ | |
| V(SuspendState) \ | |
| V(RegExp) \ | |
| V(WeakProperty) \ | |
| V(WeakReference) \ | |
| V(MirrorReference) \ | |
| V(FutureOr) \ | |
| V(UserTag) \ | |
| V(TransferableTypedData) | |
| #define CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(V) \ | |
| CLASS_LIST_INTERNAL_ONLY(V) CLASS_LIST_INSTANCE_SINGLETONS(V) | |
| #define CLASS_LIST_MAPS(V) \ | |
| V(Map) \ | |
| V(ConstMap) | |
| #define CLASS_LIST_SETS(V) \ | |
| V(Set) \ | |
| V(ConstSet) | |
| #define CLASS_LIST_FIXED_LENGTH_ARRAYS(V) \ | |
| V(Array) \ | |
| V(ImmutableArray) | |
| #define CLASS_LIST_ARRAYS(V) \ | |
| CLASS_LIST_FIXED_LENGTH_ARRAYS(V) \ | |
| V(GrowableObjectArray) | |
| #define CLASS_LIST_STRINGS(V) \ | |
| V(String) \ | |
| V(OneByteString) \ | |
| V(TwoByteString) | |
| #define CLASS_LIST_TYPED_DATA(V) \ | |
| V(Int8Array) \ | |
| V(Uint8Array) \ | |
| V(Uint8ClampedArray) \ | |
| V(Int16Array) \ | |
| V(Uint16Array) \ | |
| V(Int32Array) \ | |
| V(Uint32Array) \ | |
| V(Int64Array) \ | |
| V(Uint64Array) \ | |
| V(Float32Array) \ | |
| V(Float64Array) \ | |
| V(Float32x4Array) \ | |
| V(Int32x4Array) \ | |
| V(Float64x2Array) | |
| #define CLASS_LIST_FFI_NUMERIC_FIXED_SIZE(V) \ | |
| V(Int8) \ | |
| V(Int16) \ | |
| V(Int32) \ | |
| V(Int64) \ | |
| V(Uint8) \ | |
| V(Uint16) \ | |
| V(Uint32) \ | |
| V(Uint64) \ | |
| V(Float) \ | |
| V(Double) | |
| #define CLASS_LIST_FFI_TYPE_MARKER(V) \ | |
| CLASS_LIST_FFI_NUMERIC_FIXED_SIZE(V) \ | |
| V(Void) \ | |
| V(Handle) \ | |
| V(Bool) | |
| #define CLASS_LIST_FFI(V) \ | |
| V(NativeFunction) \ | |
| CLASS_LIST_FFI_TYPE_MARKER(V) \ | |
| V(NativeType) \ | |
| V(Struct) | |
| #define DART_CLASS_LIST_TYPED_DATA(V) \ | |
| V(Int8) \ | |
| V(Uint8) \ | |
| V(Uint8Clamped) \ | |
| V(Int16) \ | |
| V(Uint16) \ | |
| V(Int32) \ | |
| V(Uint32) \ | |
| V(Int64) \ | |
| V(Uint64) \ | |
| V(Float32) \ | |
| V(Float64) \ | |
| V(Float32x4) \ | |
| V(Int32x4) \ | |
| V(Float64x2) | |
| #define CLASS_LIST_FOR_HANDLES(V) \ | |
| CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(V) \ | |
| V(Map) \ | |
| V(Set) \ | |
| V(Array) \ | |
| V(GrowableObjectArray) \ | |
| V(String) | |
| #define CLASS_LIST_NO_OBJECT(V) \ | |
| CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(V) \ | |
| CLASS_LIST_MAPS(V) \ | |
| CLASS_LIST_SETS(V) \ | |
| CLASS_LIST_ARRAYS(V) \ | |
| CLASS_LIST_STRINGS(V) | |
| #define CLASS_LIST(V) \ | |
| V(Object) \ | |
| CLASS_LIST_NO_OBJECT(V) | |
| #define LEAF_HANDLE_LIST(V) \ | |
| V(Class) \ | |
| V(PatchClass) \ | |
| V(Function) \ | |
| V(TypeParameters) \ | |
| V(ClosureData) \ | |
| V(FfiTrampolineData) \ | |
| V(Field) \ | |
| V(Script) \ | |
| V(Library) \ | |
| V(Namespace) \ | |
| V(KernelProgramInfo) \ | |
| V(WeakSerializationReference) \ | |
| V(WeakArray) \ | |
| V(Code) \ | |
| V(Bytecode) \ | |
| V(Instructions) \ | |
| V(InstructionsSection) \ | |
| V(InstructionsTable) \ | |
| V(ObjectPool) \ | |
| V(PcDescriptors) \ | |
| V(CodeSourceMap) \ | |
| V(CompressedStackMaps) \ | |
| V(LocalVarDescriptors) \ | |
| V(LocalVarDescriptor) \ | |
| V(ExceptionHandlers) \ | |
| V(Context) \ | |
| V(ContextScope) \ | |
| V(Sentinel) \ | |
| V(SingleTargetCache) \ | |
| V(UnlinkedCall) \ | |
| V(MonomorphicSmiableCall) \ | |
| V(ICData) \ | |
| V(MegamorphicCache) \ | |
| V(SubtypeTestCache) \ | |
| V(LoadingUnit) \ | |
| V(ApiError) \ | |
| V(LanguageError) \ | |
| V(UnhandledException) \ | |
| V(UnwindError) \ | |
| V(LibraryPrefix) \ | |
| V(TypeArguments) \ | |
| V(Type) \ | |
| V(FunctionType) \ | |
| V(RecordType) \ | |
| V(TypeParameter) \ | |
| V(Finalizer) \ | |
| V(NativeFinalizer) \ | |
| V(FinalizerEntry) \ | |
| V(Closure) \ | |
| V(Smi) \ | |
| V(Mint) \ | |
| V(Double) \ | |
| V(Bool) \ | |
| V(Float32x4) \ | |
| V(Int32x4) \ | |
| V(Float64x2) \ | |
| V(Record) \ | |
| V(TypedData) \ | |
| V(ExternalTypedData) \ | |
| V(TypedDataView) \ | |
| V(Pointer) \ | |
| V(DynamicLibrary) \ | |
| V(Capability) \ | |
| V(ReceivePort) \ | |
| V(SendPort) \ | |
| V(StackTrace) \ | |
| V(SuspendState) \ | |
| V(RegExp) \ | |
| V(WeakProperty) \ | |
| V(WeakReference) \ | |
| V(MirrorReference) \ | |
| V(FutureOr) \ | |
| V(UserTag) \ | |
| V(TransferableTypedData) \ | |
| V(Map) \ | |
| V(Set) \ | |
| V(Array) \ | |
| V(GrowableObjectArray) \ | |
| V(String) | |
| #undef CID | |
| #define DEFINE_CLASS_ID(clazz) CID(clazz##Cid) | |
| #define DEFINE_FFI_CLASS_ID(clazz) CID(Ffi##clazz##Cid) | |
| #define DEFINE_TYPED_DATA_CLASS_ID(clazz) \ | |
| CID(TypedData##clazz##Cid) \ | |
| CID(TypedData##clazz##ViewCid) \ | |
| CID(ExternalTypedData##clazz##Cid) \ | |
| CID(UnmodifiableTypedData##clazz##ViewCid) | |
| #define CLASS_ID_LIST \ | |
| /* Illegal class id. */ \ | |
| CID(IllegalCid) \ | |
| /* Pseudo class id for native pointers, the heap should never see an */ \ | |
| /* object with this class id. */ \ | |
| CID(NativePointer) \ | |
| /* The following entries describes classes for pseudo-objects in the heap */ \ | |
| /* that should never be reachable from live objects. Free list elements */ \ | |
| /* maintain the free list for old space, and forwarding corpses are used */ \ | |
| /* to implement one-way become. */ \ | |
| CID(FreeListElement) \ | |
| CID(ForwardingCorpse) \ | |
| CLASS_LIST(DEFINE_CLASS_ID) \ | |
| CID(LinkedHashBaseCid) \ | |
| CLASS_LIST_FFI(DEFINE_FFI_CLASS_ID) \ | |
| CLASS_LIST_TYPED_DATA(DEFINE_TYPED_DATA_CLASS_ID) \ | |
| CID(ByteDataViewCid) \ | |
| CID(UnmodifiableByteDataViewCid) \ | |
| CID(ByteBufferCid) \ | |
| /* The following entries do not describe a predefined class, but instead */ \ | |
| /* are class indexes for pre-allocated instances */ \ | |
| /* (Null, dynamic, void, Never). */ \ | |
| CID(NullCid) \ | |
| CID(DynamicCid) \ | |
| CID(VoidCid) \ | |
| CID(NeverCid) | |
| enum ClassId : intptr_t { | |
| #define CID(cid) k##cid, | |
| CLASS_ID_LIST | |
| #undef CID | |
| kNumPredefinedCids, | |
| }; | |
| static constexpr const char* kClassIdNames[] = { | |
| #define CID(cid) #cid, | |
| CLASS_ID_LIST | |
| #undef CID | |
| }; | |
| #undef DEFINE_CLASS_ID | |
| #undef DEFINE_FFI_CLASS_ID | |
| #undef DEFINE_TYPED_DATA_CLASS_ID | |
| #undef CLASS_ID_LIST | |
| // Keep these in sync with the cid numbering above. | |
| const int kTypedDataCidRemainderInternal = 0; | |
| const int kTypedDataCidRemainderView = 1; | |
| const int kTypedDataCidRemainderExternal = 2; | |
| const int kTypedDataCidRemainderUnmodifiable = 3; | |
| const int kNumTypedDataCidRemainders = kTypedDataCidRemainderUnmodifiable + 1; | |
| // Class Id predicates. | |
| bool IsInternalOnlyClassId(intptr_t index); | |
| bool IsErrorClassId(intptr_t index); | |
| bool IsNumberClassId(intptr_t index); | |
| bool IsIntegerClassId(intptr_t index); | |
| bool IsStringClassId(intptr_t index); | |
| bool IsOneByteStringClassId(intptr_t index); | |
| bool IsBuiltinListClassId(intptr_t index); | |
| bool IsTypeClassId(intptr_t index); | |
| bool IsTypedDataBaseClassId(intptr_t index); | |
| bool IsTypedDataClassId(intptr_t index); | |
| bool IsTypedDataViewClassId(intptr_t index); | |
| bool IsExternalTypedDataClassId(intptr_t index); | |
| bool IsFfiPointerClassId(intptr_t index); | |
| bool IsFfiTypeClassId(intptr_t index); | |
| bool IsFfiDynamicLibraryClassId(intptr_t index); | |
| bool IsInternalVMdefinedClassId(intptr_t index); | |
| bool IsImplicitFieldClassId(intptr_t index); | |
| // Should be used for looping over non-Object internal-only cids. | |
| constexpr intptr_t kFirstInternalOnlyCid = kClassCid; | |
| constexpr intptr_t kLastInternalOnlyCid = kUnwindErrorCid; | |
| // Use the currently surrounding cids to check that no new classes have been | |
| // added to the beginning or end of CLASS_LIST_INTERNAL_ONLY without adjusting | |
| // the above definitions. | |
| COMPILE_ASSERT(kFirstInternalOnlyCid == kObjectCid + 1); | |
| COMPILE_ASSERT(kInstanceCid == kLastInternalOnlyCid + 1); | |
| // Returns true for any class id that either does not correspond to a real | |
| // class, like kIllegalCid or kForwardingCorpse, or that is internal to the VM | |
| // and should not be exposed directly to user code. | |
| inline bool IsInternalOnlyClassId(intptr_t index) { | |
| // Fix the condition below if these become non-contiguous. | |
| COMPILE_ASSERT(kIllegalCid + 1 == kNativePointer && | |
| kIllegalCid + 2 == kFreeListElement && | |
| kIllegalCid + 3 == kForwardingCorpse && | |
| kIllegalCid + 4 == kObjectCid && | |
| kIllegalCid + 5 == kFirstInternalOnlyCid); | |
| return index <= kLastInternalOnlyCid; | |
| } | |
| inline bool IsCallSiteDataClassId(intptr_t index) { | |
| COMPILE_ASSERT(kCallSiteDataCid + 1 == kUnlinkedCallCid && | |
| kCallSiteDataCid + 2 == kICDataCid && | |
| kCallSiteDataCid + 3 == kMegamorphicCacheCid); | |
| return (index >= kCallSiteDataCid && index <= kMegamorphicCacheCid); | |
| } | |
| // Make sure this function is updated when new Error types are added. | |
| static const ClassId kFirstErrorCid = kErrorCid; | |
| static const ClassId kLastErrorCid = kUnwindErrorCid; | |
| COMPILE_ASSERT(kFirstErrorCid == kErrorCid && | |
| kApiErrorCid == kFirstErrorCid + 1 && | |
| kLanguageErrorCid == kFirstErrorCid + 2 && | |
| kUnhandledExceptionCid == kFirstErrorCid + 3 && | |
| kUnwindErrorCid == kFirstErrorCid + 4 && | |
| kLastErrorCid == kUnwindErrorCid && | |
| // Change if needed for detecting a new error added at the end. | |
| kLastInternalOnlyCid == kLastErrorCid); | |
| inline bool IsErrorClassId(intptr_t index) { | |
| return (index >= kFirstErrorCid && index <= kLastErrorCid); | |
| } | |
| inline bool IsAbstractTypeClassId(intptr_t index) { | |
| COMPILE_ASSERT(kAbstractTypeCid + 1 == kTypeCid && | |
| kAbstractTypeCid + 2 == kFunctionTypeCid && | |
| kAbstractTypeCid + 3 == kRecordTypeCid && | |
| kAbstractTypeCid + 4 == kTypeParameterCid); | |
| return (index >= kAbstractTypeCid && index <= kTypeParameterCid); | |
| } | |
| inline bool IsConcreteTypeClassId(intptr_t index) { | |
| // Make sure to update when new AbstractType subclasses are added. | |
| COMPILE_ASSERT(kFunctionTypeCid == kTypeCid + 1 && | |
| kRecordTypeCid == kTypeCid + 2 && | |
| kTypeParameterCid == kTypeCid + 3); | |
| return (index >= kTypeCid && index <= kTypeParameterCid); | |
| } | |
| inline bool IsNumberClassId(intptr_t index) { | |
| // Make sure this function is updated when new Number types are added. | |
| COMPILE_ASSERT(kIntegerCid == kNumberCid + 1 && kSmiCid == kNumberCid + 2 && | |
| kMintCid == kNumberCid + 3 && kDoubleCid == kNumberCid + 4); | |
| return (index >= kNumberCid && index <= kDoubleCid); | |
| } | |
| inline bool IsIntegerClassId(intptr_t index) { | |
| // Make sure this function is updated when new Integer types are added. | |
| COMPILE_ASSERT(kSmiCid == kIntegerCid + 1 && kMintCid == kIntegerCid + 2); | |
| return (index >= kIntegerCid && index <= kMintCid); | |
| } | |
| // Make sure this check is updated when new StringCid types are added. | |
| COMPILE_ASSERT(kOneByteStringCid == kStringCid + 1 && | |
| kTwoByteStringCid == kStringCid + 2); | |
| inline bool IsStringClassId(intptr_t index) { | |
| return (index >= kStringCid && index <= kTwoByteStringCid); | |
| } | |
| inline bool IsOneByteStringClassId(intptr_t index) { | |
| return (index == kOneByteStringCid); | |
| } | |
| inline bool IsArrayClassId(intptr_t index) { | |
| COMPILE_ASSERT(kImmutableArrayCid == kArrayCid + 1); | |
| COMPILE_ASSERT(kGrowableObjectArrayCid == kArrayCid + 2); | |
| return (index >= kArrayCid && index <= kGrowableObjectArrayCid); | |
| } | |
| inline bool IsBuiltinListClassId(intptr_t index) { | |
| // Make sure this function is updated when new builtin List types are added. | |
| return (IsArrayClassId(index) || IsTypedDataBaseClassId(index) || | |
| (index == kByteBufferCid)); | |
| } | |
| inline bool IsTypeClassId(intptr_t index) { | |
| // Only Type, FunctionType and RecordType can be encountered as instance | |
| // types at runtime. | |
| return index == kTypeCid || index == kFunctionTypeCid || | |
| index == kRecordTypeCid; | |
| } | |
| static const ClassId kFirstTypedDataCid = kTypedDataInt8ArrayCid; | |
| static const ClassId kLastTypedDataCid = | |
| kUnmodifiableTypedDataFloat64x2ArrayViewCid; | |
| // Make sure the following checks are updated when adding new TypedData types. | |
| // The following asserts assume this. | |
| COMPILE_ASSERT(kTypedDataCidRemainderInternal == 0); | |
| // Ensure that each typed data type comes in internal/view/external variants | |
| // next to each other. | |
| COMPILE_ASSERT(kTypedDataInt8ArrayCid + kTypedDataCidRemainderView == | |
| kTypedDataInt8ArrayViewCid); | |
| COMPILE_ASSERT(kTypedDataInt8ArrayCid + kTypedDataCidRemainderExternal == | |
| kExternalTypedDataInt8ArrayCid); | |
| COMPILE_ASSERT(kTypedDataInt8ArrayCid + kTypedDataCidRemainderUnmodifiable == | |
| kUnmodifiableTypedDataInt8ArrayViewCid); | |
| // Ensure the order of the typed data members in 3-step. | |
| COMPILE_ASSERT(kFirstTypedDataCid == kTypedDataInt8ArrayCid); | |
| COMPILE_ASSERT(kFirstTypedDataCid + 1 * kNumTypedDataCidRemainders == | |
| kTypedDataUint8ArrayCid); | |
| COMPILE_ASSERT(kFirstTypedDataCid + 2 * kNumTypedDataCidRemainders == | |
| kTypedDataUint8ClampedArrayCid); | |
| COMPILE_ASSERT(kFirstTypedDataCid + 3 * kNumTypedDataCidRemainders == | |
| kTypedDataInt16ArrayCid); | |
| COMPILE_ASSERT(kFirstTypedDataCid + 4 * kNumTypedDataCidRemainders == | |
| kTypedDataUint16ArrayCid); | |
| COMPILE_ASSERT(kFirstTypedDataCid + 5 * kNumTypedDataCidRemainders == | |
| kTypedDataInt32ArrayCid); | |
| COMPILE_ASSERT(kFirstTypedDataCid + 6 * kNumTypedDataCidRemainders == | |
| kTypedDataUint32ArrayCid); | |
| COMPILE_ASSERT(kFirstTypedDataCid + 7 * kNumTypedDataCidRemainders == | |
| kTypedDataInt64ArrayCid); | |
| COMPILE_ASSERT(kFirstTypedDataCid + 8 * kNumTypedDataCidRemainders == | |
| kTypedDataUint64ArrayCid); | |
| COMPILE_ASSERT(kFirstTypedDataCid + 9 * kNumTypedDataCidRemainders == | |
| kTypedDataFloat32ArrayCid); | |
| COMPILE_ASSERT(kFirstTypedDataCid + 10 * kNumTypedDataCidRemainders == | |
| kTypedDataFloat64ArrayCid); | |
| COMPILE_ASSERT(kFirstTypedDataCid + 11 * kNumTypedDataCidRemainders == | |
| kTypedDataFloat32x4ArrayCid); | |
| COMPILE_ASSERT(kFirstTypedDataCid + 12 * kNumTypedDataCidRemainders == | |
| kTypedDataInt32x4ArrayCid); | |
| COMPILE_ASSERT(kFirstTypedDataCid + 13 * kNumTypedDataCidRemainders == | |
| kTypedDataFloat64x2ArrayCid); | |
| COMPILE_ASSERT(kFirstTypedDataCid + 13 * kNumTypedDataCidRemainders + | |
| kTypedDataCidRemainderUnmodifiable == | |
| kLastTypedDataCid); | |
| // Checks for possible new typed data entries added before or after the current | |
| // entries. | |
| COMPILE_ASSERT(kFfiStructCid + 1 == kFirstTypedDataCid); | |
| COMPILE_ASSERT(kLastTypedDataCid + 1 == kByteDataViewCid); | |
| inline bool IsTypedDataBaseClassId(intptr_t index) { | |
| return index >= kFirstTypedDataCid && index <= kLastTypedDataCid; | |
| } | |
| inline bool IsTypedDataClassId(intptr_t index) { | |
| return IsTypedDataBaseClassId(index) && | |
| ((index - kFirstTypedDataCid) % kNumTypedDataCidRemainders) == | |
| kTypedDataCidRemainderInternal; | |
| } | |
| inline bool IsTypedDataViewClassId(intptr_t index) { | |
| const bool is_byte_data_view = index == kByteDataViewCid; | |
| return is_byte_data_view || | |
| (IsTypedDataBaseClassId(index) && | |
| ((index - kFirstTypedDataCid) % kNumTypedDataCidRemainders) == | |
| kTypedDataCidRemainderView); | |
| } | |
| inline bool IsExternalTypedDataClassId(intptr_t index) { | |
| return IsTypedDataBaseClassId(index) && | |
| ((index - kFirstTypedDataCid) % kNumTypedDataCidRemainders) == | |
| kTypedDataCidRemainderExternal; | |
| } | |
| inline bool IsUnmodifiableTypedDataViewClassId(intptr_t index) { | |
| const bool is_byte_data_view = index == kUnmodifiableByteDataViewCid; | |
| return is_byte_data_view || | |
| (IsTypedDataBaseClassId(index) && | |
| ((index - kFirstTypedDataCid) % kNumTypedDataCidRemainders) == | |
| kTypedDataCidRemainderUnmodifiable); | |
| } | |
| inline bool IsClampedTypedDataBaseClassId(intptr_t index) { | |
| if (!IsTypedDataBaseClassId(index)) return false; | |
| const intptr_t internal_cid = | |
| index - ((index - kFirstTypedDataCid) % kNumTypedDataCidRemainders) + | |
| kTypedDataCidRemainderInternal; | |
| // Currently, the only clamped typed data arrays are Uint8. | |
| return internal_cid == kTypedDataUint8ClampedArrayCid; | |
| } | |
| // Whether the given cid is an external array cid, that is, an array where | |
| // the payload is not in GC-managed memory. | |
| inline bool IsExternalPayloadClassId(classid_t cid) { | |
| return cid == kPointerCid || IsExternalTypedDataClassId(cid); | |
| } | |
| // For predefined cids only. Refer to Class::is_deeply_immutable for | |
| // instances of non-predefined classes. | |
| // | |
| // Having the `@pragma('vm:deeply-immutable')`, which means statically proven | |
| // deeply immutable, implies true for this function. The other way around is not | |
| // guaranteed, predefined classes can be marked deeply immutable in the VM while | |
| // not having their subtypes or super type being deeply immutable. | |
| // | |
| // Keep consistent with runtime/docs/deeply_immutable.md. | |
| inline bool IsDeeplyImmutableCid(intptr_t predefined_cid) { | |
| ASSERT(predefined_cid < kNumPredefinedCids); | |
| return IsStringClassId(predefined_cid) || predefined_cid == kNumberCid || | |
| predefined_cid == kIntegerCid || predefined_cid == kSmiCid || | |
| predefined_cid == kMintCid || predefined_cid == kNeverCid || | |
| predefined_cid == kSentinelCid || predefined_cid == kStackTraceCid || | |
| predefined_cid == kDoubleCid || predefined_cid == kFloat32x4Cid || | |
| predefined_cid == kFloat64x2Cid || predefined_cid == kInt32x4Cid || | |
| predefined_cid == kSendPortCid || predefined_cid == kCapabilityCid || | |
| predefined_cid == kRegExpCid || predefined_cid == kBoolCid || | |
| predefined_cid == kNullCid || predefined_cid == kPointerCid || | |
| predefined_cid == kTypeCid || predefined_cid == kTypeArgumentsCid || | |
| predefined_cid == kTypeParameterCid || | |
| predefined_cid == kRecordTypeCid || | |
| predefined_cid == kFunctionTypeCid || predefined_cid == kConstMapCid; | |
| } | |
| inline bool IsShallowlyImmutableCid(intptr_t predefined_cid) { | |
| ASSERT(predefined_cid < kNumPredefinedCids); | |
| return predefined_cid == kClosureCid || | |
| IsUnmodifiableTypedDataViewClassId(predefined_cid); | |
| } | |
| inline bool IsFfiTypeClassId(intptr_t index) { | |
| switch (index) { | |
| case kPointerCid: | |
| case kFfiNativeFunctionCid: | |
| #define CASE_FFI_CID(name) case kFfi##name##Cid: | |
| CLASS_LIST_FFI_TYPE_MARKER(CASE_FFI_CID) | |
| #undef CASE_FFI_CID | |
| return true; | |
| default: | |
| return false; | |
| } | |
| UNREACHABLE(); | |
| } | |
| inline bool IsFfiPredefinedClassId(classid_t class_id) { | |
| switch (class_id) { | |
| case kPointerCid: | |
| case kDynamicLibraryCid: | |
| #define CASE_FFI_CID(name) case kFfi##name##Cid: | |
| CLASS_LIST_FFI(CASE_FFI_CID) | |
| #undef CASE_FFI_CID | |
| return true; | |
| default: | |
| return false; | |
| } | |
| UNREACHABLE(); | |
| } | |
| inline bool IsFfiPointerClassId(intptr_t index) { | |
| return index == kPointerCid; | |
| } | |
| inline bool IsFfiDynamicLibraryClassId(intptr_t index) { | |
| return index == kDynamicLibraryCid; | |
| } | |
| inline bool IsInternalVMdefinedClassId(intptr_t index) { | |
| return ((index < kNumPredefinedCids) && !IsImplicitFieldClassId(index)); | |
| } | |
| // This is a set of classes that are not Dart classes whose representation | |
| // is defined by the VM but are used in the VM code by computing the | |
| // implicit field offsets of the various fields in the dart object. | |
| inline bool IsImplicitFieldClassId(intptr_t index) { | |
| return index == kByteBufferCid; | |
| } | |
| COMPILE_ASSERT(kByteBufferCid + 1 == kNullCid); | |
| } // namespace dart | |
| #endif // RUNTIME_VM_CLASS_ID_H_ |