mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Replace nominal type descriptors with a hierarchy of context descriptors.
This new format more efficiently represents existing information, while more accurately encoding important information about nested generic contexts with same-type and layout constraints that need to be evaluated at runtime. It's also designed with an eye to forward- and backward-compatible expansion for ABI stability with future Swift versions.
This commit is contained in:
@@ -91,19 +91,17 @@ public:
|
||||
|
||||
auto TR = readTypeFromMetadata(MetadataAddress);
|
||||
auto kind = this->readKindFromMetadata(MetadataAddress);
|
||||
if (TR != nullptr && kind.first) {
|
||||
switch (kind.second) {
|
||||
if (TR != nullptr && kind) {
|
||||
switch (*kind) {
|
||||
case MetadataKind::Class: {
|
||||
// Figure out where the stored properties of this class begin
|
||||
// by looking at the size of the superclass
|
||||
bool valid;
|
||||
unsigned start;
|
||||
std::tie(valid, start) =
|
||||
auto start =
|
||||
this->readInstanceStartAndAlignmentFromClassMetadata(MetadataAddress);
|
||||
|
||||
// Perform layout
|
||||
if (valid)
|
||||
TI = TC.getClassInstanceTypeInfo(TR, start);
|
||||
if (start)
|
||||
TI = TC.getClassInstanceTypeInfo(TR, *start);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -121,20 +119,20 @@ public:
|
||||
/// metadata as its isa pointer.
|
||||
const TypeInfo *getInstanceTypeInfo(StoredPointer ObjectAddress) {
|
||||
auto MetadataAddress = readMetadataFromInstance(ObjectAddress);
|
||||
if (!MetadataAddress.first)
|
||||
if (!MetadataAddress)
|
||||
return nullptr;
|
||||
|
||||
auto kind = this->readKindFromMetadata(MetadataAddress.second);
|
||||
if (!kind.first)
|
||||
auto kind = this->readKindFromMetadata(*MetadataAddress);
|
||||
if (!kind)
|
||||
return nullptr;
|
||||
|
||||
switch (kind.second) {
|
||||
switch (*kind) {
|
||||
case MetadataKind::Class:
|
||||
return getMetadataTypeInfo(MetadataAddress.second);
|
||||
return getMetadataTypeInfo(*MetadataAddress);
|
||||
|
||||
case MetadataKind::HeapLocalVariable: {
|
||||
auto CDAddr = this->readCaptureDescriptorFromMetadata(MetadataAddress.second);
|
||||
if (!CDAddr.first)
|
||||
auto CDAddr = this->readCaptureDescriptorFromMetadata(*MetadataAddress);
|
||||
if (!CDAddr)
|
||||
return nullptr;
|
||||
|
||||
// FIXME: Non-generic SIL boxes also use the HeapLocalVariable metadata
|
||||
@@ -143,7 +141,7 @@ public:
|
||||
//
|
||||
// Non-generic SIL boxes share metadata among types with compatible
|
||||
// layout, but we need some way to get an outgoing pointer map for them.
|
||||
auto *CD = getBuilder().getCaptureDescriptor(CDAddr.second);
|
||||
auto *CD = getBuilder().getCaptureDescriptor(*CDAddr);
|
||||
if (CD == nullptr)
|
||||
return nullptr;
|
||||
|
||||
@@ -155,7 +153,7 @@ public:
|
||||
case MetadataKind::HeapGenericLocalVariable: {
|
||||
// Generic SIL @box type - there is always an instantiated metadata
|
||||
// pointer for the boxed type.
|
||||
if (auto Meta = readMetadata(MetadataAddress.second)) {
|
||||
if (auto Meta = readMetadata(*MetadataAddress)) {
|
||||
auto GenericHeapMeta =
|
||||
cast<TargetGenericBoxHeapMetadata<Runtime>>(Meta.getLocalBuffer());
|
||||
return getMetadataTypeInfo(GenericHeapMeta->BoxedType);
|
||||
@@ -255,12 +253,10 @@ public:
|
||||
case RecordKind::ErrorExistential: {
|
||||
// We have a pointer to an error existential, which is always heap object.
|
||||
|
||||
bool successfullyGotIsa = false;
|
||||
StoredPointer MetadataAddress = 0;
|
||||
std::tie(successfullyGotIsa, MetadataAddress)
|
||||
auto MetadataAddress
|
||||
= readMetadataFromInstance(ExistentialAddress.getAddressData());
|
||||
|
||||
if (!successfullyGotIsa)
|
||||
if (!MetadataAddress)
|
||||
return false;
|
||||
|
||||
bool isObjC = false;
|
||||
@@ -268,14 +264,14 @@ public:
|
||||
// If we can determine the Objective-C class name, this is probably an
|
||||
// error existential with NSError-compatible layout.
|
||||
std::string ObjCClassName;
|
||||
if (readObjCClassName(MetadataAddress, ObjCClassName)) {
|
||||
if (readObjCClassName(*MetadataAddress, ObjCClassName)) {
|
||||
if (ObjCClassName == "_SwiftNativeNSError")
|
||||
isObjC = true;
|
||||
} else {
|
||||
// Otherwise, we can check to see if this is a class metadata with the
|
||||
// kind value's least significant bit set, which indicates a pure
|
||||
// Swift class.
|
||||
auto Meta = readMetadata(MetadataAddress);
|
||||
auto Meta = readMetadata(*MetadataAddress);
|
||||
auto ClassMeta = dyn_cast<TargetClassMetadata<Runtime>>(Meta);
|
||||
if (!ClassMeta)
|
||||
return false;
|
||||
@@ -293,13 +289,12 @@ public:
|
||||
|
||||
// We need to get the instance's alignment info so we can get the exact
|
||||
// offset of the start of its data in the class.
|
||||
StoredPointer InstanceMetadataAddress = 0;
|
||||
std::tie(successfullyGotIsa, InstanceMetadataAddress) =
|
||||
auto InstanceMetadataAddress =
|
||||
readMetadataFromInstance(InstanceMetadataAddressAddress);
|
||||
if (!successfullyGotIsa)
|
||||
if (!InstanceMetadataAddress)
|
||||
return false;
|
||||
|
||||
auto InstanceTR = readTypeFromMetadata(InstanceMetadataAddress);
|
||||
auto InstanceTR = readTypeFromMetadata(*InstanceMetadataAddress);
|
||||
if (!InstanceTR)
|
||||
return false;
|
||||
|
||||
@@ -339,18 +334,18 @@ private:
|
||||
RecordKind::ClosureContext);
|
||||
|
||||
auto Metadata = readMetadataFromInstance(Context);
|
||||
if (!Metadata.first)
|
||||
if (!Metadata)
|
||||
return nullptr;
|
||||
|
||||
// Calculate the offset of the first capture.
|
||||
// See GenHeap.cpp, buildPrivateMetadata().
|
||||
auto OffsetToFirstCapture =
|
||||
this->readOffsetToFirstCaptureFromMetadata(Metadata.second);
|
||||
if (!OffsetToFirstCapture.first)
|
||||
this->readOffsetToFirstCaptureFromMetadata(*Metadata);
|
||||
if (!OffsetToFirstCapture)
|
||||
return nullptr;
|
||||
|
||||
// Initialize the builder.
|
||||
Builder.addField(OffsetToFirstCapture.second, sizeof(StoredPointer),
|
||||
Builder.addField(*OffsetToFirstCapture, sizeof(StoredPointer),
|
||||
/*numExtraInhabitants=*/0);
|
||||
|
||||
// Skip the closure's necessary bindings struct, if it's present.
|
||||
@@ -414,10 +409,10 @@ private:
|
||||
continue;
|
||||
|
||||
auto Metadata = readMetadataSource(Context, Source.second, Builder);
|
||||
if (!Metadata.first)
|
||||
if (!Metadata)
|
||||
return nullptr;
|
||||
|
||||
auto *SubstTR = readTypeFromMetadata(Metadata.second);
|
||||
auto *SubstTR = readTypeFromMetadata(*Metadata);
|
||||
if (SubstTR == nullptr)
|
||||
return nullptr;
|
||||
|
||||
@@ -475,7 +470,7 @@ private:
|
||||
/// above.
|
||||
///
|
||||
/// \param Builder Used to obtain offsets of elements known so far.
|
||||
std::pair<bool, StoredPointer>
|
||||
llvm::Optional<StoredPointer>
|
||||
readMetadataSource(StoredPointer Context,
|
||||
const MetadataSource *MS,
|
||||
const RecordTypeInfoBuilder &Builder) {
|
||||
@@ -498,7 +493,7 @@ private:
|
||||
&MetadataAddress))
|
||||
break;
|
||||
|
||||
return std::make_pair(true, MetadataAddress);
|
||||
return MetadataAddress;
|
||||
}
|
||||
case MetadataSourceKind::ReferenceCapture: {
|
||||
unsigned Index = cast<ReferenceCaptureMetadataSource>(MS)->getIndex();
|
||||
@@ -527,27 +522,27 @@ private:
|
||||
&CaptureAddress))
|
||||
break;
|
||||
|
||||
return std::make_pair(true, CaptureAddress);
|
||||
return CaptureAddress;
|
||||
}
|
||||
case MetadataSourceKind::GenericArgument: {
|
||||
auto *GAMS = cast<GenericArgumentMetadataSource>(MS);
|
||||
auto Base = readMetadataSource(Context, GAMS->getSource(), Builder);
|
||||
if (!Base.first)
|
||||
if (!Base)
|
||||
break;
|
||||
|
||||
unsigned Index = GAMS->getIndex();
|
||||
auto Arg = readGenericArgFromMetadata(Base.second, Index);
|
||||
if (!Arg.first)
|
||||
auto Arg = readGenericArgFromMetadata(*Base, Index);
|
||||
if (!Arg)
|
||||
break;
|
||||
|
||||
return Arg;
|
||||
return *Arg;
|
||||
}
|
||||
case MetadataSourceKind::Self:
|
||||
case MetadataSourceKind::SelfWitnessTable:
|
||||
break;
|
||||
}
|
||||
|
||||
return std::make_pair(false, StoredPointer(0));
|
||||
return llvm::None;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user