[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:
Michael Gottesman
2014-04-24 03:37:33 +00:00
parent c7566510f3
commit afa464f980
3 changed files with 15 additions and 7 deletions

View File

@@ -323,8 +323,13 @@ public:
/// Look up the SILWitnessTable representing the lowering of a protocol
/// conformance, and collect the substitutions to apply to the referenced
/// 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>>
lookUpWitnessTable(const ProtocolConformance *C);
lookUpWitnessTable(const ProtocolConformance *C, bool deserializeLazily=true);
/// Look up the VTable mapped to the given ClassDecl. Returns null on failure.
SILVTable *lookUpVTable(const ClassDecl *C);

View File

@@ -136,7 +136,8 @@ SILModule::createWitnessTableDeclaration(ProtocolConformance *C) {
}
std::pair<SILWitnessTable *, ArrayRef<Substitution>>
SILModule::lookUpWitnessTable(const ProtocolConformance *C) {
SILModule::
lookUpWitnessTable(const ProtocolConformance *C, bool deserializeLazily) {
// Walk down to the base NormalProtocolConformance.
const ProtocolConformance *ParentC = C;
ArrayRef<Substitution> Subs;
@@ -201,6 +202,7 @@ SILModule::lookUpWitnessTable(const ProtocolConformance *C) {
//
// *NOTE* In practice, wT will be deserializedTable, but I do not want to rely
// on that behavior for now.
if (deserializeLazily)
if (auto deserializedTable = getSILLoader()->lookupWitnessTable(wT))
return {deserializedTable, Subs};

View File

@@ -1682,7 +1682,7 @@ SILWitnessTable *SILDeserializer::readWitnessTable(DeclID WId,
auto theConformance = cast<NormalProtocolConformance>(*maybeConformance);
if (!existingWt)
existingWt = SILMod.lookUpWitnessTable(theConformance).first;
existingWt = SILMod.lookUpWitnessTable(theConformance, false).first;
auto wT = existingWt;
// If we have an existing witness table, verify that the conformance matches
@@ -1698,7 +1698,7 @@ SILWitnessTable *SILDeserializer::readWitnessTable(DeclID WId,
// declaration.
} else {
// Otherwise, create a new function.
// Otherwise, create a new witness table declaration.
wT = SILWitnessTable::create(SILMod, *Linkage, theConformance);
if (Callback)
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 "
"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) {
wTableOrOffset.set(wT, /*fully deserialized*/ false);
return wT;