From ea613c63608232bf33fd454fc6cd1ce20d63d82e Mon Sep 17 00:00:00 2001 From: Mirek Klimos Date: Sat, 10 Dec 2022 10:35:31 -0800 Subject: [PATCH] Expose need_major_gc via GC.latest_gc_info (#6791) --- gc.c | 19 +++++++++++++++++-- test/ruby/test_gc.rb | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/gc.c b/gc.c index 4254922f78..b9e9a9d147 100644 --- a/gc.c +++ b/gc.c @@ -10954,7 +10954,7 @@ gc_count(rb_execution_context_t *ec, VALUE self) static VALUE gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const unsigned int orig_flags) { - static VALUE sym_major_by = Qnil, sym_gc_by, sym_immediate_sweep, sym_have_finalizer, sym_state; + static VALUE sym_major_by = Qnil, sym_gc_by, sym_immediate_sweep, sym_have_finalizer, sym_state, sym_need_major_by; static VALUE sym_nofree, sym_oldgen, sym_shady, sym_force, sym_stress; #if RGENGC_ESTIMATE_OLDMALLOC static VALUE sym_oldmalloc; @@ -10962,7 +10962,7 @@ gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const unsigned static VALUE sym_newobj, sym_malloc, sym_method, sym_capi; static VALUE sym_none, sym_marking, sym_sweeping; VALUE hash = Qnil, key = Qnil; - VALUE major_by; + VALUE major_by, need_major_by; unsigned int flags = orig_flags ? orig_flags : objspace->profile.latest_gc_info; if (SYMBOL_P(hash_or_key)) { @@ -10982,6 +10982,7 @@ gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const unsigned S(immediate_sweep); S(have_finalizer); S(state); + S(need_major_by); S(stress); S(nofree); @@ -11019,6 +11020,20 @@ gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const unsigned Qnil; SET(major_by, major_by); + if (orig_flags == 0) { /* set need_major_by only if flags not set explicitly */ + unsigned int need_major_flags = objspace->rgengc.need_major_gc; + need_major_by = + (need_major_flags & GPR_FLAG_MAJOR_BY_NOFREE) ? sym_nofree : + (need_major_flags & GPR_FLAG_MAJOR_BY_OLDGEN) ? sym_oldgen : + (need_major_flags & GPR_FLAG_MAJOR_BY_SHADY) ? sym_shady : + (need_major_flags & GPR_FLAG_MAJOR_BY_FORCE) ? sym_force : +#if RGENGC_ESTIMATE_OLDMALLOC + (need_major_flags & GPR_FLAG_MAJOR_BY_OLDMALLOC) ? sym_oldmalloc : +#endif + Qnil; + SET(need_major_by, need_major_by); + } + SET(gc_by, (flags & GPR_FLAG_NEWOBJ) ? sym_newobj : (flags & GPR_FLAG_MALLOC) ? sym_malloc : diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb index e22d6436d4..937f303604 100644 --- a/test/ruby/test_gc.rb +++ b/test/ruby/test_gc.rb @@ -229,6 +229,7 @@ class TestGc < Test::Unit::TestCase assert_equal :force, h[:major_by] if use_rgengc? assert_equal :method, h[:gc_by] assert_equal true, h[:immediate_sweep] + assert_equal true, h.key?(:need_major_by) GC.stress = true assert_equal :force, GC.latest_gc_info[:major_by] @@ -246,6 +247,25 @@ class TestGc < Test::Unit::TestCase assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) {GC.latest_gc_info(:"\u{30eb 30d3 30fc}")} end + def test_latest_gc_info_need_major_by + return unless use_rgengc? + omit 'stress' if GC.stress + + 3.times { GC.start } + assert_nil GC.latest_gc_info(:need_major_by) + + # allocate objects until need_major_by is set or major GC happens + major_count = GC.stat(:major_gc_count) + objects = [] + while GC.stat(:major_gc_count) == major_count && GC.latest_gc_info(:need_major_by).nil? + objects.append(100.times.map { '*' }) + end + + assert_not_nil GC.latest_gc_info(:need_major_by) + GC.start(full_mark: false) # should be upgraded to major + assert_not_nil GC.latest_gc_info(:major_by) + end + def test_stress_compile_send assert_in_out_err(%w[--disable-gems], <<-EOS, [], [], "") GC.stress = true