@@ -73,6 +73,8 @@ pub struct ImmixSpaceArgs {
7373 // Currently only used when "vo_bit" is enabled. Using #[cfg(...)] to eliminate dead code warning.
7474 #[ cfg( feature = "vo_bit" ) ]
7575 pub mixed_age : bool ,
76+ /// Disable copying for this Immix space.
77+ pub never_move_objects : bool ,
7678}
7779
7880unsafe impl < VM : VMBinding > Sync for ImmixSpace < VM > { }
@@ -84,7 +86,7 @@ impl<VM: VMBinding> SFT for ImmixSpace<VM> {
8486
8587 fn get_forwarded_object ( & self , object : ObjectReference ) -> Option < ObjectReference > {
8688 // If we never move objects, look no further.
87- if super :: NEVER_MOVE_OBJECTS {
89+ if ! self . is_movable ( ) {
8890 return None ;
8991 }
9092
@@ -102,7 +104,7 @@ impl<VM: VMBinding> SFT for ImmixSpace<VM> {
102104 }
103105
104106 // If we never move objects, look no further.
105- if super :: NEVER_MOVE_OBJECTS {
107+ if ! self . is_movable ( ) {
106108 return false ;
107109 }
108110
@@ -122,7 +124,7 @@ impl<VM: VMBinding> SFT for ImmixSpace<VM> {
122124 VM :: VMObjectModel :: LOCAL_PINNING_BIT_SPEC . is_object_pinned :: < VM > ( object)
123125 }
124126 fn is_movable ( & self ) -> bool {
125- !super :: NEVER_MOVE_OBJECTS
127+ !self . space_args . never_move_objects
126128 }
127129
128130 #[ cfg( feature = "sanity" ) ]
@@ -276,23 +278,37 @@ impl<VM: VMBinding> ImmixSpace<VM> {
276278
277279 pub fn new (
278280 args : crate :: policy:: space:: PlanCreateSpaceArgs < VM > ,
279- space_args : ImmixSpaceArgs ,
281+ mut space_args : ImmixSpaceArgs ,
280282 ) -> Self {
281- #[ cfg( feature = "immix_non_moving" ) ]
282- info ! (
283- "Creating non-moving ImmixSpace: {}. Block size: 2^{}" ,
284- args. name,
285- Block :: LOG_BYTES
286- ) ;
287-
288283 if space_args. unlog_object_when_traced {
289284 assert ! (
290285 args. constraints. needs_log_bit,
291286 "Invalid args when the plan does not use log bit"
292287 ) ;
293288 }
294289
295- super :: validate_features ( ) ;
290+ // Make sure we override the space args if we force non moving Immix
291+ if cfg ! ( feature = "immix_non_moving" ) && !space_args. never_move_objects {
292+ info ! (
293+ "Overriding never_moves_objects for Immix Space {}, as the immix_non_moving feature is set. Block size: 2^{}" ,
294+ args. name,
295+ Block :: LOG_BYTES ,
296+ ) ;
297+ space_args. never_move_objects = true ;
298+ }
299+
300+ // validate features
301+ if super :: BLOCK_ONLY {
302+ assert ! (
303+ space_args. never_move_objects,
304+ "Block-only immix must not move objects"
305+ ) ;
306+ }
307+ assert ! (
308+ Block :: LINES / 2 <= u8 :: MAX as usize - 2 ,
309+ "Number of lines in a block should not exceed BlockState::MARK_MARKED"
310+ ) ;
311+
296312 #[ cfg( feature = "vo_bit" ) ]
297313 vo_bit:: helper:: validate_config :: < VM > ( ) ;
298314 let vm_map = args. vm_map ;
@@ -356,6 +372,7 @@ impl<VM: VMBinding> ImmixSpace<VM> {
356372 full_heap_system_gc : bool ,
357373 ) -> bool {
358374 self . defrag . decide_whether_to_defrag (
375+ self . is_defrag_enabled ( ) ,
359376 emergency_collection,
360377 collect_whole_heap,
361378 collection_attempts,
@@ -390,7 +407,7 @@ impl<VM: VMBinding> ImmixSpace<VM> {
390407 }
391408
392409 // Prepare defrag info
393- if super :: DEFRAG {
410+ if self . is_defrag_enabled ( ) {
394411 self . defrag . prepare ( self , plan_stats) ;
395412 }
396413
@@ -483,7 +500,7 @@ impl<VM: VMBinding> ImmixSpace<VM> {
483500 /// Return whether this GC was a defrag GC, as a plan may want to know this.
484501 pub fn end_of_gc ( & mut self ) -> bool {
485502 let did_defrag = self . defrag . in_defrag ( ) ;
486- if super :: DEFRAG {
503+ if self . is_defrag_enabled ( ) {
487504 self . defrag . reset_in_defrag ( ) ;
488505 }
489506 did_defrag
@@ -806,8 +823,8 @@ impl<VM: VMBinding> ImmixSpace<VM> {
806823 Some ( ( start, end) )
807824 }
808825
809- pub fn is_last_gc_exhaustive ( did_defrag_for_last_gc : bool ) -> bool {
810- if super :: DEFRAG {
826+ pub fn is_last_gc_exhaustive ( & self , did_defrag_for_last_gc : bool ) -> bool {
827+ if self . is_defrag_enabled ( ) {
811828 did_defrag_for_last_gc
812829 } else {
813830 // If defrag is disabled, every GC is exhaustive.
@@ -833,6 +850,18 @@ impl<VM: VMBinding> ImmixSpace<VM> {
833850 self . mark_lines ( object) ;
834851 }
835852 }
853+
854+ pub ( crate ) fn prefer_copy_on_nursery_gc ( & self ) -> bool {
855+ self . is_nursery_copy_enabled ( )
856+ }
857+
858+ pub ( crate ) fn is_nursery_copy_enabled ( & self ) -> bool {
859+ !self . space_args . never_move_objects && !cfg ! ( feature = "sticky_immix_non_moving_nursery" )
860+ }
861+
862+ pub ( crate ) fn is_defrag_enabled ( & self ) -> bool {
863+ !self . space_args . never_move_objects
864+ }
836865}
837866
838867/// A work packet to prepare each block for a major GC.
@@ -867,7 +896,7 @@ impl<VM: VMBinding> GCWork<VM> for PrepareBlockState<VM> {
867896 continue ;
868897 }
869898 // Check if this block needs to be defragmented.
870- let is_defrag_source = if !super :: DEFRAG {
899+ let is_defrag_source = if !self . space . is_defrag_enabled ( ) {
871900 // Do not set any block as defrag source if defrag is disabled.
872901 false
873902 } else if super :: DEFRAG_EVERY_BLOCK {
0 commit comments