-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Index] Force indexing of system modules to read only from swiftinterfaces #61649
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@swift-ci Please smoke test |
Am I correct in understanding that we will still load prebuilt binary modules from the sdk (in the separate prebuilt directory), just not adjacent ones? |
lib/Index/IndexRecord.cpp
Outdated
module->getASTContext().setIgnoreAdjacentModules(true); | ||
|
||
ImportPath::Module::Builder builder(module->getName()); | ||
auto reloadedModule = module->getASTContext().getModule(builder.get()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm concerned about the cost of re-reading the module here. Even if nothing is later deserialized from the module, my understanding is that loading the module has a non-trivial cost (this was important in code-completion for example). Indexing-while-building is enabled by default in all debug builds, so this would have a wide impact.
Can we move the reload of the module below the parentUnitWriter.isUnitUpToDateForOutputFile
check below? Then we would only incur this cost when we will actually need to index the given module. We would still need the updated module filename for that check, but not to actually read the file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I moved the new logic after the "Up to date check". I also tweaked it in the hope the we still write down something when the swiftinterface fails to build, so the next indexing phase won't attempt to rebuild it again.
I'm not sure how to test superfluous reindexing though, please let me know if you have an idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how to test superfluous reindexing though, please let me know if you have an idea.
We could add a remark (indexing-system-module
), add -Rindexing-system-module
to the test, and then check the output of the second compile doesn't contain it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, I added this remark and used it in the test. It shows on attempts to index, whenever we write a file, and specifies if the content is fixed because of a broken swiftinterface.
2c1a719
to
7b8547b
Compare
Pushing a new version to run tests. I still have some offline comments to look into. @swift-ci Please smoke test |
That's correct, only the adjacent modules are ignored. |
@swift-ci Please smoke test |
lib/Index/IndexRecord.cpp
Outdated
module->getASTContext().setIgnoreAdjacentModules(true); | ||
|
||
ImportPath::Module::Builder builder(module->getName()); | ||
auto reloadedModule = module->getASTContext().getModule(builder.get()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how to test superfluous reindexing though, please let me know if you have an idea.
We could add a remark (indexing-system-module
), add -Rindexing-system-module
to the test, and then check the output of the second compile doesn't contain it?
5bef4c3
to
fa80f22
Compare
@swift-ci Please smoke test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Alexis! This seems reasonable to me, especially if ignoring the adjacent swiftmodule is something we're moving towards for the build anyway.
With the change to not attempt to reload broken modules, the only slowdown now will be the initial reload-from-interface for each module 👍. I think that's a decent tradeoff to avoid all the crashers we've been seeing.
// RUN: -Rindexing-system-module \ | ||
// RUN: %t/Client.swift \ | ||
// RUN: 2>&1 | %FileCheck -check-prefix=BROKEN-BUILD-2 --allow-empty %s | ||
// BROKEN-BUILD-2-NOT: indexing system module |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's working nicely!
fa80f22
to
0ed635c
Compare
@swift-ci Please smoke test |
1 similar comment
@swift-ci Please smoke test |
@swift-ci Please smoke test macOS |
1 similar comment
@swift-ci Please smoke test macOS |
d89865f
to
1538fc3
Compare
Tweaked how this interacts with the in-memory cached modules. Instead of dropping the module cache it nows ignores the cache only to reload the target system module to index, and it doesn't attempt to reload the stdlib as it can break existing references to it. @swift-ci Please smoke test |
include/swift/AST/ASTContext.h
Outdated
/// Change the behavior of all loaders to ignore swiftmodules next to | ||
/// swiftinterfaces and clear the in-memory cache on a change of value. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is out of date now, ie. it doesn't clear the in-memory cache.
@@ -2441,11 +2445,12 @@ bool ASTContext::canImportModule(ImportPath::Module ModuleName, | |||
} | |||
|
|||
ModuleDecl * | |||
ASTContext::getModule(ImportPath::Module ModulePath) { | |||
ASTContext::getModule(ImportPath::Module ModulePath, bool AllowMemoryCached) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we not add the module to the loaded modules when AllowMemoryCached
is set? Ie. SerializedModuleLoader.cpp
will call Ctx.addLoadedModule(M);
after loading the module and that will replace the already loaded one. But that means that if index module A and then module B, which depends on A, we would then have the loaded-from-interface module A when indexing B.
Or does not adding the module cause issues later, eg. something could be expecting to find that module in the loaded modules map and then getting the old B when we're indexing the loaded-from-interface B?
Mostly I'm concerned that we're not expecting this type of thing to happen in the compiler, so it's possible something is caching results that will cause problems here. I don't know if that's true. Though the comment about reloading the stdlib breaking references would point to something like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with you about the potential problem here. If the current approach works, I'll look into adding what you suggest, at least for completeness purposes and it may be more important when indexing larger projects.
@swift-ci Please smoke test |
@swift-ci Please smoke test macOS |
1538fc3
to
34ce961
Compare
@swift-ci Please smoke test |
34ce961
to
ab3c186
Compare
@swift-ci Please smoke test |
swiftlang/swift-package-manager#5851 @swift-ci Please smoke test macOS |
ab3c186
to
009149a
Compare
Extracted some of the new serialization logic to a different PR and rebased on it. swiftlang/swift-package-manager#5851 @swift-ci Please smoke test |
@swift-ci Please smoke test Linux |
@swift-ci Please smoke test Linux |
009149a
to
1d46ca0
Compare
Intro ASTContext::setIgnoreAdjacentModules to change module loading to accept load only resilient modules from their swiftinterfaces, ignoring the adjacent module and any silencing swiftinterfaces errors.
Use setIgnoreAdjacentModules before indexing any resilient system module to force indexing to read only from resilient modules. rdar://100644036
Use a clean module cache in tests printing path to the swiftmodule/swiftinterface used as it may change depending on previous tests.
1d46ca0
to
5d59a8f
Compare
@swift-ci Please smoke test |
Indexing system modules while building is a crash prone phase because it tries to read everything from swiftmodules in the SDK. We saw it crash often on reading implementation details relying on implementation-only imported types.
To rule out all of these issues, let's force indexing system modules to use only swiftinterfaces in the SDK and ignores the adjacent swiftmodule files. In the future, we want a similar behavior for all compilation, not just indexing, at that time we can revert this change.
rdar://100644036