mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 20:51:50 +00:00
69167e2bdb
This change adds can_be_sentinel() flag to CompileType and prevents unboxing of phis which can be sentinel. This flag means that set of values can potentially contain Object::sentinel() which is used as a marker for the uninitialized value of late variables. TEST=runtime/tests/vm/dart/regress_46141_test.dart Fixes https://github.com/dart-lang/sdk/issues/46141 Change-Id: I32f19488f54c6f69932584ecec3094e3b78cc0d0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/201600 Reviewed-by: Slava Egorov <vegorov@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
406 lines
20 KiB
C++
406 lines
20 KiB
C++
// 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"
|
|
|
|
namespace dart {
|
|
|
|
// Size of the class-id part of the object header. See UntaggedObject.
|
|
typedef uint16_t ClassIdTagType;
|
|
|
|
#define CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(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(Code) \
|
|
V(Instructions) \
|
|
V(InstructionsSection) \
|
|
V(InstructionsTable) \
|
|
V(ObjectPool) \
|
|
V(PcDescriptors) \
|
|
V(CodeSourceMap) \
|
|
V(CompressedStackMaps) \
|
|
V(LocalVarDescriptors) \
|
|
V(ExceptionHandlers) \
|
|
V(Context) \
|
|
V(ContextScope) \
|
|
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) \
|
|
V(Instance) \
|
|
V(LibraryPrefix) \
|
|
V(TypeArguments) \
|
|
V(AbstractType) \
|
|
V(Type) \
|
|
V(FunctionType) \
|
|
V(TypeRef) \
|
|
V(TypeParameter) \
|
|
V(Closure) \
|
|
V(Number) \
|
|
V(Integer) \
|
|
V(Smi) \
|
|
V(Mint) \
|
|
V(Double) \
|
|
V(Bool) \
|
|
V(GrowableObjectArray) \
|
|
V(Float32x4) \
|
|
V(Int32x4) \
|
|
V(Float64x2) \
|
|
V(TypedDataBase) \
|
|
V(TypedData) \
|
|
V(ExternalTypedData) \
|
|
V(TypedDataView) \
|
|
V(Pointer) \
|
|
V(DynamicLibrary) \
|
|
V(Capability) \
|
|
V(ReceivePort) \
|
|
V(SendPort) \
|
|
V(StackTrace) \
|
|
V(RegExp) \
|
|
V(WeakProperty) \
|
|
V(MirrorReference) \
|
|
V(LinkedHashMap) \
|
|
V(FutureOr) \
|
|
V(UserTag) \
|
|
V(TransferableTypedData)
|
|
|
|
#define CLASS_LIST_ARRAYS(V) \
|
|
V(Array) \
|
|
V(ImmutableArray)
|
|
|
|
#define CLASS_LIST_STRINGS(V) \
|
|
V(String) \
|
|
V(OneByteString) \
|
|
V(TwoByteString) \
|
|
V(ExternalOneByteString) \
|
|
V(ExternalTwoByteString)
|
|
|
|
#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(V) \
|
|
V(Int8) \
|
|
V(Int16) \
|
|
V(Int32) \
|
|
V(Int64) \
|
|
V(Uint8) \
|
|
V(Uint16) \
|
|
V(Uint32) \
|
|
V(Uint64) \
|
|
V(IntPtr) \
|
|
V(Float) \
|
|
V(Double)
|
|
|
|
#define CLASS_LIST_FFI_TYPE_MARKER(V) \
|
|
CLASS_LIST_FFI_NUMERIC(V) \
|
|
V(Void) \
|
|
V(Handle)
|
|
|
|
#define CLASS_LIST_FFI(V) \
|
|
V(Pointer) \
|
|
V(NativeFunction) \
|
|
CLASS_LIST_FFI_TYPE_MARKER(V) \
|
|
V(NativeType) \
|
|
V(DynamicLibrary) \
|
|
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(V) \
|
|
V(Array) \
|
|
V(String)
|
|
|
|
#define CLASS_LIST_NO_OBJECT(V) \
|
|
CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(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,
|
|
|
|
// 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,
|
|
CLASS_LIST_TYPED_DATA(DEFINE_OBJECT_KIND)
|
|
#undef DEFINE_OBJECT_KIND
|
|
kByteDataViewCid,
|
|
|
|
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,
|
|
};
|
|
|
|
constexpr ClassId kSentinelCid = kNeverCid;
|
|
|
|
// Keep these in sync with the cid numbering above.
|
|
const int kTypedDataCidRemainderInternal = 0;
|
|
const int kTypedDataCidRemainderView = 1;
|
|
const int kTypedDataCidRemainderExternal = 2;
|
|
|
|
// Class Id predicates.
|
|
|
|
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 IsExternalStringClassId(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);
|
|
|
|
inline bool IsErrorClassId(intptr_t index) {
|
|
// Make sure this function is updated when new Error types are added.
|
|
COMPILE_ASSERT(
|
|
kApiErrorCid == kErrorCid + 1 && kLanguageErrorCid == kErrorCid + 2 &&
|
|
kUnhandledExceptionCid == kErrorCid + 3 &&
|
|
kUnwindErrorCid == kErrorCid + 4 && kInstanceCid == kErrorCid + 5);
|
|
return (index >= kErrorCid && index < kInstanceCid);
|
|
}
|
|
|
|
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 &&
|
|
kExternalOneByteStringCid == kStringCid + 3 &&
|
|
kExternalTwoByteStringCid == kStringCid + 4);
|
|
|
|
inline bool IsStringClassId(intptr_t index) {
|
|
return (index >= kStringCid && index <= kExternalTwoByteStringCid);
|
|
}
|
|
|
|
inline bool IsOneByteStringClassId(intptr_t index) {
|
|
return (index == kOneByteStringCid || index == kExternalOneByteStringCid);
|
|
}
|
|
|
|
inline bool IsExternalStringClassId(intptr_t index) {
|
|
return (index == kExternalOneByteStringCid ||
|
|
index == kExternalTwoByteStringCid);
|
|
}
|
|
|
|
inline bool IsBuiltinListClassId(intptr_t index) {
|
|
// Make sure this function is updated when new builtin List types are added.
|
|
COMPILE_ASSERT(kImmutableArrayCid == kArrayCid + 1);
|
|
return ((index >= kArrayCid && index <= kImmutableArrayCid) ||
|
|
(index == kGrowableObjectArrayCid) || IsTypedDataBaseClassId(index) ||
|
|
(index == kByteBufferCid));
|
|
}
|
|
|
|
inline bool IsTypeClassId(intptr_t index) {
|
|
// Only Type and FunctionType can be encountered as instance types at runtime.
|
|
return index == kTypeCid || index == kFunctionTypeCid;
|
|
}
|
|
|
|
inline bool IsTypedDataBaseClassId(intptr_t index) {
|
|
// Make sure this is updated when new TypedData types are added.
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 3 == kTypedDataUint8ArrayCid);
|
|
return index >= kTypedDataInt8ArrayCid && index < kByteDataViewCid;
|
|
}
|
|
|
|
inline bool IsTypedDataClassId(intptr_t index) {
|
|
// Make sure this is updated when new TypedData types are added.
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 3 == kTypedDataUint8ArrayCid);
|
|
return IsTypedDataBaseClassId(index) && ((index - kTypedDataInt8ArrayCid) %
|
|
3) == kTypedDataCidRemainderInternal;
|
|
}
|
|
|
|
inline bool IsTypedDataViewClassId(intptr_t index) {
|
|
// Make sure this is updated when new TypedData types are added.
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayViewCid + 3 == kTypedDataUint8ArrayViewCid);
|
|
|
|
const bool is_byte_data_view = index == kByteDataViewCid;
|
|
return is_byte_data_view ||
|
|
(IsTypedDataBaseClassId(index) &&
|
|
((index - kTypedDataInt8ArrayCid) % 3) == kTypedDataCidRemainderView);
|
|
}
|
|
|
|
inline bool IsExternalTypedDataClassId(intptr_t index) {
|
|
// Make sure this is updated when new TypedData types are added.
|
|
COMPILE_ASSERT(kExternalTypedDataInt8ArrayCid + 3 ==
|
|
kExternalTypedDataUint8ArrayCid);
|
|
|
|
return IsTypedDataBaseClassId(index) && ((index - kTypedDataInt8ArrayCid) %
|
|
3) == kTypedDataCidRemainderExternal;
|
|
}
|
|
|
|
inline bool IsFfiTypeClassId(intptr_t index) {
|
|
switch (index) {
|
|
case kFfiPointerCid:
|
|
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) {
|
|
#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 == kFfiPointerCid;
|
|
}
|
|
|
|
inline bool IsFfiDynamicLibraryClassId(intptr_t index) {
|
|
return index == kFfiDynamicLibraryCid;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// Make sure the following checks are updated when adding new TypedData types.
|
|
|
|
// Ensure that each typed data type comes in internal/view/external variants
|
|
// next to each other.
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 1 == kTypedDataInt8ArrayViewCid);
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 2 == kExternalTypedDataInt8ArrayCid);
|
|
|
|
// Ensure the order of the typed data members in 3-step.
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 1 * 3 == kTypedDataUint8ArrayCid);
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 2 * 3 ==
|
|
kTypedDataUint8ClampedArrayCid);
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 3 * 3 == kTypedDataInt16ArrayCid);
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 4 * 3 == kTypedDataUint16ArrayCid);
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 5 * 3 == kTypedDataInt32ArrayCid);
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 6 * 3 == kTypedDataUint32ArrayCid);
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 7 * 3 == kTypedDataInt64ArrayCid);
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 8 * 3 == kTypedDataUint64ArrayCid);
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 9 * 3 == kTypedDataFloat32ArrayCid);
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 10 * 3 == kTypedDataFloat64ArrayCid);
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 11 * 3 == kTypedDataFloat32x4ArrayCid);
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 12 * 3 == kTypedDataInt32x4ArrayCid);
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 13 * 3 == kTypedDataFloat64x2ArrayCid);
|
|
COMPILE_ASSERT(kTypedDataInt8ArrayCid + 14 * 3 == kByteDataViewCid);
|
|
COMPILE_ASSERT(kByteBufferCid + 1 == kNullCid);
|
|
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_VM_CLASS_ID_H_
|