-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[libSyntax] Assert there are no reference-cycles in the SyntaxArenas #36232
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 |
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.
Traversing a whole tree just for an assertion looks to be an overkill, but I think it's OK because the number of SyntaxArena
must be fairly low.
include/swift/Syntax/SyntaxArena.h
Outdated
if (PreviousNodes.count(this) > 0) { | ||
return true; | ||
} | ||
for (auto ChildArena : ChildArenas) { | ||
std::set<SyntaxArena *> NewPreviousNodes = PreviousNodes; | ||
NewPreviousNodes.insert(this); | ||
if (ChildArena->containsReferenceCycle(NewPreviousNodes)) { | ||
return true; | ||
} | ||
} | ||
return false; |
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.
Since PreviousNodes
is already copied, we don't need to make a new copy.
if (PreviousNodes.count(this) > 0) { | |
return true; | |
} | |
for (auto ChildArena : ChildArenas) { | |
std::set<SyntaxArena *> NewPreviousNodes = PreviousNodes; | |
NewPreviousNodes.insert(this); | |
if (ChildArena->containsReferenceCycle(NewPreviousNodes)) { | |
return true; | |
} | |
} | |
return false; | |
if (!PreviousNodes.insert(this).second) | |
return true; | |
return llvm::any_of(ChildArenas, [&](SyntaxArena *Child) { | |
Child->containsReferenceCycle(PreviousNodes) | |
}); |
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.
Oh, yeah. For some reason I though I was adding a different node depending on which child node I was visiting. But of course I’m not. Also your implementation looks much cleaner. I changed it. Also renamed PreviousNodes
to VisitedArenas
.
include/swift/Syntax/SyntaxArena.h
Outdated
auto DidInsert = ChildArenas.insert(Arena); | ||
if (DidInsert.second) { | ||
Arena->Retain(); | ||
assert(!containsReferenceCycle()); |
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.
assert(!containsReferenceCycle()); | |
assert(!Arena->containsReferenceCycle({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.
Nice and small performance improvement. I like it 👍🏽
include/swift/Syntax/SyntaxArena.h
Outdated
} | ||
} | ||
|
||
bool containsReferenceCycle(std::set<SyntaxArena *> PreviousNodes = {}) { |
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.
const
if possible.
I don’t expect there to ever be more than, say, 5 arenas, so the performance hit should be pretty marginal. Plus it’s only in assert builds, so I guess it should be fine. |
a8ca2b8
to
c7ba6d8
Compare
c7ba6d8
to
7be84c1
Compare
@swift-ci Please smoke test |
As discussed here.