Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/binding-tests-openjdk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,6 @@ jobs:
cd mmtk-openjdk
export RUST_BACKTRACE=1
./.github/scripts/${{ inputs.test-script }}
- name: Setup tmate session
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 was used for debugging. I will revert this.

if: ${{ failure() }}
uses: mxschmitt/action-tmate@v3
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ portable-atomic = "1.4.3"
probe = "0.5"
regex = "1.7.0"
rustversion = "1.0"
rayon-core = "=1.12.1" # We can remove this dependency when we use MSRV 1.80+
spin = "0.9.5"
static_assertions = "1.1.0"
strum = "0.27.1"
Expand Down
4 changes: 2 additions & 2 deletions docs/userguide/src/tutorial/code/mygc_semispace/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,9 @@ impl<VM: VMBinding> MyGC<VM> {
let res = MyGC {
hi: AtomicBool::new(false),
// ANCHOR: copyspace_new
copyspace0: CopySpace::new(plan_args.get_space_args("copyspace0", true, false, VMRequest::discontiguous()), false),
copyspace0: CopySpace::new(plan_args.get_normal_space_args("copyspace0", true, false, VMRequest::discontiguous()), false),
// ANCHOR_END: copyspace_new
copyspace1: CopySpace::new(plan_args.get_space_args("copyspace1", true, false, VMRequest::discontiguous()), true),
copyspace1: CopySpace::new(plan_args.get_normal_space_args("copyspace1", true, false, VMRequest::discontiguous()), true),
common: CommonPlan::new(plan_args),
};

Expand Down
2 changes: 1 addition & 1 deletion src/plan/compressor/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ impl<VM: VMBinding> Compressor<VM> {
};

let res = Compressor {
compressor_space: CompressorSpace::new(plan_args.get_space_args(
compressor_space: CompressorSpace::new(plan_args.get_normal_space_args(
"compressor_space",
true,
false,
Expand Down
7 changes: 5 additions & 2 deletions src/plan/generational/copying/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ impl<VM: VMBinding> Plan for GenCopy<VM> {
let full_heap = !self.gen.is_current_gc_nursery();
self.gen.release(tls);
if full_heap {
if VM::VMObjectModel::GLOBAL_LOG_BIT_SPEC.is_on_side() {
self.fromspace().clear_side_log_bits();
}
self.fromspace().release();
}
}
Expand Down Expand Up @@ -209,11 +212,11 @@ impl<VM: VMBinding> GenCopy<VM> {
};

let copyspace0 = CopySpace::new(
plan_args.get_space_args("copyspace0", true, false, VMRequest::discontiguous()),
plan_args.get_mature_space_args("copyspace0", true, false, VMRequest::discontiguous()),
false,
);
let copyspace1 = CopySpace::new(
plan_args.get_space_args("copyspace1", true, false, VMRequest::discontiguous()),
plan_args.get_mature_space_args("copyspace1", true, false, VMRequest::discontiguous()),
true,
);

Expand Down
5 changes: 4 additions & 1 deletion src/plan/generational/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub struct CommonGenPlan<VM: VMBinding> {
impl<VM: VMBinding> CommonGenPlan<VM> {
pub fn new(mut args: CreateSpecificPlanArgs<VM>) -> Self {
let nursery = CopySpace::new(
args.get_space_args("nursery", true, false, VMRequest::discontiguous()),
args.get_nursery_space_args("nursery", true, false, VMRequest::discontiguous()),
true,
);
let full_heap_gc_count = args
Expand Down Expand Up @@ -74,6 +74,9 @@ impl<VM: VMBinding> CommonGenPlan<VM> {
/// Release Gen. This should be called by a single thread in GC release work.
pub fn release(&mut self, tls: VMWorkerThread) {
let full_heap = !self.is_current_gc_nursery();
if VM::VMObjectModel::GLOBAL_LOG_BIT_SPEC.is_on_side() {
self.nursery.clear_side_log_bits();
}
self.common.release(tls, full_heap);
self.nursery.release();
}
Expand Down
13 changes: 9 additions & 4 deletions src/plan/generational/immix/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ impl<VM: VMBinding> Plan for GenImmix<VM> {
let full_heap = !self.gen.is_current_gc_nursery();
self.gen.prepare(tls);
if full_heap {
if VM::VMObjectModel::GLOBAL_LOG_BIT_SPEC.is_on_side() {
self.immix_space.clear_side_log_bits();
}
self.immix_space.prepare(
full_heap,
Some(crate::policy::immix::defrag::StatsForDefrag::new(self)),
Expand Down Expand Up @@ -247,12 +250,14 @@ impl<VM: VMBinding> GenImmix<VM> {
crate::plan::generational::new_generational_global_metadata_specs::<VM>(),
};
let immix_space = ImmixSpace::new(
plan_args.get_space_args("immix_mature", true, false, VMRequest::discontiguous()),
plan_args.get_mature_space_args(
"immix_mature",
true,
false,
VMRequest::discontiguous(),
),
ImmixSpaceArgs {
// We need to unlog objects at tracing time since we currently clear all log bits during a major GC
unlog_object_when_traced: true,
// In GenImmix, young objects are not allocated in ImmixSpace directly.
#[cfg(feature = "vo_bit")]
mixed_age: false,
never_move_objects: false,
},
Expand Down
1 change: 1 addition & 0 deletions src/plan/generational/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub const FULL_NURSERY_GC: bool = false;
pub const GEN_CONSTRAINTS: PlanConstraints = PlanConstraints {
moves_objects: true,
needs_log_bit: ACTIVE_BARRIER.equals(BarrierSelector::ObjectBarrier),
generational: true,
barrier: ACTIVE_BARRIER,
// We may trace duplicate edges in sticky immix (or any plan that uses object remembering barrier). See https://github.com/mmtk/mmtk-core/issues/743.
may_trace_duplicate_edges: ACTIVE_BARRIER.equals(BarrierSelector::ObjectBarrier),
Expand Down
167 changes: 144 additions & 23 deletions src/plan/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,18 +404,22 @@ pub struct CreateSpecificPlanArgs<'a, VM: VMBinding> {

impl<VM: VMBinding> CreateSpecificPlanArgs<'_, VM> {
/// Get a PlanCreateSpaceArgs that can be used to create a space
pub fn get_space_args(
pub fn _get_space_args(
&mut self,
name: &'static str,
zeroed: bool,
permission_exec: bool,
unlog_allocated_object: bool,
unlog_traced_object: bool,
vmrequest: VMRequest,
) -> PlanCreateSpaceArgs<VM> {
PlanCreateSpaceArgs {
name,
zeroed,
permission_exec,
vmrequest,
unlog_allocated_object,
unlog_traced_object,
global_side_metadata_specs: self.global_side_metadata_specs.clone(),
vm_map: self.global_args.vm_map,
mmapper: self.global_args.mmapper,
Expand All @@ -427,39 +431,121 @@ impl<VM: VMBinding> CreateSpecificPlanArgs<'_, VM> {
global_state: self.global_args.state.clone(),
}
}

// The following are some convenience methods for common presets.
// These are not an exhaustive list -- it is just common presets that are used by most plans.

/// Get a preset for a nursery space (where young objects are located).
pub fn get_nursery_space_args(
&mut self,
name: &'static str,
zeroed: bool,
permission_exec: bool,
vmrequest: VMRequest,
) -> PlanCreateSpaceArgs<VM> {
// Objects are allocatd as young, and when traced, they stay young. If they are copied out of the nursery space, they will be moved to a mature space,
// and log bits will be set in that case by the mature space.
self._get_space_args(name, zeroed, permission_exec, false, false, vmrequest)
}

/// Get a preset for a mature space (where mature objects are located).
pub fn get_mature_space_args(
&mut self,
name: &'static str,
zeroed: bool,
permission_exec: bool,
vmrequest: VMRequest,
) -> PlanCreateSpaceArgs<VM> {
// Objects are allocated as mature (pre-tenured), and when traced, they stay mature.
// If an object gets copied into a mature space, the object is also mature,
self._get_space_args(name, zeroed, permission_exec, true, true, vmrequest)
}

// Get a preset for a mixed age space (where both young and mature objects are located).
pub fn get_mixed_age_space_args(
&mut self,
name: &'static str,
zeroed: bool,
permission_exec: bool,
vmrequest: VMRequest,
) -> PlanCreateSpaceArgs<VM> {
// Objects are allocated as young, and when traced, they become mature objects.
self._get_space_args(name, zeroed, permission_exec, false, true, vmrequest)
}

/// Get a preset for spaces in a non-generational plan.
pub fn get_normal_space_args(
&mut self,
name: &'static str,
zeroed: bool,
permission_exec: bool,
vmrequest: VMRequest,
) -> PlanCreateSpaceArgs<VM> {
// Non generational plan: we do not use any of the flags about log bits.
self._get_space_args(name, zeroed, permission_exec, false, false, vmrequest)
}

/// Get a preset for spaces in [`crate::plan::global::CommonPlan`].
/// Spaces like LOS which may include both young and mature objects should not use this method.
pub fn get_common_space_args(
&mut self,
generational: bool,
name: &'static str,
) -> PlanCreateSpaceArgs<VM> {
self.get_base_space_args(
generational,
name,
false, // Common spaces are not executable.
)
}

/// Get a preset for spaces in [`crate::plan::global::BasePlan`].
pub fn get_base_space_args(
&mut self,
generational: bool,
name: &'static str,
permission_exec: bool,
) -> PlanCreateSpaceArgs<VM> {
if generational {
// In generational plans, common/base spaces behave like a mature space:
// * the objects in these spaces are not traced in a nursery GC
// * the log bits for the objects are maintained exactly the same as a mature space.
// Thus we consider them as mature spaces.
self.get_mature_space_args(name, true, permission_exec, VMRequest::discontiguous())
} else {
self.get_normal_space_args(name, true, permission_exec, VMRequest::discontiguous())
}
}
}

impl<VM: VMBinding> BasePlan<VM> {
#[allow(unused_mut)] // 'args' only needs to be mutable for certain features
pub fn new(mut args: CreateSpecificPlanArgs<VM>) -> BasePlan<VM> {
let _generational = args.constraints.generational;
BasePlan {
#[cfg(feature = "code_space")]
code_space: ImmortalSpace::new(args.get_space_args(
code_space: ImmortalSpace::new(args.get_base_space_args(
_generational,
"code_space",
true,
true,
VMRequest::discontiguous(),
)),
#[cfg(feature = "code_space")]
code_lo_space: ImmortalSpace::new(args.get_space_args(
code_lo_space: ImmortalSpace::new(args.get_base_space_args(
_generational,
"code_lo_space",
true,
true,
VMRequest::discontiguous(),
)),
#[cfg(feature = "ro_space")]
ro_space: ImmortalSpace::new(args.get_space_args(
ro_space: ImmortalSpace::new(args.get_base_space_args(
_generational,
"ro_space",
true,
false,
VMRequest::discontiguous(),
)),
#[cfg(feature = "vm_space")]
vm_space: VMSpace::new(args.get_space_args(
vm_space: VMSpace::new(args.get_base_space_args(
_generational,
"vm_space",
false,
false, // it doesn't matter -- we are not mmapping for VM space.
VMRequest::discontiguous(),
)),

global_state: args.global_args.state.clone(),
Expand Down Expand Up @@ -517,6 +603,28 @@ impl<VM: VMBinding> BasePlan<VM> {
self.vm_space.release();
}

pub fn clear_side_log_bits(&self) {
#[cfg(feature = "code_space")]
self.code_space.clear_side_log_bits();
#[cfg(feature = "code_space")]
self.code_lo_space.clear_side_log_bits();
#[cfg(feature = "ro_space")]
self.ro_space.clear_side_log_bits();
#[cfg(feature = "vm_space")]
self.vm_space.clear_side_log_bits();
}

pub fn set_side_log_bits(&self) {
#[cfg(feature = "code_space")]
self.code_space.set_side_log_bits();
#[cfg(feature = "code_space")]
self.code_lo_space.set_side_log_bits();
#[cfg(feature = "ro_space")]
self.ro_space.set_side_log_bits();
#[cfg(feature = "vm_space")]
self.vm_space.set_side_log_bits();
}

pub fn end_of_gc(&mut self, _tls: VMWorkerThread) {
// Do nothing here. None of the spaces needs end_of_gc.
}
Expand Down Expand Up @@ -584,16 +692,19 @@ pub struct CommonPlan<VM: VMBinding> {

impl<VM: VMBinding> CommonPlan<VM> {
pub fn new(mut args: CreateSpecificPlanArgs<VM>) -> CommonPlan<VM> {
let needs_log_bit = args.constraints.needs_log_bit;
let generational = args.constraints.generational;
CommonPlan {
immortal: ImmortalSpace::new(args.get_space_args(
"immortal",
true,
false,
VMRequest::discontiguous(),
)),
immortal: ImmortalSpace::new(args.get_common_space_args(generational, "immortal")),
los: LargeObjectSpace::new(
args.get_space_args("los", true, false, VMRequest::discontiguous()),
// LOS is a bit special, as it is a mixed age space. It has a logical nursery.
if generational {
args.get_mixed_age_space_args("los", true, false, VMRequest::discontiguous())
} else {
args.get_normal_space_args("los", true, false, VMRequest::discontiguous())
},
false,
needs_log_bit,
),
nonmoving: Self::new_nonmoving_space(&mut args),
base: BasePlan::new(args),
Expand Down Expand Up @@ -621,6 +732,18 @@ impl<VM: VMBinding> CommonPlan<VM> {
self.base.release(tls, full_heap)
}

pub fn clear_side_log_bits(&self) {
self.immortal.clear_side_log_bits();
self.los.clear_side_log_bits();
self.base.clear_side_log_bits();
}

pub fn set_side_log_bits(&self) {
self.immortal.set_side_log_bits();
self.los.set_side_log_bits();
self.base.set_side_log_bits();
}

pub fn end_of_gc(&mut self, tls: VMWorkerThread) {
self.end_of_gc_nonmoving_space();
self.base.end_of_gc(tls);
Expand All @@ -639,7 +762,7 @@ impl<VM: VMBinding> CommonPlan<VM> {
}

fn new_nonmoving_space(args: &mut CreateSpecificPlanArgs<VM>) -> NonMovingSpace<VM> {
let space_args = args.get_space_args("nonmoving", true, false, VMRequest::discontiguous());
let space_args = args.get_common_space_args(args.constraints.generational, "nonmoving");
cfg_if::cfg_if! {
if #[cfg(any(feature = "immortal_as_nonmoving", feature = "marksweep_as_nonmoving"))] {
NonMovingSpace::new(space_args)
Expand All @@ -648,8 +771,6 @@ impl<VM: VMBinding> CommonPlan<VM> {
NonMovingSpace::new(
space_args,
crate::policy::immix::ImmixSpaceArgs {
unlog_object_when_traced: false,
#[cfg(feature = "vo_bit")]
mixed_age: false,
never_move_objects: true,
},
Expand Down
18 changes: 15 additions & 3 deletions src/plan/immix/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,6 @@ impl<VM: VMBinding> Immix<VM> {
Self::new_with_args(
plan_args,
ImmixSpaceArgs {
unlog_object_when_traced: false,
#[cfg(feature = "vo_bit")]
mixed_age: false,
never_move_objects: false,
},
Expand All @@ -152,7 +150,21 @@ impl<VM: VMBinding> Immix<VM> {
) -> Self {
let immix = Immix {
immix_space: ImmixSpace::new(
plan_args.get_space_args("immix", true, false, VMRequest::discontiguous()),
if space_args.mixed_age {
plan_args.get_mixed_age_space_args(
"immix",
true,
false,
VMRequest::discontiguous(),
)
} else {
plan_args.get_normal_space_args(
"immix",
true,
false,
VMRequest::discontiguous(),
)
},
space_args,
),
common: CommonPlan::new(plan_args),
Expand Down
Loading
Loading