-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[RemoteMirror] Fix demangle node corruption caused by excessively eager clearing of the NodeFactory. #64674
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
[RemoteMirror] Fix demangle node corruption caused by excessively eager clearing of the NodeFactory. #64674
Conversation
@swift-ci please test |
@swift-ci please test macos platform |
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.
LGTM.
@@ -93,6 +93,7 @@ RemoteRef<char> TypeRefBuilder::readTypeRef(uint64_t remoteAddr) { | |||
/// Load and normalize a mangled name so it can be matched with string equality. | |||
llvm::Optional<std::string> | |||
TypeRefBuilder::normalizeReflectionName(RemoteRef<char> reflectionName) { | |||
auto checkpoint = pushNodeFactoryCheckpoint(); |
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.
A lot of code that does this seems to follow the pattern
auto checkpoint = pushNodeFactoryCheckpoint();
...
popNodeFactoryCheckpoint(checkpoint);
which makes me wonder whether we should have a
template <typename T, typename F>
T withScopedNodes(F func) {
auto checkpoint = pushNodeFactoryCheckpoint();
T result = func();
popNodeFactoryCheckpoint(checkpoint);
return result;
}
or similar (obviously that's written OTOH in a Github comment, but you get the 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.
RAII would be more idiomatic in C++. I've gone ahead and added a little RAII wrapper and switched over to that. The scoping makes things less convenient in a couple of places where we declare locals that get used later, but overall it's nicer.
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 seems to have Swift on the brain at the moment. Yes, RAII is more idiomatic in C++.
9f18a44
to
4fda3b4
Compare
@swift-ci please test |
…er clearing of the NodeFactory. We clear the NodeFactory to prevent unbounded buildup of allocated memory, but this is done too eagerly. In particular, normalizeReflectionName can end up clearing the factory while the calling code is still using nodes that were allocated from it. To keep peak memory usage low while avoiding this problem, we introduce a checkpoint mechanism in NodeFactory. A checkpoint can be pushed and then subsequently popped. When a checkpoint is popped, only the nodes allocated since the checkpoint was pushed are invalidated and the memory reclaimed. This allows us to quickly clear short-lived nodes like those created in normalizeReflectionName, while preserving longer-lived nodes used in code calling it. Uses of clearNodeFactory are replaced with this checkpoint mechanism. rdar://106547092
4fda3b4
to
fbc3f69
Compare
@swift-ci please test |
We clear the NodeFactory to prevent unbounded buildup of allocated memory, but this is done too eagerly. In particular, normalizeReflectionName can end up clearing the factory while the calling code is still using nodes that were allocated from it.
To keep peak memory usage low while avoiding this problem, we introduce a checkpoint mechanism in NodeFactory. A checkpoint can be pushed and then subsequently popped. When a checkpoint is popped, only the nodes allocated since the checkpoint was pushed are invalidated and the memory reclaimed. This allows us to quickly clear short-lived nodes like those created in normalizeReflectionName, while preserving longer-lived nodes used in code calling it. Uses of clearNodeFactory are replaced with this checkpoint mechanism.
rdar://106547092