Skip to content

[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

Merged
merged 14 commits into from
Oct 31, 2022

Conversation

xymus
Copy link
Contributor

@xymus xymus commented Oct 20, 2022

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

@xymus xymus requested a review from bnbarham October 20, 2022 21:05
@xymus
Copy link
Contributor Author

xymus commented Oct 20, 2022

@swift-ci Please smoke test

@benlangmuir
Copy link
Contributor

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?

module->getASTContext().setIgnoreAdjacentModules(true);

ImportPath::Module::Builder builder(module->getName());
auto reloadedModule = module->getASTContext().getModule(builder.get());
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor Author

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.

@xymus xymus force-pushed the index-swiftinterfaces branch from 2c1a719 to 7b8547b Compare October 21, 2022 19:28
@xymus
Copy link
Contributor Author

xymus commented Oct 21, 2022

Pushing a new version to run tests. I still have some offline comments to look into.

@swift-ci Please smoke test

@xymus
Copy link
Contributor Author

xymus commented Oct 21, 2022

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?

That's correct, only the adjacent modules are ignored.

@xymus
Copy link
Contributor Author

xymus commented Oct 21, 2022

@swift-ci Please smoke test

module->getASTContext().setIgnoreAdjacentModules(true);

ImportPath::Module::Builder builder(module->getName());
auto reloadedModule = module->getASTContext().getModule(builder.get());
Copy link
Contributor

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?

@xymus xymus force-pushed the index-swiftinterfaces branch from 5bef4c3 to fa80f22 Compare October 21, 2022 23:11
@xymus
Copy link
Contributor Author

xymus commented Oct 21, 2022

@swift-ci Please smoke test

Copy link
Contributor

@bnbarham bnbarham left a 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's working nicely!

@xymus xymus force-pushed the index-swiftinterfaces branch from fa80f22 to 0ed635c Compare October 21, 2022 23:33
@xymus
Copy link
Contributor Author

xymus commented Oct 21, 2022

@swift-ci Please smoke test

1 similar comment
@xymus
Copy link
Contributor Author

xymus commented Oct 24, 2022

@swift-ci Please smoke test

@xymus
Copy link
Contributor Author

xymus commented Oct 24, 2022

@swift-ci Please smoke test macOS

1 similar comment
@xymus
Copy link
Contributor Author

xymus commented Oct 24, 2022

@swift-ci Please smoke test macOS

@xymus xymus force-pushed the index-swiftinterfaces branch from d89865f to 1538fc3 Compare October 25, 2022 17:35
@xymus
Copy link
Contributor Author

xymus commented Oct 25, 2022

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

Comment on lines 1175 to 1176
/// Change the behavior of all loaders to ignore swiftmodules next to
/// swiftinterfaces and clear the in-memory cache on a change of value.
Copy link
Contributor

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) {
Copy link
Contributor

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.

Copy link
Contributor Author

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.

@xymus
Copy link
Contributor Author

xymus commented Oct 25, 2022

@swift-ci Please smoke test

@xymus
Copy link
Contributor Author

xymus commented Oct 26, 2022

@swift-ci Please smoke test macOS

@xymus xymus force-pushed the index-swiftinterfaces branch from 1538fc3 to 34ce961 Compare October 26, 2022 23:40
@xymus
Copy link
Contributor Author

xymus commented Oct 26, 2022

@swift-ci Please smoke test

@xymus xymus force-pushed the index-swiftinterfaces branch from 34ce961 to ab3c186 Compare October 27, 2022 16:10
@xymus
Copy link
Contributor Author

xymus commented Oct 27, 2022

@swift-ci Please smoke test

@xymus
Copy link
Contributor Author

xymus commented Oct 27, 2022

swiftlang/swift-package-manager#5851

@swift-ci Please smoke test macOS

@xymus
Copy link
Contributor Author

xymus commented Oct 28, 2022

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

@xymus
Copy link
Contributor Author

xymus commented Oct 28, 2022

@swift-ci Please smoke test Linux

@xymus
Copy link
Contributor Author

xymus commented Oct 30, 2022

Cannot contact i-09a88659ae06fbf33: hudson.remoting.ChannelClosedException: Channel "hudson.remoting.Channel@3cbfe351:i-09a88659ae06fbf33": Remote call on i-09a88659ae06fbf33 failed. The channel is closing down or has closed down

@swift-ci Please smoke test Linux

@xymus xymus force-pushed the index-swiftinterfaces branch from 009149a to 1d46ca0 Compare October 31, 2022 17:43
xymus added 14 commits October 31, 2022 10:58
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.
@xymus xymus force-pushed the index-swiftinterfaces branch from 1d46ca0 to 5d59a8f Compare October 31, 2022 18:11
@xymus
Copy link
Contributor Author

xymus commented Oct 31, 2022

@swift-ci Please smoke test

@xymus xymus merged commit 47b29b6 into swiftlang:main Oct 31, 2022
@xymus xymus deleted the index-swiftinterfaces branch October 31, 2022 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants