diff --git a/gc/mmtk/mmtk.c b/gc/mmtk/mmtk.c index 9b09116..1dacd95 100644 --- a/gc/mmtk/mmtk.c +++ b/gc/mmtk/mmtk.c @@ -21,6 +21,7 @@ struct objspace { bool gc_stress; size_t gc_count; + size_t moving_gc_count; size_t total_gc_time; size_t total_allocated_objects; @@ -132,7 +133,7 @@ rb_mmtk_stop_the_world(void) } static void -rb_mmtk_resume_mutators(void) +rb_mmtk_resume_mutators(bool current_gc_may_move) { struct objspace *objspace = rb_gc_get_objspace(); @@ -143,6 +144,7 @@ rb_mmtk_resume_mutators(void) objspace->world_stopped = false; objspace->gc_count++; + if (current_gc_may_move) objspace->moving_gc_count++; pthread_cond_broadcast(&objspace->cond_world_started); if ((err = pthread_mutex_unlock(&objspace->mutex)) != 0) { @@ -492,7 +494,7 @@ rb_mmtk_gc_thread_bug(const char *msg, ...) rb_gc_print_backtrace(); fprintf(stderr, "\n"); - rb_mmtk_resume_mutators(); + rb_mmtk_resume_mutators(false); sleep(5); @@ -1459,6 +1461,7 @@ rb_gc_impl_latest_gc_info(void *objspace_ptr, VALUE hash_or_key) enum gc_stat_sym { gc_stat_sym_count, + gc_stat_sym_moving_gc_count, gc_stat_sym_time, gc_stat_sym_total_allocated_objects, gc_stat_sym_total_bytes, @@ -1478,6 +1481,7 @@ setup_gc_stat_symbols(void) if (gc_stat_symbols[0] == 0) { #define S(s) gc_stat_symbols[gc_stat_sym_##s] = ID2SYM(rb_intern_const(#s)) S(count); + S(moving_gc_count); S(time); S(total_allocated_objects); S(total_bytes); @@ -1514,6 +1518,7 @@ rb_gc_impl_stat(void *objspace_ptr, VALUE hash_or_sym) rb_hash_aset(hash, gc_stat_symbols[gc_stat_sym_##name], SIZET2NUM(attr)); SET(count, objspace->gc_count); + SET(moving_gc_count, objspace->moving_gc_count); SET(time, objspace->total_gc_time / (1000 * 1000)); SET(total_allocated_objects, objspace->total_allocated_objects); SET(total_bytes, mmtk_total_bytes()); diff --git a/gc/mmtk/mmtk.h b/gc/mmtk/mmtk.h index 20d2684..ee338c8 100644 --- a/gc/mmtk/mmtk.h +++ b/gc/mmtk/mmtk.h @@ -60,7 +60,7 @@ typedef struct MMTk_RubyUpcalls { void (*init_gc_worker_thread)(struct MMTk_GCThreadTLS *gc_worker_tls); bool (*is_mutator)(void); void (*stop_the_world)(void); - void (*resume_mutators)(void); + void (*resume_mutators)(bool gc_may_move); void (*block_for_gc)(MMTk_VMMutatorThread tls); void (*before_updating_jit_code)(void); void (*after_updating_jit_code)(void); diff --git a/gc/mmtk/src/abi.rs b/gc/mmtk/src/abi.rs index 2a0e911..c880302 100644 --- a/gc/mmtk/src/abi.rs +++ b/gc/mmtk/src/abi.rs @@ -301,7 +301,7 @@ pub struct RubyUpcalls { pub init_gc_worker_thread: extern "C" fn(gc_worker_tls: *mut GCThreadTLS), pub is_mutator: extern "C" fn() -> bool, pub stop_the_world: extern "C" fn(), - pub resume_mutators: extern "C" fn(), + pub resume_mutators: extern "C" fn(gc_may_move: bool), pub block_for_gc: extern "C" fn(tls: VMMutatorThread), pub before_updating_jit_code: extern "C" fn(), pub after_updating_jit_code: extern "C" fn(), diff --git a/gc/mmtk/src/collection.rs b/gc/mmtk/src/collection.rs index 83d046a..28daa4f 100644 --- a/gc/mmtk/src/collection.rs +++ b/gc/mmtk/src/collection.rs @@ -48,11 +48,13 @@ impl Collection for VMCollection { } fn resume_mutators(_tls: VMWorkerThread) { - if CURRENT_GC_MAY_MOVE.load(Ordering::Relaxed) { + let current_gc_may_move = CURRENT_GC_MAY_MOVE.load(Ordering::Relaxed); + + if current_gc_may_move { (upcalls().after_updating_jit_code)(); } - (upcalls().resume_mutators)(); + (upcalls().resume_mutators)(current_gc_may_move); } fn block_for_gc(tls: VMMutatorThread) { diff --git a/test/mmtk/test_stat.rb b/test/mmtk/test_stat.rb index 03dca20..6962d39 100644 --- a/test/mmtk/test_stat.rb +++ b/test/mmtk/test_stat.rb @@ -4,6 +4,21 @@ module MMTk class TestStat < TestCase + def test_moving_gc_count + assert_separately([{ "MMTK_PLAN" => "Immix" }], <<~RUBY) + before = nil + after = nil + + before = GC.stat(:moving_gc_count) + + 2.times { GC.start } + + after = GC.stat(:moving_gc_count) + + assert_operator(before, :<, after) + RUBY + end + def test_weak_references_count assert_operator(GC.stat(:weak_references_count), :>, 0)