[serialization] Record nominal types in the module table ASAP.

Deserializing a nominal decl often ends up referring to the nominal's type,
so if we're /already/ serializing the type, we should finish that as soon
as we have a decl. Accomplish this by adding a callback that is called
right after a nominal decl is recorded in the module's decl table, so that
the type can be immediately recorded as well.

Swift SVN r6227
This commit is contained in:
Jordan Rose
2013-07-12 23:29:45 +00:00
parent c8cb4d82b7
commit 4db68ed617
2 changed files with 66 additions and 17 deletions

View File

@@ -16,12 +16,32 @@
#include "swift/Basic/STLExtras.h" #include "swift/Basic/STLExtras.h"
#include "swift/Serialization/BCReadingExtras.h" #include "swift/Serialization/BCReadingExtras.h"
#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MemoryBuffer.h"
#include <functional>
using namespace swift; using namespace swift;
using namespace swift::serialization; using namespace swift::serialization;
static constexpr const auto AF_DontPopBlockAtEnd = static constexpr const auto AF_DontPopBlockAtEnd =
llvm::BitstreamCursor::AF_DontPopBlockAtEnd; llvm::BitstreamCursor::AF_DontPopBlockAtEnd;
/// Declares a member \c type that is a std::function compatible with the given
/// callable type.
///
/// \tparam T A callable type, such as a lambda.
template <typename T>
struct as_function : public as_function<decltype(&T::operator())> {};
template <typename L, typename R, typename... Args>
struct as_function<R(L::*)(Args...) const> {
using type = std::function<R(Args...)>;
};
/// Returns a std::function that can call a void-returning, single-argument
/// lambda without copying it.
template <typename L>
static typename as_function<L>::type makeStackLambda(const L &theLambda) {
return std::cref(theLambda);
}
static ModuleStatus static ModuleStatus
validateControlBlock(llvm::BitstreamCursor &cursor, validateControlBlock(llvm::BitstreamCursor &cursor,
llvm::SmallVectorImpl<uint64_t> &scratch) { llvm::SmallVectorImpl<uint64_t> &scratch) {
@@ -178,16 +198,15 @@ Optional<ProtocolConformance *> ModuleFile::maybeReadConformance() {
return Nothing; return Nothing;
unsigned kind = DeclTypeCursor.readRecord(next.ID, scratch); unsigned kind = DeclTypeCursor.readRecord(next.ID, scratch);
if (kind == NO_CONFORMANCE) { if (kind != PROTOCOL_CONFORMANCE && kind != NO_CONFORMANCE)
assert(scratch.empty());
lastRecordOffset.reset();
return nullptr;
}
if (kind != PROTOCOL_CONFORMANCE)
return Nothing; return Nothing;
lastRecordOffset.reset(); lastRecordOffset.reset();
if (kind == NO_CONFORMANCE) {
assert(scratch.empty());
return nullptr;
}
unsigned valueCount, typeCount, inheritedCount, defaultedCount; unsigned valueCount, typeCount, inheritedCount, defaultedCount;
ArrayRef<uint64_t> rawIDs; ArrayRef<uint64_t> rawIDs;
@@ -222,13 +241,13 @@ Optional<ProtocolConformance *> ModuleFile::maybeReadConformance() {
auto inherited = maybeReadConformance(); auto inherited = maybeReadConformance();
assert(inherited.hasValue()); assert(inherited.hasValue());
lastRecordOffset.reset();
conformance->InheritedMapping.insert(std::make_pair(proto, *inherited)); conformance->InheritedMapping.insert(std::make_pair(proto, *inherited));
} }
lastRecordOffset.reset();
while (defaultedCount--) { while (defaultedCount--) {
BCOffsetRAII restoreOffset(DeclTypeCursor);
auto decl = cast<ValueDecl>(getDecl(*rawIDIter++)); auto decl = cast<ValueDecl>(getDecl(*rawIDIter++));
conformance->DefaultedDefinitions.insert(decl); conformance->DefaultedDefinitions.insert(decl);
} }
@@ -382,8 +401,7 @@ Optional<MutableArrayRef<Decl *>> ModuleFile::readMembers() {
SmallVector<uint64_t, 16> memberIDBuffer; SmallVector<uint64_t, 16> memberIDBuffer;
unsigned kind = DeclTypeCursor.readRecord(entry.ID, memberIDBuffer); unsigned kind = DeclTypeCursor.readRecord(entry.ID, memberIDBuffer);
if (kind != DECL_CONTEXT) assert(kind == DECL_CONTEXT);
return Nothing;
ArrayRef<uint64_t> rawMemberIDs; ArrayRef<uint64_t> rawMemberIDs;
decls_block::DeclContextLayout::readRecord(memberIDBuffer, rawMemberIDs); decls_block::DeclContextLayout::readRecord(memberIDBuffer, rawMemberIDs);
@@ -463,15 +481,20 @@ static Optional<swift::Associativity> getActualAssociativity(uint8_t assoc) {
} }
} }
Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) { Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext,
Optional<std::function<void(Decl*)>> DidRecord) {
if (DID == 0) if (DID == 0)
return nullptr; return nullptr;
assert(DID <= Decls.size() && "invalid decl ID"); assert(DID <= Decls.size() && "invalid decl ID");
auto &declOrOffset = Decls[DID-1]; auto &declOrOffset = Decls[DID-1];
if (declOrOffset.is<Decl *>()) if (declOrOffset.is<Decl *>()) {
return declOrOffset.get<Decl *>(); auto result = declOrOffset.get<Decl *>();
if (DidRecord)
(*DidRecord)(result);
return result;
}
DeclTypeCursor.JumpToBit(declOrOffset.get<BitOffset>()); DeclTypeCursor.JumpToBit(declOrOffset.get<BitOffset>());
auto entry = DeclTypeCursor.advance(); auto entry = DeclTypeCursor.advance();
@@ -570,6 +593,8 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
SourceLoc(), inherited, SourceLoc(), inherited,
genericParams, DC); genericParams, DC);
declOrOffset = theStruct; declOrOffset = theStruct;
if (DidRecord)
(*DidRecord)(theStruct);
if (isImplicit) if (isImplicit)
theStruct->setImplicit(); theStruct->setImplicit();
@@ -800,6 +825,8 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
SourceLoc(), getIdentifier(nameID), SourceLoc(), getIdentifier(nameID),
inherited); inherited);
declOrOffset = proto; declOrOffset = proto;
if (DidRecord)
(*DidRecord)(proto);
if (isImplicit) if (isImplicit)
proto->setImplicit(); proto->setImplicit();
@@ -893,6 +920,8 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
SourceLoc(), inherited, SourceLoc(), inherited,
genericParams, DC); genericParams, DC);
declOrOffset = theClass; declOrOffset = theClass;
if (DidRecord)
(*DidRecord)(theClass);
if (isImplicit) if (isImplicit)
theClass->setImplicit(); theClass->setImplicit();
@@ -940,6 +969,8 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
SourceLoc(), inherited, SourceLoc(), inherited,
genericParams, DC); genericParams, DC);
declOrOffset = oneOf; declOrOffset = oneOf;
if (DidRecord)
(*DidRecord)(oneOf);
if (isImplicit) if (isImplicit)
oneOf->setImplicit(); oneOf->setImplicit();
@@ -1290,8 +1321,17 @@ Type ModuleFile::getType(TypeID TID) {
DeclID declID; DeclID declID;
TypeID parentID; TypeID parentID;
decls_block::NominalTypeLayout::readRecord(scratch, declID, parentID); decls_block::NominalTypeLayout::readRecord(scratch, declID, parentID);
typeOrOffset = NominalType::get(cast<NominalTypeDecl>(getDecl(declID)),
getType(parentID), ctx); Type parentTy = getType(parentID);
// Record the type as soon as possible. Members of a nominal type often
// try to refer back to the type.
getDecl(declID, Nothing, makeStackLambda([&](Decl *D) {
auto nominal = cast<NominalTypeDecl>(D);
typeOrOffset = NominalType::get(nominal, parentTy, ctx);
}));
assert(typeOrOffset.is<Type>());
break; break;
} }

View File

@@ -188,8 +188,17 @@ private:
DeclContext *getDeclContext(serialization::DeclID DID); DeclContext *getDeclContext(serialization::DeclID DID);
/// Returns the decl with the given ID, deserializing it if needed. /// Returns the decl with the given ID, deserializing it if needed.
///
/// \param DID The ID for the decl within this module.
/// \param ForcedContext Optional override for the decl context of certain
/// kinds of decls, used to avoid re-entrant
/// deserialization.
/// \param DidRecord Optional callback, called when certain kinds of decls
/// have been recorded in the decl table but not necessarily
/// completed.
Decl *getDecl(serialization::DeclID DID, Decl *getDecl(serialization::DeclID DID,
Optional<DeclContext *> ForcedContext = {}); Optional<DeclContext *> ForcedContext = {},
Optional<std::function<void(Decl*)>> DidRecord = {});
/// Returns the type with the given ID, deserializing it if needed. /// Returns the type with the given ID, deserializing it if needed.
Type getType(serialization::TypeID TID); Type getType(serialization::TypeID TID);