@@ -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 . is_defrag_enabled ( ) && ! self . is_nursery_copy_enabled ( )
126
128
}
127
129
128
130
#[ cfg( feature = "sanity" ) ]
@@ -278,12 +280,13 @@ impl<VM: VMBinding> ImmixSpace<VM> {
278
280
args : crate :: policy:: space:: PlanCreateSpaceArgs < VM > ,
279
281
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
- ) ;
283
+ if space_args. never_move_objects {
284
+ info ! (
285
+ "Creating non-moving ImmixSpace: {}. Block size: 2^{}" ,
286
+ args. name,
287
+ Block :: LOG_BYTES
288
+ ) ;
289
+ }
287
290
288
291
if space_args. unlog_object_when_traced {
289
292
assert ! (
@@ -292,7 +295,18 @@ impl<VM: VMBinding> ImmixSpace<VM> {
292
295
) ;
293
296
}
294
297
295
- super :: validate_features ( ) ;
298
+ // validate features
299
+ if super :: BLOCK_ONLY {
300
+ assert ! (
301
+ space_args. never_move_objects,
302
+ "Block-only immix must not move objects"
303
+ ) ;
304
+ }
305
+ assert ! (
306
+ Block :: LINES / 2 <= u8 :: MAX as usize - 2 ,
307
+ "Number of lines in a block should not exceed BlockState::MARK_MARKED"
308
+ ) ;
309
+
296
310
#[ cfg( feature = "vo_bit" ) ]
297
311
vo_bit:: helper:: validate_config :: < VM > ( ) ;
298
312
let vm_map = args. vm_map ;
@@ -355,6 +369,9 @@ impl<VM: VMBinding> ImmixSpace<VM> {
355
369
user_triggered_collection : bool ,
356
370
full_heap_system_gc : bool ,
357
371
) -> bool {
372
+ if !self . is_defrag_enabled ( ) {
373
+ return false ;
374
+ }
358
375
self . defrag . decide_whether_to_defrag (
359
376
emergency_collection,
360
377
collect_whole_heap,
@@ -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
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 . space_args . never_move_objects {
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