[serialization] Lazily load top-level decls, extensions, and operators.

This switches from simple lists of decls to name-based on-disk hash tables,
which allows decls to be loaded lazily when doing simple lookup (but not
code completion, at least not yet).

The on-disk hash table implementation is borrowed from Clang; eventually
it will be pushed down to LLVM's Support library. (Fortunately the
implementation is header-only.)

This breaks a few tests that rely on magic protocols like
IntegerLiteralConvertible, because the type checker won't have seen the
types that conform to those protocols yet. This will be fixed by doing
an additional "hey, modules, got any of these?" lookup.

Swift SVN r7259
This commit is contained in:
Jordan Rose
2013-08-15 17:31:44 +00:00
parent 49f1d53e50
commit bca05dab59
6 changed files with 302 additions and 121 deletions

View File

@@ -33,6 +33,12 @@ namespace llvm {
class MemoryBuffer;
}
// This template should eventually move to llvm/Support.
namespace clang {
template <typename Info>
class OnDiskChainedHashTable;
}
namespace swift {
class Pattern;
class ProtocolConformance;
@@ -163,22 +169,13 @@ private:
/// Identifiers referenced by this module.
std::vector<SerializedIdentifier> Identifiers;
/// All top-level decls in this module.
llvm::DenseMap<Identifier, TinyPtrVector<ValueDecl *>> TopLevelDecls;
private:
class DeclTableInfo;
using SerializedDeclTable = clang::OnDiskChainedHashTable<DeclTableInfo>;
/// An array of the top-level decl IDs.
// FIXME: We don't really want to deserialize all of these at once.
std::vector<serialization::DeclID> RawTopLevelIDs;
using OperatorKey = std::pair<Identifier, serialization::OperatorKind>;
friend struct llvm::DenseMapInfo<OperatorKey>;
/// All the operators in the module.
llvm::DenseMap<OperatorKey, OperatorDecl *> Operators;
/// An array of the top-level decl IDs.
// FIXME: We don't really want to deserialize all of these at once.
std::vector<serialization::DeclID> RawOperatorIDs;
public:
std::unique_ptr<SerializedDeclTable> TopLevelDecls;
std::unique_ptr<SerializedDeclTable> OperatorDecls;
/// Whether this module file can be used.
ModuleStatus Status;
@@ -186,6 +183,9 @@ private:
/// Constructs an new module and validates it.
ModuleFile(llvm::OwningPtr<llvm::MemoryBuffer> &&input);
// Out of line to avoid instantiation OnDiskChainedHashTable here.
~ModuleFile();
/// Convenience function for module loading.
void error(ModuleStatus issue = ModuleStatus::Malformed) {
assert(issue != ModuleStatus::Valid &&
@@ -277,7 +277,7 @@ public:
/// \returns Whether the module was successfully loaded, or what went wrong
/// if it was not.
static ModuleStatus load(llvm::OwningPtr<llvm::MemoryBuffer> &&input,
llvm::OwningPtr<ModuleFile> &module) {
std::unique_ptr<ModuleFile> &module) {
module.reset(new ModuleFile(std::move(input)));
return module->getStatus();
}
@@ -317,6 +317,11 @@ public:
void lookupVisibleDecls(Module::AccessPathTy accessPath,
VisibleDeclConsumer &consumer,
NLKind lookupKind);
/// Loads extensions for the given decl.
///
/// Note that this may cause other extensions to load as well.
void loadExtensions(NominalTypeDecl *nominal);
};
class SerializedModule : public LoadedModule {
@@ -337,25 +342,4 @@ public:
} // end namespace swift
namespace llvm {
template<> struct DenseMapInfo<swift::ModuleFile::OperatorKey> {
using OperatorKey = swift::ModuleFile::OperatorKey;
using Identifier = swift::Identifier;
static OperatorKey getEmptyKey() {
return OperatorKey(Identifier(), swift::serialization::Prefix);
}
static OperatorKey getTombstoneKey() {
return OperatorKey(Identifier(), swift::serialization::Postfix);
}
static unsigned getHashValue(OperatorKey Val) {
using RawPair = std::pair<Identifier, unsigned>;
return DenseMapInfo<RawPair>::getHashValue(RawPair(Val));
}
static bool isEqual(OperatorKey LHS, OperatorKey RHS) {
return LHS == RHS;
}
};
}
#endif