@@ -73,6 +73,8 @@ pub struct ImmixSpaceArgs {
73
73
// Currently only used when "vo_bit" is enabled. Using #[cfg(...)] to eliminate dead code warning.
74
74
#[ cfg( feature = "vo_bit" ) ]
75
75
pub mixed_age : bool ,
76
+ /// Disable copying for this Immix space.
77
+ pub never_move_objects : bool ,
76
78
}
77
79
78
80
unsafe impl < VM : VMBinding > Sync for ImmixSpace < VM > { }
@@ -84,7 +86,7 @@ impl<VM: VMBinding> SFT for ImmixSpace<VM> {
84
86
85
87
fn get_forwarded_object ( & self , object : ObjectReference ) -> Option < ObjectReference > {
86
88
// If we never move objects, look no further.
87
- if super :: NEVER_MOVE_OBJECTS {
89
+ if ! self . is_movable ( ) {
88
90
return None ;
89
91
}
90
92
@@ -102,7 +104,7 @@ impl<VM: VMBinding> SFT for ImmixSpace<VM> {
102
104
}
103
105
104
106
// If we never move objects, look no further.
105
- if super :: NEVER_MOVE_OBJECTS {
107
+ if ! self . is_movable ( ) {
106
108
return false ;
107
109
}
108
110
@@ -122,7 +124,7 @@ impl<VM: VMBinding> SFT for ImmixSpace<VM> {
122
124
VM :: VMObjectModel :: LOCAL_PINNING_BIT_SPEC . is_object_pinned :: < VM > ( object)
123
125
}
124
126
fn is_movable ( & self ) -> bool {
125
- !super :: NEVER_MOVE_OBJECTS
127
+ !self . space_args . never_move_objects
126
128
}
127
129
128
130
#[ cfg( feature = "sanity" ) ]
@@ -276,23 +278,37 @@ impl<VM: VMBinding> ImmixSpace<VM> {
276
278
277
279
pub fn new (
278
280
args : crate :: policy:: space:: PlanCreateSpaceArgs < VM > ,
279
- space_args : ImmixSpaceArgs ,
281
+ mut space_args : ImmixSpaceArgs ,
280
282
) -> 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
-
288
283
if space_args. unlog_object_when_traced {
289
284
assert ! (
290
285
args. constraints. needs_log_bit,
291
286
"Invalid args when the plan does not use log bit"
292
287
) ;
293
288
}
294
289
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
+
296
312
#[ cfg( feature = "vo_bit" ) ]
297
313
vo_bit:: helper:: validate_config :: < VM > ( ) ;
298
314
let vm_map = args. vm_map ;
@@ -356,6 +372,7 @@ impl<VM: VMBinding> ImmixSpace<VM> {
356
372
full_heap_system_gc : bool ,
357
373
) -> bool {
358
374
self . defrag . decide_whether_to_defrag (
375
+ self . is_defrag_enabled ( ) ,
359
376
emergency_collection,
360
377
collect_whole_heap,
361
378
collection_attempts,
@@ -390,7 +407,7 @@ impl<VM: VMBinding> ImmixSpace<VM> {
390
407
}
391
408
392
409
// Prepare defrag info
393
- if super :: DEFRAG {
410
+ if self . is_defrag_enabled ( ) {
394
411
self . defrag . prepare ( self , plan_stats) ;
395
412
}
396
413
@@ -483,7 +500,7 @@ impl<VM: VMBinding> ImmixSpace<VM> {
483
500
/// Return whether this GC was a defrag GC, as a plan may want to know this.
484
501
pub fn end_of_gc ( & mut self ) -> bool {
485
502
let did_defrag = self . defrag . in_defrag ( ) ;
486
- if super :: DEFRAG {
503
+ if self . is_defrag_enabled ( ) {
487
504
self . defrag . reset_in_defrag ( ) ;
488
505
}
489
506
did_defrag
@@ -806,8 +823,8 @@ impl<VM: VMBinding> ImmixSpace<VM> {
806
823
Some ( ( start, end) )
807
824
}
808
825
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 ( ) {
811
828
did_defrag_for_last_gc
812
829
} else {
813
830
// If defrag is disabled, every GC is exhaustive.
@@ -833,6 +850,18 @@ impl<VM: VMBinding> ImmixSpace<VM> {
833
850
self . mark_lines ( object) ;
834
851
}
835
852
}
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
+ }
836
865
}
837
866
838
867
/// A work packet to prepare each block for a major GC.
@@ -867,7 +896,7 @@ impl<VM: VMBinding> GCWork<VM> for PrepareBlockState<VM> {
867
896
continue ;
868
897
}
869
898
// 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 ( ) {
871
900
// Do not set any block as defrag source if defrag is disabled.
872
901
false
873
902
} else if super :: DEFRAG_EVERY_BLOCK {
0 commit comments