Skip to content

Fix compressed val register. #293

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

Closed
wants to merge 4 commits into from
Closed

Conversation

wks
Copy link
Contributor

@wks wks commented Dec 3, 2024

MMTkBarrierSetAssembler::store_at calls object_reference_write_post after calling BarrierSetAssembler::store_at. However, BarrierSetAssembler::store_at modifies the val register to compress its value in place. Consequently, object_reference_write_post will see a compressed pointer in the val register.

We decompress the pointer in the slow path before calling into MMTk core. This makes the barrier general, and fixes the assertion error when the compressed target value is not aligned, although our current ObjectBarrier doesn't use the slot and the target arguments.

Known issue: The fixed MMTkObjectBarrierSetAssembler::object_reference_write_post depends on the internal implementation of the BarrierSetAssembler::store_at method in OpenJDK. However, a general solution needs to save and restore the val register before and after calling BarrierSetAssembler::store_at, which adds an overhead in the fast path.

Fixes: #291

wks added 3 commits December 3, 2024 14:06
In `MMTkBarrierSetAssembler`, `object_reference_write_post` is called
after calling `BarrierSetAssembler::store_at` which modifies the `val`
register and compresses its value in place.  Consequently,
`object_reference_write_post` will see a compressed pointer in the `val`
register.  We decompress the pointer in the slow path before calling
into MMTk core.
@wks wks requested review from qinsoon and wenyuzhao December 3, 2024 08:02
Copy link
Member

@qinsoon qinsoon left a comment

Choose a reason for hiding this comment

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

Looks good to me.

@@ -40,6 +40,10 @@ run_all 4
# Test heap resizing
runbms_dacapo2006_with_heap_size fop 20 100

# Test compressed oops with heap range > 4GB
# When the heap size is larger than 4GiB, compressed oops will be shifted by 3 bits.
runbms_dacapo2006_with_heap_size fop 20 5000
Copy link
Member

Choose a reason for hiding this comment

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

I added tests here as a separate job: #292. We can either remove the test here, or close that PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll remove this test because #292 tests with multiple plans, and GenImmix may not be the only plan affected by the compressed oops.

I'll keep the one I added to ci-test-minimal.sh so that it will be executed for every new commit in mmtk-core.

Copy link
Member

@wenyuzhao wenyuzhao left a comment

Choose a reason for hiding this comment

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

LGTM. I don't think we have reached a conclusion in our meeting due to the time. Should we fix this parameter or remove it?

@wenyuzhao
Copy link
Member

FYI looks like it's still beneficial to have the target value. Our current object barrier conservatively remembers all the references, including mature->mature. This can be filtered out by checking the target object address. For generational GC, we only care about mature->young

@wks
Copy link
Contributor Author

wks commented Dec 4, 2024

LGTM. I don't think we have reached a conclusion in our meeting due to the time. Should we fix this parameter or remove it?

I think one thing we all agree with is that if we know what barrier we are implementing, we can do whatever we want to exploit the semantics of the barrier. In this case, we are implementing ObjectBarrier, and we know that the barrier behaves the same regardless of the value of the target argument. So we can pass null to the target parameter and expect it to continue to work.

To be safe, I'll create another PR that simply passes null to the target argument, and we discuss this further on Zulip to confirm that we agree with this idea.

@wks
Copy link
Contributor Author

wks commented Dec 4, 2024

FYI looks like it's still beneficial to have the target value. Our current object barrier conservatively remembers all the references, including mature->mature. This can be filtered out by checking the target object address. For generational GC, we only care about mature->young

I think that'll not be the (standard) object-remembering barrier. It will be a barrier specific to generational GC, and is not applicable to, for example, coalescing RC. To make it working, we need a GenObjectBarrier which implements object_reference_write_post differently (with an additional check). The OpenJDK binding, knowing the semantic difference, will not omit the target argument when using that barrier when calling object_reference_write_post. But since the slow path (remembering the object) doesn't need the target, we can probably omit the target when calling object_reference_write_slow.

But whether the new GenObjectBarrier is better than the current ObjectBarrier will be another topic. I think @steveblackburn mentioned before that each has its pros and cons, and the unconditional ObjectBarrier is faster for some reasons.

@wks
Copy link
Contributor Author

wks commented Dec 5, 2024

Our discussion indicates it's OK to do optimization by passing nullptr to those unused arguments. So I am closing this PR in favor for #294

@wks wks closed this Dec 5, 2024
wks added a commit that referenced this pull request Dec 5, 2024
`MMTkBarrierSetAssembler::store_at` calls `object_reference_write_post`
after calling `BarrierSetAssembler::store_at`. However,
`BarrierSetAssembler::store_at` modifies the `val` register to compress
its value in place. Consequently, `object_reference_write_post` will see
a compressed pointer in the `val` register.

This PR makes two changes.

Firstly, in
`MMTkObjectBarrierSetAssembler::object_reference_write_post`, we simply
set both `c_rarg1` and `c_rarg2` to 0 before calling the write barrier
slow path. We exploit the semantics of the `ObjectBarrier` that it
simply logs the object without looking at the slot or the target. This
will fix the [assertion
error](#291) because 0 will
be interpreted as a `None` of type `Option<ObjectReference>`.

Secondly, we add a `bool compensate_val_reg` parameter to
`MMTkBarrierSetAssembler::object_reference_write_post` so that if we
call it after `BarrierSetAssembler::store_at`, we can give
`object_reference_write_post` a chance to decompress the compressed oop
in the `val`. This is intended for implementing *other barriers
introduced in the future* that may use the `val` register, and keep the
developers informed that the `val` register is mutated in
`BarrierSetAssembler::store_at`.

Fixes: #291
Related PR: #293
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.

ObjectReference is required to be word aligned. addr: 0x8000026
3 participants