Skip to content
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

Fix retain cycles in the Swift runtime #2076

Merged
merged 12 commits into from
Oct 27, 2017

Conversation

ewanmellor
Copy link
Contributor

Fix a number of retain cycles in the Swift runtime (see the individual changesets for details). These were causing the lexer, parser, ATN simulators, and tokens all to be retained after a parse.

Add RecognitionException.{clearRecognizer,clearInputStream} so that client code can clear those fields if desired, thus releasing the parser / token stream if it is not needed for error handling.

This depends on PR #2075 (and transitively upon PR #2072) due to merge conflicts.

These were ported over from the Java runtime, but they were all deprecated
there, and were commented as such here.  There is no point having them in
the Swift runtime because we don't have legacy code to support.
This fixes some hangovers from the port from Java:
* unnecessary type annotations;
* failure to use "if let" for nil checks;
* comments with Java code in them;
* a couple of fields that should have been declared private;
* some whitespace issues.

No semantic change.
This has been ported over from the Java code, but it was deprecated there.
There's no point having it in the Swift runtime because we don't have the
legacy code to support.  Also, it wasn't implemented properly, so it
never worked.

Remove {DFA,IntervalSet}.toString(_:[String?]?)
and the inits in ParserInterpreter and DFASerializer for the same reason.
Switch the unit tests to use the alternate toString(_:Vocabulary).
This was doing nothing for us that we couldn't already get with fatalError,
so it was just cluttering things.
This is a port of the equivalent code in the Java runtime.

This required a change to the CharStream interface: getText was documented
as throwing exceptions, but it wasn't actually declared as such.  The
UnbufferedCharStream.getText implementation throws exceptions (in order to
match the semantics of the Java implementation), so this declaration is now
needed, and callsites need to be adjusted appropriately.
This refers back up the tree of RuleContext instances, and meant that the
whole tree was leaked.  Fix this by making the parent field weak.
This refers back up the parse tree, and meant that the
whole tree was leaked.  Fix this by making the parent field weak.
This was causing the entire parser to be retained, resulting in a large
memory leak.

This fix simply changes the reference from ParserATNSimulator to Parser
to be unowned.

Ditto between Lexer and LexerATNSimulator, except this reference is made
weak because LexerATNSimulator.recog is nullable.  (That difference is
dubious IMHO, but I'm leaving it intact for now.)
…rom.

This was causing all the tokens, streams, and lexers to be retained.  The
primary cycle was because of the backreference at CommonToken.source, and
the fact that the token streams buffer the tokens that they create.

Fix this by replacing the use of a (TokenSource?, CharStream?) pair with
TokenSourceAndStream, which does the same job but references its fields
weakly.  This means that Token.getTokenSource() and Token.getInputStream()
will return valid values as long as you retain the lexer / stream elsewhere,
but a Token won't itself retain those things.
token stream that triggered the error.

These are useful for error diagnostics, but if client code wants to throw
the RecognitionException but discard the parser and token stream, then
the fields in RecognitionException need to be cleared.

This adds RecognitionException.{clearRecognizer,clearInputStream} so that
client code can clear those fields if desired.  It also makes
RecognitionException.ctx weak, so it will go nil at the same time as
the parser is discarded.
@parrt parrt added this to the 4.7.1 milestone Oct 27, 2017
@parrt parrt merged commit bce47ca into antlr:master Oct 27, 2017
@ewanmellor ewanmellor deleted the swift-retain-cycles branch October 29, 2017 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants