Implement global module indexing to improve performance.

The global module index represents an efficient on-disk hash table which stores
identifier->module mapping. Every time clang finds a unknown identifier we
are informed and we can load the corresponding module on demand.

This way we can provide minimal set of loaded modules. Currently, we see that
for hsimple.C only the half of the modules are loaded. This can be further
improved because we currently load all modules which have an identifier, that is
when looking for (for example TPad) we will load all modules which have the
identifier TPad, including modules which contain only a forward declaration of
it.

Kudos Arpitha Raghunandan (arpi-r)!
This commit is contained in:
Vassil Vassilev 2019-02-20 10:02:34 +01:00 committed by SFT
parent 9220b498f3
commit 051044c062
2 changed files with 31 additions and 11 deletions

View File

@ -547,17 +547,15 @@ namespace {
for (StringRef ModulePath : Paths) {
// FIXME: If we have a prebuilt module path that is equal to our module
// cache we fail to compile the clang builtin modules for some reason.
// This can't be reproduced in clang, so I assume we have some strange
// error in our interpreter setup where this is causing errors (or maybe
// clang is doing the same check in some hidden place).
// The error looks like this:
// .../include/stddef.h error: unknown type name '__PTRDIFF_TYPE__'
// typedef __PTRDIFF_TYPE__ ptrdiff_t;
// <similar follow up errors>
// This makes clang to think it failed to build a dependency module, i.e.
// if we are building module C, clang goes off and builds B and A first.
// If the module cache points to the same location as the prebuilt module
// path, clang errors out on building module A, however, it builds it.
// Next time we run, it will build module B and issue diagnostics.
// If we run third time, it'd build successfully C and continue.
// For now it is fixed by just checking those two paths are not identical.
if (normalizePath(ModulePath) != normalizePath(Opts.ModuleCachePath)) {
if (normalizePath(ModulePath) != normalizePath(Opts.ModuleCachePath))
Opts.AddPrebuiltModulePath(ModulePath);
}
}
}

View File

@ -873,10 +873,32 @@ namespace cling {
if (getSema().isModuleVisible(M))
return true;
// We cannot use #pragma clang module import because the on-demand modules
// may load a module in the middle of a function body for example. In this
// case this triggers an error:
// fatal error: import of module '...' appears within function '...'
//
// if (declare("#pragma clang module import \"" + M->Name + "\"") ==
// kSuccess)
// return true;
// FIXME: What about importing submodules such as std.blah. This disables
// this functionality.
if (declare("#pragma clang module import \"" + M->Name + "\"") == kSuccess)
return true;
Preprocessor& PP = getCI()->getPreprocessor();
IdentifierInfo* II = PP.getIdentifierInfo(M->Name);
SourceLocation ValidLoc = M->DefinitionLoc;
Interpreter::PushTransactionRAII RAII(this);
bool success = !getCI()
->getSema()
.ActOnModuleImport(ValidLoc, ValidLoc,
std::make_pair(II, ValidLoc))
.isInvalid();
if (success) {
// Also make the module visible in the preprocessor to export its macros.
PP.makeModuleVisible(M, ValidLoc);
return success;
}
if (complain) {
if (M->IsSystem)