Skip to content

Choose Non-moving Policy based on features #1308

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

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

qinsoon
Copy link
Member

@qinsoon qinsoon commented Apr 23, 2025

This PR uses an Immix space as the default non moving space, and adds two features to use mark sweep or immortal as the non moving space.

  • Mutator now includes 2 Immix allocators (one for Immix as the default space, and the other for Immix as the non moving space).
  • Call prepare/release/end_of_gc for the non moving space.
  • Add common_prepare_func and common_release_func for mutators.

qinsoon added 8 commits April 23, 2025 00:15
commit 4472263
Author: Yi Lin <[email protected]>
Date:   Thu Apr 17 04:32:13 2025 +0000

    Remove an outdated assertion

commit abbde8b
Author: Yi Lin <[email protected]>
Date:   Thu Apr 17 03:39:41 2025 +0000

    Remove ALLOC_TABLE from local specs. Fix build for 1.74.1

commit 1c64dcb
Author: Yi Lin <[email protected]>
Date:   Thu Apr 17 01:21:45 2025 +0000

    Make chunk map as global side metadata

commit b7b5988
Author: Yi Lin <[email protected]>
Date:   Tue Apr 15 04:33:21 2025 +0000

    Refactor ChunkState to encode space index
commit 530d80c
Author: Yi Lin <[email protected]>
Date:   Tue Apr 22 04:03:27 2025 +0000

    Fix

commit 836cac5
Author: Yi Lin <[email protected]>
Date:   Thu Apr 17 04:27:11 2025 +0000

    Allow configuring each Immix space to be non moving
@qinsoon
Copy link
Member Author

qinsoon commented May 6, 2025

binding-refs
OPENJDK_BINDING_REPO=qinsoon/mmtk-openjdk
OPENJDK_BINDING_REF=update-mmtk-core-1308
JULIA_BINDING_REPO=qinsoon/mmtk-julia
JULIA_BINDING_REF=update-mmtk-core-1308
JIKESRVM_BINDING_REPO=qinsoon/mmtk-jikesrvm
JIKESRVM_BINDING_REF=update-mmtk-core-1308

@qinsoon qinsoon force-pushed the nonmoving-space-options branch from 654ec4d to 0763fb7 Compare May 7, 2025 07:10
# Group:marksweepallocation
# default is native allocator with lazy sweeping
eager_sweeping = []
# Use library malloc as the freelist allocator for mark sweep. This will makes mark sweep slower. As malloc may return addresses outside our
# normal heap range, we will have to use chunk-based SFT table. Turning on this feature will use a different SFT map implementation on 64bits,
# and will affect all the plans in the build. Please be aware of the consequence, and this is only meant to be experimental use.
malloc_mark_sweep = []

# Group:nonmovingspace
immortal_as_nonmoving = []
Copy link
Member Author

Choose a reason for hiding this comment

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

This is a bit awkward. Ideally, we should have 3 features immix_as_nonmoving, immortal_as_nonmoving and marksweep_as_nonmoving, and we use immix_as_nonmoving as a default feature. But we need to ensure that for every build, exactly one feature from those 3 features is enabled. This also applies to the mark sweep features above, which should be 3 features lazy_sweeping, eager_sweeping and malloc_mark_sweep, and we need to choose exactly one.

So basically we need mutually exclusive features, and we need to make sure the features are mandatory that you need to use one of them. We cannot do this with cargo. In our test script, we try to achieve this when we cover all the builds with different features, but our test script only supports optional mutually exclusive features. So for now, we assume the default (without any feature to control it), and make the other two features optional and mutually exclusive.

I would like to do this refactoring in a separate PR.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Collaborator

Choose a reason for hiding this comment

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

Default features can be disabled (see https://doc.rust-lang.org/cargo/reference/features.html#the-default-feature). mmtk-core currently has one default feature: builtin_env_logger, and VM bindings that use their own logging frameworks (such as OpenJDK) could disable default features and wire Rust logs into their own.

If the user disables default features, there will be neither immix_as_nonmoving, immortal_as_nonmoving nor marksweep_as_nonmoving. So we need to consider the case that there is no non-moving space.

Actually I think the default should be "no non-moving space". Not all VMs need that. Neither OpenJDK, JikesRVM nor Ruby need it. We can make all of them optional, and use the trick described in https://doc.rust-lang.org/cargo/reference/features.html#mutually-exclusive-features to reject multiple non-moving spaces.

@qinsoon qinsoon added the PR-extended-testing Run extended tests for the pull request label May 8, 2025
@qinsoon qinsoon requested a review from wks May 8, 2025 04:39
@qinsoon qinsoon marked this pull request as ready for review May 8, 2025 04:39
Copy link
Collaborator

@wks wks left a comment

Choose a reason for hiding this comment

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

I refactored the code a bit to make NonMovingSpace a trait. By doing so, we greatly reduced the amount of cfg attributes used.

https://github.com/qinsoon/mmtk-core/compare/nonmoving-space-options...wks:mmtk-core:feature/nonmoving-space-options-trait?expand=1

If you think that is appropriate, you can cherry-pick it into this PR.
Please tell me if it is appropriate, as I am still adding comments and making other changes.

@wks
Copy link
Collaborator

wks commented May 8, 2025

OK. I have pushed more changes to

https://github.com/qinsoon/mmtk-core/compare/nonmoving-space-options...wks:mmtk-core:feature/nonmoving-space-options-trait?expand=1

@qinsoon You can merge it into your nonmoving-space-options branch to make it part of this PR if you think it is appropriate.

I am also trying to further remove the cfg in create_allocator_mapping (see here), but without success. I basically wanted to use the "visitor pattern" to remove the cascading if-else. But the ChosenNonMovingSpace type still has a <VM> type parameter, while the create_allocator_mapping doesn't have that. I think there is a deeper problem that create_allocator_mapping should really visit each space in the Plan and let each space reserve its desired allocator. But that requires more refactoring, and may be better done in a separate PR.

Comment on lines +549 to +556
#[cfg(feature = "immortal_as_nonmoving")]
pub type NonMovingSpace<VM> = crate::policy::immortalspace::ImmortalSpace<VM>;

#[cfg(not(any(feature = "immortal_as_nonmoving", feature = "marksweep_as_nonmoving")))]
pub type NonMovingSpace<VM> = crate::policy::immix::ImmixSpace<VM>;

#[cfg(feature = "marksweep_as_nonmoving")]
pub type NonMovingSpace<VM> = crate::policy::marksweepspace::native_ms::MarkSweepSpace<VM>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

If you think it is not worth introducing the trait NonMovingSpace as I suggested in #1308 (comment), we can still simplify this part of the code with cfg_if::cfg_if!. The else branch can save you from having to type not(any(feature = "immortal_as_nonmoving", feature = "marksweep_as_nonmoving")).

Copy link
Member Author

Choose a reason for hiding this comment

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

See my comments in #1308 (comment). I would like to introduce a feature immix_as_nonmoving as a default feature. That would solve most of the issues here with annoying cfg (we also have the same issue with the features like malloc_jemalloc, and eager_sweep).

&self.nonmoving
}

fn new_nonmoving_space(args: &mut CreateSpecificPlanArgs<VM>) -> NonMovingSpace<VM> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

And we can use cfg_if in these functions, too.

Comment on lines +542 to +543
} else {
panic!("No policy selected for nonmoving space")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Actually the first branch cfg!(not(any(feature = "immortal_as_nonmoving", feature = "marksweep_as_nonmoving"))) covers all other cases, so this else is unreachable. But I suggest we move reserved.add_immix_allocator() into this else branch and removt the first if cfg!(not(any(..., ...))) branch.

reserved.add_immix_allocator()
} else if cfg!(feature = "immortal_as_nonmoving") {
reserved.add_bump_pointer_allocator()
} else {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here.

@qinsoon
Copy link
Member Author

qinsoon commented May 8, 2025

I refactored the code a bit to make NonMovingSpace a trait. By doing so, we greatly reduced the amount of cfg attributes used.

https://github.com/qinsoon/mmtk-core/compare/nonmoving-space-options...wks:mmtk-core:feature/nonmoving-space-options-trait?expand=1

If you think that is appropriate, you can cherry-pick it into this PR. Please tell me if it is appropriate, as I am still adding comments and making other changes.

I considered introducing a struct NonMovingSpace, but I gave up the idea. I think it is inconsistent with the design. We have policies which are GC algorithms, and we use those policies for certain spaces, such as non moving, or nursery. It would be strange to have something like NonMovingSpace, which confuses GC algorithms and its actual use.

Besides, the methods in the proposed ChosenNonMovingSpace are just methods that should have been in the Space. I think we could just add methods like prepare, release, end_of_gc, etc, to Space. Some policies may need extra parameters like the defrag stats for Immix, we can invoke a separate method in the ImmixSpace to set the parameter, and make prepare/release/end_of_gc have the same parameters for all the spaces.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PR-extended-testing Run extended tests for the pull request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants