-
Notifications
You must be signed in to change notification settings - Fork 77
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
base: master
Are you sure you want to change the base?
Conversation
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
binding-refs |
654ec4d
to
0763fb7
Compare
# 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 = [] |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can do something like this: https://doc.rust-lang.org/cargo/reference/features.html#mutually-exclusive-features
There was a problem hiding this comment.
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.
There was a problem hiding this 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.
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.
OK. I have pushed more changes to @qinsoon You can merge it into your I am also trying to further remove the cfg in |
#[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>; |
There was a problem hiding this comment.
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"))
.
There was a problem hiding this comment.
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> { |
There was a problem hiding this comment.
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.
} else { | ||
panic!("No policy selected for nonmoving space") |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
I considered introducing a Besides, the methods in the proposed |
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).common_prepare_func
andcommon_release_func
for mutators.