-
Notifications
You must be signed in to change notification settings - Fork 5
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
Support copying GC #18
Comments
Copying GC support has been merged to the main branches of
It can now use the PPPs are handled. Roots are currently pinned using the object-pinning API instead of black roots. We can use the black roots mechanism instead, and we can enable the movement of some non-pinning roots, too. |
Issues about pinning roots (red/black roots) have been resolved. We probably don't need moving global roots now because very few global roots can be updated. MMTk-Ruby is already able outperforming vanilla Ruby on Liquid benchmark at certain heap sizes after we started tuning performance. I am closing this issue. |
Challenges for supporting copying GC include
finalizer_trable
Handling of roots:
mmtk::memory_manager::pin_object
)Make some roots movable.Upstream changes needed for copying GC
Scan roots usingtrace_object
directly. Exposetrace_object
to the VM binding mmtk-core#710Needed to support movable rootsNo. We probably don't need it.Adding support for red/black roots mmtk-core#706This PR enables transitively pinning (TP) objects from particular roots for Immix/StickyImmix mmtk-core#897rb_gc_mark
.Correctness goals
Performance goals
Un-update-able references
One challenge of supporting copying GC in Ruby is that some object references cannot be updated. Specifically,
rb_gc_mark
duringgc_mark_roots
. Those fields cannot be updated.Because object references held in those places cannot be updated, the objects pointed by those reference must be pinned. In other words, if an object has type
T_DATA
,T_IMEMO
,T_HASH
or has the, the object itself can move, but it pins its children.EXIVAR
flagRecording "potential pinning parents"
The Ruby binding shall maintain a runtime list of "potential pinning parents" (PPP for short). That includes all types of object in (3) in the previous section. Specifically,
T_DATA
, and those listedT_MEMO
are instantiated, we add them to the PPP list.T_HASH
becomescompare_by_identity
or when an object gets theEXIVAR
flag, we add it to the PPP list.Note that some PPPs don't always pin their children. Some
T_DATA
can actually move their children because it is modern, and the developers usedrb_gc_mark_movable
and provided thedcompact
function. For other PPPs, their pinning fields may just benil
at the moment of the GC. But we have to add them to the PPP list conservatively because we don't know if aT_DATA
is modern enough or if any field isnil
.We visit all PPPs before GC and pin their children (via pinning fields only), so when GC starts, those children won't move. Note that
After GC, re-visit the PPP list, and remove all dead objects from it. Unpin live objects in the PPP list.
More language-neutral discussions on this topic are here: mmtk/mmtk-core#690
Ways to reduce the number of potential pinning parents
T_DATA
objects that support declarative marking are not considered PPPs.T_DATA
types in Ruby core/stdlib that are known not to pin childrenT_DATA
types in Ruby core/stdlib, replace theirrb_gc_mark
withrb_gc_mark_movable
, and introduce compaction functions for them.Address-aware data structures
Global address-to-ID table
In Ruby, objects may optionally have an ID. Once the ID of an object is seen, it will never change as long as it is alive. In vanilla Ruby, it maintains two tables:
Those table are maintained when objects are moved (in
gc_move
) and entries are removed when objects die (inobj_free
).In MMTk, we should consider them weak maps, and use our existing weak reference processing framework to handle them. Effectively, those table entries are things that gets garbage-collected when their owners (the object) die. We can treat both
id_to_obj_tbl
andobj_to_id_tbl
as one single bi-directional weak map.Interestingly, this is exactly what WeakReferences are intended for. In Java documentation:
Global address-to-gen_ivtbl map
If an object is not
T_OBJECT
, its instance variables (@foo
,@bar
, ... in Ruby language) are stored in an external generic instance variable table (gen_ivtbl), and is associated to the object via a global hash map (generic_iv_tbl_
), with the object address as key, and the gen_ivtbl as value.This global map (
generic_iv_tbl_
invariable.c
) needs to be updated whenever an object is moved. In vanilla Ruby, this is done ingc_move
, by callingrb_mv_generic_ivar
Like the address-to-ID table, this is also a "canonical map", and should be treated as a weak map with weak keys.
The text was updated successfully, but these errors were encountered: