-
Notifications
You must be signed in to change notification settings - Fork 178
kernel: move ReaderState out of GAPState and onto the stack #3819
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
8e9f42e to
7ab4781
Compare
|
|
||
| struct ReaderState { | ||
|
|
||
| ScannerState s; |
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.
The ScannerState becomes part of the ReaderState (I've intended to do it this way for quite some time now - finally it happens, yay!)
One way to make this perhaps slightly nicer, and avoid some of the diffs in this PR permanently (i.e. not just with my crappy HACK commit) would be to switch read.c to C++, and then make ReaderState into a "subclass" of ScannerState. This way, a ReaderState * can be passed to any function expecting a ScannerState.
But I have doubts whether that's enough to justify converting the whole file to C++... ?!
| readTop = rs->ReadTop; | ||
| readTilde = rs->ReadTilde; | ||
| tilde = STATE(Tilde); | ||
| currLHSGVar = rs->CurrLHSGVar; |
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.
Here something "real" happens: we avoid the need to backing up parts of the ReaderState (and we also avoid questions about why we just save those parts of the Reader, but not others... Now we "save" all of them, automatically.)
| UInt currLHSGVar; | ||
| UInt userHasQuit; | ||
| syJmp_buf readJmpError; | ||
| UInt intrCoding; |
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.
Hmm, I guess we should rename SavedReaderState to something else...
Note that I am thinking about moving STATE(IntrCoding) and friends into a new InterpreterState (which ultimately also would be stack allocated...)
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 was done in PR #3823 which also removed SavedReaderState
7ab4781 to
ef4f2b9
Compare
ef4f2b9 to
2013750
Compare
2013750 to
f4753f3
Compare
| { | ||
| return (struct ReaderState *)StateSlotsAtOffset(ReaderStateOffset); | ||
| } | ||
| typedef struct ReaderState ReaderState; |
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.
Here we can see that there was a (per-thread) instance of struct ReaderState inside the global GAPState (accessed here via StateSlotsAtOffset), and now isn't anymore. ReaderState used to refer to a helper function to access it; now ReaderState is an alias for struct ReaderState, and we instead pass a stack-allocated instance of struct ReaderState around via function arguments
| ** be declared forward. | ||
| */ | ||
| static void ReadExpr(ScannerState * s, TypSymbolSet follow, Char mode); | ||
| static void ReadExpr(ReaderState * rs, TypSymbolSet follow, Char mode); |
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.
From here on, we see a lot of changes identical to this: instead of just a ScannerState, we now pass around a ReaderState (which contains a ScannerState).
| GAP_ASSERT(ReaderState()->CurrentGlobalForLoopDepth); | ||
| ReaderState()->CurrentGlobalForLoopDepth--; | ||
| GAP_ASSERT(rs->CurrentGlobalForLoopDepth); | ||
| rs->CurrentGlobalForLoopDepth--; |
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.
We also see a lot of changes identical to this: instead of using ReaderState(), we now use a ReaderState instance named rs which the callers passes down to us.
| else if (s->Symbol == S_LPAREN) { | ||
| Match(s, S_LPAREN, "(", S_COMMA | follow); | ||
| ReadExpr(s, follow, 'r'); | ||
| ReadExpr(rs, follow, 'r'); |
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.
Aaaand we also see a lot of these: instead of passing a ScannerState named s, we pass on a ReaderState called rs.
src/read.c
Outdated
|
|
||
|
|
||
| // HACK | ||
| #define s (&rs->s) |
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 HACK is part of the second commit (which is meant to be dropped before merging this), and only is here for review purposes, to reduce the number of meaningless diffs: where before we directly accessed a ScannerState named s, we now instead need to get the ScannerState from inside the ReaderState called rs. To hide this, we use this #define.
| memset(s, 0, sizeof(ScannerState)); | ||
| ReaderState reader; | ||
| ReaderState * volatile rs = &reader; | ||
| memset(rs, 0, sizeof(ReaderState)); |
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.
Up to here, basically nothing happened besides the things I explicitly pointed out; 99% of the changes are change ScannerState * s -> ReaderState * rs and related changes.
Here now we allocate a ReaderState on the stack, and zero 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.
Could we do ReaderState reader = {0} instead?
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 actually tried this first, but it caused compiler warnings on Travis. I couldn't reproduce those on macOS or on my Ubuntu, probably because my versions of GCC were too new.
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.
No problem. Stupid travis, but it's not worth adding code which will have warnings.
| rs->ReadTop = readTop; | ||
| rs->ReadTilde = readTilde; | ||
| STATE(Tilde) = tilde; | ||
| rs->CurrLHSGVar = currLHSGVar; |
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.
Real change: since we freshly allocated the ReaderState on the stack, there is no need to "restore" its content before returning.
| rs->ReadTop = readTop; | ||
| rs->ReadTilde = readTilde; | ||
| STATE(Tilde) = tilde; | ||
| rs->CurrLHSGVar = currLHSGVar; |
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.
Real change: since we freshly allocated the ReaderState on the stack, there is no need to "restore" its content before returning.
| } | ||
|
|
||
| GAP_ASSERT(rs->LoopNesting == 0); | ||
| nr = ReadStats(rs, S_SEMICOLON | S_EOF); |
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.
Real change: since we freshly allocated the ReaderState on the stack, there is no need to "restore" its LoopNesting member here.
| readTop = rs->ReadTop; | ||
| readTilde = rs->ReadTilde; | ||
| tilde = STATE(Tilde); | ||
| currLHSGVar = rs->CurrLHSGVar; |
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.
Real change: since we freshly allocated the ReaderState on the stack, there is no need to "preserve" its "previous" content.
| memset(s, 0, sizeof(ScannerState)); | ||
| ReaderState reader; | ||
| ReaderState * volatile rs = &reader; | ||
| memset(rs, 0, sizeof(ReaderState)); |
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.
Real change: we allocate a ReaderState on the stack and zero it.
| ReaderState()->StackNams = NEW_PLIST( T_PLIST, 16 ); | ||
| ReaderState()->ReadTop = 0; | ||
| ReaderState()->ReadTilde = 0; | ||
| ReaderState()->CurrLHSGVar = 0; |
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.
No need to preserve or restore these, as we stack allocate the ReaderState for each use freshly on the stack.
| ReaderState()->StackNams = s->stackNams; | ||
| ReaderState()->ReadTop = s->readTop; | ||
| ReaderState()->ReadTilde = s->readTilde; | ||
| ReaderState()->CurrLHSGVar = s->currLHSGVar; |
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.
No need to preserve or restore these, as we stack allocate the ReaderState for each use freshly on the stack.
| StructInitInfo * module ) | ||
| { | ||
| #if !defined(HPCGAP) | ||
| InitGlobalBag(&ReaderState()->StackNams, "src/read.c:StackNams"); |
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.
StackNams now is in a ReaderState instance on the stack, and hence our stack scanning code ensure it is not garbage collected. So this line can go.
| ReaderState()->ReadTop = 0; | ||
| ReaderState()->ReadTilde = 0; | ||
| ReaderState()->CurrLHSGVar = 0; | ||
| ReaderState()->CurrentGlobalForLoopDepth = 0; |
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.
There is no per-thread ReaderState as part of the GAPState anymore, so the above can go.
| .initKernel = InitKernel, | ||
|
|
||
| .moduleStateSize = sizeof(struct ReaderState), | ||
| .moduleStateOffsetPtr = &ReaderStateOffset, |
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.
There is no per-thread ReaderState as part of the GAPState anymore, so the above can go.
|
I've now left a bunch of comments that try to explain the changes in-depth. Perhaps that's enough to make some people dare to look at it, e.g. @DominikBernhardt @wucas @flyingapfopenguin @ChrisJefferson |
ChrisJefferson
left a comment
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.
One comment, about removing memset and using {0} instead (which isn't required). There are a couple of places this change would be made.
wilfwilson
left a comment
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 for the hand-holding comments Max.
In case you've not noticed, this PR now has conflicts with master.
f4753f3 to
d25867e
Compare
This way, saving and restoring it becomes unnecessary. It also gets easier to reason about the behaviour of the code.
d25867e to
ece4b25
Compare
This way, saving and restoring it becomes unnecessary. It also gets easier to reason about the behaviour of the code.
Note: the second commit in this PR should be removed before merging; it contains a gross
#definehack which I added to make reviewing easier, by reducing the noise in which the actual changes are otherwise lost. It's still quite a bit, but hopefully manageable.Continues work begun in PR #3805.