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:
Joe Groff
2017-12-12 09:57:36 -08:00
parent 9ac1dc80b0
commit a7a3b17597
58 changed files with 3418 additions and 1291 deletions

View File

@@ -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;
}
};