Skip to content

Simplified LXR GC - #1508

Draft
wenyuzhao wants to merge 1754 commits into
mmtk:masterfrom
wenyuzhao:lxr-x/simplified
Draft

Simplified LXR GC#1508
wenyuzhao wants to merge 1754 commits into
mmtk:masterfrom
wenyuzhao:lxr-x/simplified

Conversation

@wenyuzhao

@wenyuzhao wenyuzhao commented Jun 5, 2026

Copy link
Copy Markdown
Member

DRAFT: We may merge this PR as long as the LXR plan is working correctly, even if it still contains code that needs refactoring. This PR should also do its best to keep other parts of MMTk clean. We need to ensure the following issues are resolved before this PR is merged.

  • Some modules/types/functions/etc. are made public. We need to reduce their visibility to what's necessary.
  • Some metadata are made public. We need to reduce their visibility to what's necessary.
  • Plans other than LXR should not suffer functionality loss, including:
    • They should still support reference processing and finalization.
    • They should not assume there are only two spaces.
    • They should not assume the raw address of object reference == object start.
  • The performance of plans other than LXR should not regress.

This pull request introduces a simplified version of the LXR collector. There are many features not included in this version of LXR, such as reference processing, and they will be ported to the master branch in the future.

In addition to the LXR plan, this PR also makes the following changes to mmtk-core

  • Field unlog bits metadata and field-logging barrier. They can be used by generational and concurrent Immix plans to implement remembered set and SATB.
  • Pause::RefCount: a new pause kind for reference counting.
  • RootsWorkFactory::create_process_roots_work_with_root_kind: an experimental API with RootKind.
  • Many changes to the ImmixSpace and LargeObjectSpace to support reference counting-based Immix plans.
  • Additional object metadata to support LXR.
  • Additional scheduler stages to support LXR.
  • Each work bucket now has two queues to support deferred work packets.
  • Renamed pause-start and pause-end hooks to merge the two mechanisms from the master branch and the LXR branch to make the names consistent.- UnstraddlableRegion to prevent the invocation of region.contains on regions which objects can straddle, specifically Line.
  • Merged the implementations of ObjectReference::iterate_fields.
  • The definition of "chunk index" is changed.
  • Map32: 0 is now a valid entry of the linked list, and invalid entries are represented as -1.

Related PRs:

Line::MARK_TABLE
.bzero_metadata(block.start(), crate::policy::immix::block::Block::BYTES);
// mark objects if concurrent marking is active
if self.immix_space().should_allocate_as_live() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure why it is removed. I didn't find an alternative approach in the PR to mark new allocated objects as live.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is added back for non-LXR plans.

// is a defrag source) for every Immix-family plan, not just plans with reference
// counting enabled. So this table must always be mapped, regardless of which plan
// requests it.
ret.push(crate::policy::immix::block::Block::DEFRAG_STATE_TABLE);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is added by Claude during fixing mmtk-core test/build. It is clearly wrong. We need to revert this.

wks and others added 5 commits July 31, 2026 15:39
We let ConcurrentImmix use `add_deferred` for the `Concurrent` bucket
like LXR.  This simplifies the design so that the `Concurrent` bucket is
always flipped during the end of a pause.
// as if drained, even though unprocessed concurrent-marking work is still sitting in the
// now-inactive queue. Keep this the same enable/disable-only mechanism as master unless
// the plan is LXR.
let is_lxr = mmtk.get_plan().downcast_ref::<LXR<VM>>().is_some();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a workaround for now. Should fix it before merging the PR.

self.reusable_blocks.flush_all();
// FIXME: Do we need this for LXR? We observed this to cause fails on conix.
if !self.rc_enabled {
self.reusable_blocks.flush_all();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line was removed from this PR. Now it has been added back for non-LXR plans.

wks and others added 8 commits August 3, 2026 14:47
Currently the VO bit is not precise enough for conservative stack
scanning because dead objects in lines that also contain live objects
will still have VO bits.  It is enough for asserting that INC and DEC
never operate on dead objects.
We remove methods of `Block` and `Line` if they are already implemented
by the `Region` trait.

We split `Line::contains` into `Line::contains_obj_start` and
`Line::contains_obj_ref` to disambiguate the different intentions.
Fixed build errors.

Both master and lxr-x/simplified introduced concurrent GC options.  We
use the option introduced in master recently.

Both master and lxr-x/simplified introduced pause start/end hooks.  We
combine them and rename them `on_pause_start` and `on_pause_end` to be
consistent with the methods in `GCTriggerPolicy`.
@qinsoon

qinsoon commented Aug 7, 2026

Copy link
Copy Markdown
Member

binding-refs
OPENJDK21_BINDING_REPO=wenyuzhao/mmtk-openjdk
OPENJDK21_BINDING_REF=lxr-x/jdk21-simplified

wks added 9 commits August 7, 2026 13:18
We introduce the `UnstraddlableRegion` and move the method
`Region::containing(object: ObjectReference)` into it.

The primary intention is to prevent the invocation of
`Line::containing`.  An object may straddle multiple lines.  In this
case, the line that contains the *starting address* of the object and
the line that contains the *raw address* of `ObjectReference` will be
different.  Removing `Line::containing` will eliminate unintended
misuse.
There is no "relaxed fence"
The SlotIterator was introduced with ConcurrentImmix, and was inspired
by the SlotIterator in the LXR branch.  Observing from the use case, we
find that it is usually used as a method of `ObjectReference`, and is
not specific to tracing.  We move its implementation to
`ObjectReference::iterate_fields`.
The method `Mutator::assert_is_flushed` is never used, and the method
`Barrier::assert_is_flushed` was removed long ago.
Move the constants `LOGGED_VALUE` and `UNLOGGED_VALUE` into the
`log_bit` module.
We keep the signature of `RootsWorkFactory::create_process_roots_work`
unchanged while adding a `create_process_roots_work_with_root_kind`
method for LXR and OpenJDK.  Currently the `RootKind` contains
OpenJDK-specific concerns, and should be made VM-agnostic.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants