mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[deserialization] Do not allow SILModule to attempt to deserialize a witness table lazily while we are already deserializing.
When deserializing, the serialized sil loader attempts to first lookup from its SILModule the witness table to attempt to grab a witness table declaration. Before this patch if the SILModule could not find it, it would attempt to deserialize it. In certain edge cases this would cause us to attempt to deserialize a function definition which violates the invariant that that should never happen. This patch adds an argument to SILModule::lookUpWitnessTable that enables you to turn off the lazy deserialization behavior. The default argument gives the current behavior which should be used everywhere except for the deserializer. Swift SVN r16740
This commit is contained in:
@@ -323,8 +323,13 @@ public:
|
|||||||
/// Look up the SILWitnessTable representing the lowering of a protocol
|
/// Look up the SILWitnessTable representing the lowering of a protocol
|
||||||
/// conformance, and collect the substitutions to apply to the referenced
|
/// conformance, and collect the substitutions to apply to the referenced
|
||||||
/// witnesses, if any.
|
/// witnesses, if any.
|
||||||
|
///
|
||||||
|
/// \arg C The protocol conformance mapped key to use to lookup the witness
|
||||||
|
/// table.
|
||||||
|
/// \arg deserializeLazily If we can not find the witness table should we
|
||||||
|
/// attempt to lazily deserialize it.
|
||||||
std::pair<SILWitnessTable *, ArrayRef<Substitution>>
|
std::pair<SILWitnessTable *, ArrayRef<Substitution>>
|
||||||
lookUpWitnessTable(const ProtocolConformance *C);
|
lookUpWitnessTable(const ProtocolConformance *C, bool deserializeLazily=true);
|
||||||
|
|
||||||
/// Look up the VTable mapped to the given ClassDecl. Returns null on failure.
|
/// Look up the VTable mapped to the given ClassDecl. Returns null on failure.
|
||||||
SILVTable *lookUpVTable(const ClassDecl *C);
|
SILVTable *lookUpVTable(const ClassDecl *C);
|
||||||
|
|||||||
@@ -136,7 +136,8 @@ SILModule::createWitnessTableDeclaration(ProtocolConformance *C) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::pair<SILWitnessTable *, ArrayRef<Substitution>>
|
std::pair<SILWitnessTable *, ArrayRef<Substitution>>
|
||||||
SILModule::lookUpWitnessTable(const ProtocolConformance *C) {
|
SILModule::
|
||||||
|
lookUpWitnessTable(const ProtocolConformance *C, bool deserializeLazily) {
|
||||||
// Walk down to the base NormalProtocolConformance.
|
// Walk down to the base NormalProtocolConformance.
|
||||||
const ProtocolConformance *ParentC = C;
|
const ProtocolConformance *ParentC = C;
|
||||||
ArrayRef<Substitution> Subs;
|
ArrayRef<Substitution> Subs;
|
||||||
@@ -201,8 +202,9 @@ SILModule::lookUpWitnessTable(const ProtocolConformance *C) {
|
|||||||
//
|
//
|
||||||
// *NOTE* In practice, wT will be deserializedTable, but I do not want to rely
|
// *NOTE* In practice, wT will be deserializedTable, but I do not want to rely
|
||||||
// on that behavior for now.
|
// on that behavior for now.
|
||||||
if (auto deserializedTable = getSILLoader()->lookupWitnessTable(wT))
|
if (deserializeLazily)
|
||||||
return {deserializedTable, Subs};
|
if (auto deserializedTable = getSILLoader()->lookupWitnessTable(wT))
|
||||||
|
return {deserializedTable, Subs};
|
||||||
|
|
||||||
// If we fail, just return the declaration.
|
// If we fail, just return the declaration.
|
||||||
return {wT, Subs};
|
return {wT, Subs};
|
||||||
|
|||||||
@@ -1682,7 +1682,7 @@ SILWitnessTable *SILDeserializer::readWitnessTable(DeclID WId,
|
|||||||
auto theConformance = cast<NormalProtocolConformance>(*maybeConformance);
|
auto theConformance = cast<NormalProtocolConformance>(*maybeConformance);
|
||||||
|
|
||||||
if (!existingWt)
|
if (!existingWt)
|
||||||
existingWt = SILMod.lookUpWitnessTable(theConformance).first;
|
existingWt = SILMod.lookUpWitnessTable(theConformance, false).first;
|
||||||
auto wT = existingWt;
|
auto wT = existingWt;
|
||||||
|
|
||||||
// If we have an existing witness table, verify that the conformance matches
|
// If we have an existing witness table, verify that the conformance matches
|
||||||
@@ -1698,7 +1698,7 @@ SILWitnessTable *SILDeserializer::readWitnessTable(DeclID WId,
|
|||||||
// declaration.
|
// declaration.
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, create a new function.
|
// Otherwise, create a new witness table declaration.
|
||||||
wT = SILWitnessTable::create(SILMod, *Linkage, theConformance);
|
wT = SILWitnessTable::create(SILMod, *Linkage, theConformance);
|
||||||
if (Callback)
|
if (Callback)
|
||||||
Callback->didDeserialize(MF->getAssociatedModule(), wT);
|
Callback->didDeserialize(MF->getAssociatedModule(), wT);
|
||||||
@@ -1707,7 +1707,8 @@ SILWitnessTable *SILDeserializer::readWitnessTable(DeclID WId,
|
|||||||
assert(wT->isDeclaration() && "Our witness table at this point must be a "
|
assert(wT->isDeclaration() && "Our witness table at this point must be a "
|
||||||
"declaration.");
|
"declaration.");
|
||||||
|
|
||||||
// If we have a declaration, create the witness table declaration and bail.
|
// If we are asked to just emit a declaration, return the declaration and say
|
||||||
|
// that the witness table is not fully deserialized.
|
||||||
if (IsDeclaration || declarationOnly) {
|
if (IsDeclaration || declarationOnly) {
|
||||||
wTableOrOffset.set(wT, /*fully deserialized*/ false);
|
wTableOrOffset.set(wT, /*fully deserialized*/ false);
|
||||||
return wT;
|
return wT;
|
||||||
|
|||||||
Reference in New Issue
Block a user