Skip to content

Fix stale forwarding bits bug #777

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

Merged
merged 1 commit into from
Mar 14, 2023
Merged

Fix stale forwarding bits bug #777

merged 1 commit into from
Mar 14, 2023

Conversation

wks
Copy link
Collaborator

@wks wks commented Mar 10, 2023

When copying, we erroneously assumed that the forwarding bits of the new copy must not have been set if the forwarding bits metadata is on the side. If the new copy is allocated in a previously free chunk, it may contain stale forwarding bits from the previous GC.

Now we clear forwarding bits in post_copy regardless whether the forwarding bits metadata is in the header or on the side.

Given that post_copy always clears forwarding bits, PrepareBlockState now only clears forwarding bits for defrag source blocks of ImmixSpace.

Closes: #776

When copying, we erroneously assumed that the forwarding bits of the new
copy must not have been set if the forwarding bits metadata is on the
side.  If the new copy is allocated in a previously free chunk, it may
contain stale forwarding bits from the previous GC.

Now we clear forwarding bits in post_copy regardless whether the
forwarding bits metadata is in the header or on the side.

Given that post_copy always clears forwarding bits, PrepareBlockState
now only clears forwarding bits for defrag source blocks of ImmixSpace.

Closes: mmtk#776
@wks wks requested a review from qinsoon March 12, 2023 13:31
@@ -808,6 +802,18 @@ impl<VM: VMBinding> GCWork<VM> for PrepareBlockState<VM> {
block.set_state(BlockState::Unmarked);
debug_assert!(!block.get_state().is_reusable());
debug_assert_ne!(block.get_state(), BlockState::Marked);
// Clear forwarding bits if necessary.
if is_defrag_source {
if let MetadataSpec::OnSide(side) = *VM::VMObjectModel::LOCAL_FORWARDING_BITS_SPEC {
Copy link
Member

Choose a reason for hiding this comment

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

This moves the bzero code from reset_object_mark() which does bzero unconditionally for the entire chunk to here, which is conditional (is_defrag_source and not Unallocated), and zeroed at block granularity. Is this an optimization?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes. This is an optimisation. It will still be correct if we zero entire chunks unconditionally.

Previously, it was necessary to clear all forwarding bits of all chunks because post_copy assumed all forwarding bits for all chunks were cleared. Since post_copy now unconditionally clears the forwarding bits of new copies, we no longer need to clear the forwarding bits of all chunks. We only need to ensure all objects that can be moved have their forwarding bits (of the old copies) cleared before copying them.

An alternative solution is letting PrepareBlockState clear all forwarding bits of all Allocated and Free chunks so that post_copy can still elide the clearing of forwarding bits. That would be too costly because very few blocks are defrag sources. If the number of copied objects is small, it should be faster to clear the forwarding bits for less blocks in PrepareBlockState and clear the forwarding bits for more objects in post_copy.

Copy link
Member

Choose a reason for hiding this comment

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

I see. The bulk zeroing was also introduced in d341506. So this PR basically reverts both changes in that commit, and does bulk zeroing in another place to fix the original problem. It is probably worth mentioning the commit d341506 in the description (which will be the merge commit message).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure. I'll mention it when merging.

@qinsoon qinsoon added the PR-testing Run binding tests for the pull request (deprecated: use PR-extended-testing instead) label Mar 13, 2023
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.

LGTM

@qinsoon
Copy link
Member

qinsoon commented Mar 14, 2023

The Julia tests failed. But it seems to be a network issue. I don't think it is related with this PR.

@wks wks merged commit 4cefff7 into mmtk:master Mar 14, 2023
JunmingZhao42 pushed a commit to JunmingZhao42/mmtk-core that referenced this pull request Mar 19, 2023
When copying, we erroneously assumed that the forwarding
bits of the new copy must not have been set if the forwarding
bits metadata is on the side.  That assumption was introduced in
mmtk@d341506
as an optimisation to reduce the number of forwarding bits clearing.
However, it is unsound.  If the new copy is allocated in a previously
free chunk, it may contain stale forwarding bits from the previous GC.

Now we clear forwarding bits in post_copy regardless whether the
forwarding bits metadata is in the header or on the side.

Given that post_copy always clears forwarding bits, PrepareBlockState
now only clears forwarding bits for defrag source blocks of ImmixSpace.

Closes: mmtk#776
wenyuzhao pushed a commit to wenyuzhao/mmtk-core that referenced this pull request Mar 20, 2023
When copying, we erroneously assumed that the forwarding
bits of the new copy must not have been set if the forwarding
bits metadata is on the side.  That assumption was introduced in
mmtk@d341506
as an optimisation to reduce the number of forwarding bits clearing.
However, it is unsound.  If the new copy is allocated in a previously
free chunk, it may contain stale forwarding bits from the previous GC.

Now we clear forwarding bits in post_copy regardless whether the
forwarding bits metadata is in the header or on the side.

Given that post_copy always clears forwarding bits, PrepareBlockState
now only clears forwarding bits for defrag source blocks of ImmixSpace.

Closes: mmtk#776
wenyuzhao pushed a commit to wenyuzhao/mmtk-core that referenced this pull request Mar 22, 2023
When copying, we erroneously assumed that the forwarding
bits of the new copy must not have been set if the forwarding
bits metadata is on the side.  That assumption was introduced in
mmtk@d341506
as an optimisation to reduce the number of forwarding bits clearing.
However, it is unsound.  If the new copy is allocated in a previously
free chunk, it may contain stale forwarding bits from the previous GC.

Now we clear forwarding bits in post_copy regardless whether the
forwarding bits metadata is in the header or on the side.

Given that post_copy always clears forwarding bits, PrepareBlockState
now only clears forwarding bits for defrag source blocks of ImmixSpace.

Closes: mmtk#776
(cherry picked from commit 4cefff7)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PR-testing Run binding tests for the pull request (deprecated: use PR-extended-testing instead)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Assertion failure in post_copy
2 participants