Skip to content

Commit

Permalink
[ABI] Move the resilient witness table into the conformance descriptor.
Browse files Browse the repository at this point in the history
Place resilient witnesses in the protocol conformance descriptor,
tail-allocated after the conditional requirements, so they can be found by
reflection. Drop the resilient witness table and protocol descriptor from
the generic witness table.

Addresses rdar://problem/45228582.
  • Loading branch information
DougGregor committed Oct 12, 2018
1 parent a4d53b8 commit 41891f6
Show file tree
Hide file tree
Showing 11 changed files with 215 additions and 157 deletions.
63 changes: 52 additions & 11 deletions include/swift/ABI/Metadata.h
Expand Up @@ -2013,17 +2013,9 @@ struct TargetGenericWitnessTable {
/// to require instantiation.
uint16_t WitnessTablePrivateSizeInWordsAndRequiresInstantiation;

/// The protocol descriptor. Only used for resilient conformances.
RelativeIndirectablePointer<ProtocolDescriptor,
/*nullable*/ true> Protocol;

/// The pattern.
RelativeDirectPointer<const TargetWitnessTable<Runtime>> Pattern;

/// The resilient witness table, if any.
RelativeDirectPointer<const TargetResilientWitnessTable<Runtime>,
/*nullable*/ true> ResilientWitnesses;

/// The instantiation function, which is called after the template is copied.
RelativeDirectPointer<void(TargetWitnessTable<Runtime> *instantiatedTable,
const TargetMetadata<Runtime> *type,
Expand All @@ -2044,6 +2036,18 @@ struct TargetGenericWitnessTable {
uint16_t requiresInstantiation() const {
return WitnessTablePrivateSizeInWordsAndRequiresInstantiation & 0x01;
}

/// Retrieve the protocol conformance descriptor.
ConstTargetPointer<Runtime, TargetProtocolConformanceDescriptor<Runtime>>
getConformance() const {
return Pattern->Description;
}

/// Retrieve the protocol.
ConstTargetPointer<Runtime, TargetProtocolDescriptor<Runtime>>
getProtocol() const {
return Pattern->Description->getProtocol();
}
};
using GenericWitnessTable = TargetGenericWitnessTable<InProcess>;

Expand Down Expand Up @@ -2222,6 +2226,14 @@ struct TargetTypeReference {
};
using TypeReference = TargetTypeReference<InProcess>;

/// Header containing information about the resilient witnesses in a
/// protocol conformance descriptor.
template <typename Runtime>
struct TargetResilientWitnessesHeader {
uint32_t NumWitnesses;
};
using ResilientWitnessesHeader = TargetResilientWitnessesHeader<InProcess>;

/// The structure of a protocol conformance.
///
/// This contains enough static information to recover the witness table for a
Expand All @@ -2231,12 +2243,16 @@ struct TargetProtocolConformanceDescriptor final
: public swift::ABI::TrailingObjects<
TargetProtocolConformanceDescriptor<Runtime>,
RelativeContextPointer<Runtime>,
TargetGenericRequirementDescriptor<Runtime>> {
TargetGenericRequirementDescriptor<Runtime>,
TargetResilientWitnessesHeader<Runtime>,
TargetResilientWitness<Runtime>> {

using TrailingObjects = swift::ABI::TrailingObjects<
TargetProtocolConformanceDescriptor<Runtime>,
RelativeContextPointer<Runtime>,
TargetGenericRequirementDescriptor<Runtime>>;
TargetGenericRequirementDescriptor<Runtime>,
TargetResilientWitnessesHeader<Runtime>,
TargetResilientWitness<Runtime>>;
friend TrailingObjects;

template<typename T>
Expand All @@ -2250,6 +2266,9 @@ struct TargetProtocolConformanceDescriptor final
using GenericRequirementDescriptor =
TargetGenericRequirementDescriptor<Runtime>;

using ResilientWitnessesHeader = TargetResilientWitnessesHeader<Runtime>;
using ResilientWitness = TargetResilientWitness<Runtime>;

private:
/// The protocol being conformed to.
RelativeIndirectablePointer<ProtocolDescriptor> Protocol;
Expand All @@ -2271,7 +2290,8 @@ struct TargetProtocolConformanceDescriptor final
ConformanceFlags Flags;

public:
const ProtocolDescriptor *getProtocol() const {
ConstTargetPointer<Runtime, TargetProtocolDescriptor<Runtime>>
getProtocol() const {
return Protocol;
}

Expand Down Expand Up @@ -2345,6 +2365,16 @@ struct TargetProtocolConformanceDescriptor final
const swift::TargetWitnessTable<Runtime> *
getWitnessTable(const TargetMetadata<Runtime> *type) const;

/// Retrieve the resilient witnesses.
ArrayRef<ResilientWitness> getResilientWitnesses() const{
if (!Flags.hasResilientWitnesses())
return { };

return ArrayRef<ResilientWitness>(
this->template getTrailingObjects<ResilientWitness>(),
numTrailingObjects(OverloadToken<ResilientWitness>()));
}

#if !defined(NDEBUG) && SWIFT_OBJC_INTEROP
void dump() const;
#endif
Expand All @@ -2368,6 +2398,17 @@ struct TargetProtocolConformanceDescriptor final
size_t numTrailingObjects(OverloadToken<GenericRequirementDescriptor>) const {
return Flags.getNumConditionalRequirements();
}

size_t numTrailingObjects(OverloadToken<ResilientWitnessesHeader>) const {
return Flags.hasResilientWitnesses() ? 1 : 0;
}

size_t numTrailingObjects(OverloadToken<ResilientWitness>) const {
return Flags.hasResilientWitnesses()
? this->template getTrailingObjects<ResilientWitnessesHeader>()
->NumWitnesses
: 0;
}
};
using ProtocolConformanceDescriptor
= TargetProtocolConformanceDescriptor<InProcess>;
Expand Down
13 changes: 13 additions & 0 deletions include/swift/ABI/MetadataValues.h
Expand Up @@ -627,6 +627,8 @@ class ConformanceFlags {

NumConditionalRequirementsMask = 0xFF << 8,
NumConditionalRequirementsShift = 8,

HasResilientWitnessesMask = 0x01 << 16,
};

int_type Value;
Expand Down Expand Up @@ -660,6 +662,12 @@ class ConformanceFlags {
| (n << NumConditionalRequirementsShift));
}

ConformanceFlags withHasResilientWitnesses(bool hasResilientWitnesses) const {
return ConformanceFlags((Value & ~HasResilientWitnessesMask)
| (hasResilientWitnesses? HasResilientWitnessesMask
: 0));
}

/// Retrieve the conformance kind.
ConformanceKind getConformanceKind() const {
return ConformanceKind(Value & ConformanceKindMask);
Expand Down Expand Up @@ -696,6 +704,11 @@ class ConformanceFlags {
>> NumConditionalRequirementsShift;
}

/// Whether this conformance has any resilient witnesses.
bool hasResilientWitnesses() const {
return Value & HasResilientWitnessesMask;
}

int_type getIntValue() const { return Value; }
};

Expand Down
18 changes: 8 additions & 10 deletions lib/IRGen/GenDecl.cpp
Expand Up @@ -2451,20 +2451,20 @@ llvm::Constant *IRGenModule::emitSwiftProtocols() {
}

void IRGenModule::addProtocolConformance(
const NormalProtocolConformance *conformance) {
ConformanceDescription record) {
// Add this protocol conformance.
ProtocolConformances.push_back(conformance);
ProtocolConformances.push_back(std::move(record));
}

/// Emit the protocol conformance list and return it.
llvm::Constant *IRGenModule::emitProtocolConformances() {
// Emit the conformances.
bool anyReflectedConformances = false;
for (auto *conformance : ProtocolConformances) {
for (const auto &record : ProtocolConformances) {
// Emit the protocol conformance now.
emitProtocolConformance(conformance);
emitProtocolConformance(record);

if (conformance->isBehaviorConformance())
if (record.conformance->isBehaviorConformance())
continue;

anyReflectedConformances = true;
Expand All @@ -2477,7 +2477,9 @@ llvm::Constant *IRGenModule::emitProtocolConformances() {
ConstantInitBuilder builder(*this);
auto descriptorArray = builder.beginArray(RelativeAddressTy);

for (auto *conformance : ProtocolConformances) {
for (const auto &record : ProtocolConformances) {
auto conformance = record.conformance;

// Behavior conformances cannot be reflected.
if (conformance->isBehaviorConformance())
continue;
Expand Down Expand Up @@ -3687,12 +3689,8 @@ llvm::StructType *IRGenModule::getGenericWitnessTableCacheTy() {
Int16Ty,
// WitnessTablePrivateSizeInWords + RequiresInstantiation bit
Int16Ty,
// Protocol
RelativeAddressTy,
// Pattern
RelativeAddressTy,
// ResilientWitnesses
RelativeAddressTy,
// Instantiator
RelativeAddressTy,
// PrivateData
Expand Down

0 comments on commit 41891f6

Please sign in to comment.