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

kernel: use more accurate marking #2408

Merged
merged 8 commits into from
Apr 28, 2018

Conversation

fingolfin
Copy link
Member

@fingolfin fingolfin commented Apr 26, 2018

This PR how we mark-for-garbage-collection in various bag types with GASMAN. This is motivated by @rbehrends' work on integrating Julia GC, see PR #2092

Specifically, when marking bags during garbage collection, we were very liberal in what we passed on to MarkBag (directly or indirectly). This is no big deal with GASMAN, as GASMAN can easily decide whether a given pointer is a master pointer or not (it has to be in a certain range), and ignore all other values passed to it. For other GCs, this is not quite as easy, as master pointers typically are not allocated from a fixed pool (though one could think about doing that... with the provision that one may have to maintain multiple such pools...)

This PR resolves most of these issues:

  • we abused T_BODY bags in code.c to maintain two stacks of statements resp. expressions, which are not bags. But in a T_BODY, the first three slots are expected to be bag refs. This wasn't the case for these stacks. So now we use a T_DATOBJ for them (and make sure to leave its type slot intact)
  • we marked all slots in plists via MarkAllSubBags; but the first slot contains the length of the list; fixed via new marking function MarkAllButFirstSubBags
  • we marked all slots in precords and component objects via MarkAllSubBags; but only slot 0 (for component objects), and the odd slots starting with slot 3, contain bag refs. Fixed with a custom marking function MarkPRecSubBags
  • we marked all slots in T_FUNCTION objects via MarkAllSubBags; but we store pointers to C functions in the first 8 slots, and also stored raw UInt values in two other slots. The latter were replaced by immediate integer objects; and a custom marking function MarkFunctionSubBags was added, which skips the first 8 slots, and only marks the rest.
  • I also added a debug #define DEBUG_GASMAN_MARKING which enables code that tests if MarkBag is called on something that is neither a valid bag ref, a valid immediate object (integer or FFE), nor a null pointer. This can be used to track down more instances of the problem type described here, which is much easier than trying to do so while also hooking up a new GC at the same time ;-).
  • For LVars and HVars, there is an Expr in slot 1 which should not marked. I moved it from slot 1 into slot 0, and then made it use MarkAllButFirstSubBags. This also required tweaking the LVars pool code, which I did (it is now also documented and more readable).

@fingolfin fingolfin added topic: kernel release notes: not needed PRs introducing changes that are wholly irrelevant to the release notes labels Apr 26, 2018
@codecov
Copy link

codecov bot commented Apr 26, 2018

Codecov Report

Merging #2408 into master will increase coverage by <.01%.
The diff coverage is 99.09%.

@@            Coverage Diff             @@
##           master    #2408      +/-   ##
==========================================
+ Coverage   73.88%   73.88%   +<.01%     
==========================================
  Files         484      484              
  Lines      245435   245458      +23     
==========================================
+ Hits       181333   181361      +28     
+ Misses      64102    64097       -5
Impacted Files Coverage Δ
src/precord.h 96.87% <ø> (ø) ⬆️
src/gasman.h 90% <ø> (ø) ⬆️
src/vars.h 100% <ø> (ø) ⬆️
src/boehm_gc.c 93.68% <0%> (-0.5%) ⬇️
src/objects.c 80.1% <100%> (ø) ⬆️
src/calls.c 93.75% <100%> (+0.05%) ⬆️
src/code.c 93.76% <100%> (+0.18%) ⬆️
src/vars.c 86.3% <100%> (+0.01%) ⬆️
src/opers.c 94.67% <100%> (ø) ⬆️
src/calls.h 95.74% <100%> (ø) ⬆️
... and 7 more

@ChrisJefferson
Copy link
Contributor

Looks good to me. Just in case anyone has the same thought as me, I wondered about only checking up to LEN_PLIST or LEN_PREC, rather than the end of the bag, but that doesn't work as we often put values into lists/records before we update their length (and I guess the problems will be even worse in parallel!)

If DEBUG_GASMAN_MARKING is #defined, then we increment a counter
whenever `MarkBag` is called on something that isn't either zero,
or a valid bag ref, or an immediate integer or FFE.

By setting a break point on the line incrementing BadMarksCounter,
one can quickly find out which bags are affected.
Not all slots of a T_FUNCTION bag are filled with bag refs, yet when
marking the slots of such a bag during garbage collection, we still used
MarkAllSubBags. This is usually no problem with GASMAN, as it detects if
a pointer isn't a master pointer, and can then simply ignore it. But
other garbage collections can't as easily verify master pointers. So
let's try to be accurate about what we mark as a bag and what not: skip
the first eight slots of every T_FUNCTION bag for marking (they contain
pointers to C functions), and also ensure that the rest of any
T_FUNCTION bag only contains bag refs.

Also fix a bug in saving/restoring operations, where the 'enabled' field
was stored as an UInt, even though it now is an Obj (though we currently
only store immediate ints in it, hence there was no functional problem).
They now all call MarkArrayOfBags, but thanks to inlining, this produces
identical machine code.
... instead of a T_BODY, as we don't really create a T_BODY here.
(and this can lead to confusion in GC marking)
@fingolfin fingolfin merged commit d0693f8 into gap-system:master Apr 28, 2018
@fingolfin fingolfin deleted the mh/gc-mark-bags branch April 28, 2018 11:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release notes: not needed PRs introducing changes that are wholly irrelevant to the release notes topic: kernel
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants