| // 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(Instructions) \ |
| V(InstructionsSection) \ |
| V(InstructionsTable) \ |
| V(ObjectPool) \ |
| V(PcDescriptors) \ |
| V(CodeSourceMap) \ |
| V(CompressedStackMaps) \ |
| V(LocalVarDescriptors) \ |
| V(ExceptionHandlers) \ |
| V(Context) \ |
| V(ContextScope) \ |
| V(Sentinel) \ |
| V(SingleTargetCache) \ |
| V(UnlinkedCall) \ |
| V(MonomorphicSmiableCall) \ |
| V(CallSiteData) \ |
| 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) |
| |
| enum ClassId : intptr_t { |
| // Illegal class id. |
| kIllegalCid = 0, |
| |
| // Pseudo class id for native pointers, the heap should never see an |
| // object with this class id. |
| kNativePointer, |
| |
| // 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. |
| kFreeListElement, |
| kForwardingCorpse, |
| |
| // List of Ids for predefined classes. |
| #define DEFINE_OBJECT_KIND(clazz) k##clazz##Cid, |
| CLASS_LIST(DEFINE_OBJECT_KIND) |
| #undef DEFINE_OBJECT_KIND |
| |
| // clang-format off |
| #define DEFINE_OBJECT_KIND(clazz) kFfi##clazz##Cid, |
| CLASS_LIST_FFI(DEFINE_OBJECT_KIND) |
| #undef DEFINE_OBJECT_KIND |
| |
| #define DEFINE_OBJECT_KIND(clazz) \ |
| kTypedData##clazz##Cid, \ |
| kTypedData##clazz##ViewCid, \ |
| kExternalTypedData##clazz##Cid, \ |
| kUnmodifiableTypedData##clazz##ViewCid, |
| CLASS_LIST_TYPED_DATA(DEFINE_OBJECT_KIND) |
| #undef DEFINE_OBJECT_KIND |
| kByteDataViewCid, |
| kUnmodifiableByteDataViewCid, |
| |
| kByteBufferCid, |
| // clang-format on |
| |
| // The following entries do not describe a predefined class, but instead |
| // are class indexes for pre-allocated instances (Null, dynamic, void, Never). |
| kNullCid, |
| kDynamicCid, |
| kVoidCid, |
| kNeverCid, |
| |
| kNumPredefinedCids, |
| }; |
| |
| // 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; |
| } |
| |
| // 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 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 == kRecordTypeCid || |
| predefined_cid == kFunctionTypeCid; |
| } |
| |
| inline bool IsShallowlyImmutableCid(intptr_t predefined_cid) { |
| ASSERT(predefined_cid < kNumPredefinedCids); |
| // TODO(https://dartbug.com/55136): Mark kClosureCid as shallowly imutable. |
| return IsUnmodifiableTypedDataViewClassId(predefined_cid); |
| } |
| |
| // See documentation on ImmutableBit in raw_object.h |
| inline bool ShouldHaveImmutabilityBitSetCid(intptr_t predefined_cid) { |
| ASSERT(predefined_cid < kNumPredefinedCids); |
| return IsDeeplyImmutableCid(predefined_cid) || |
| IsShallowlyImmutableCid(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_ |