Include the currently active GC in RUBY_DESCRIPTION

This will add +MOD_GC to the version string and Ruby description when
Ruby is compiled with shared gc support.

When shared GC support is compiled in and a GC module has been loaded
using RUBY_GC_LIBRARY, the version string will include the name of
the currently active GC as reported by the rb_gc_active_gc_name function
in the form

+MOD_GC[gc_name]

[Feature #20794]
This commit is contained in:
Matt Valentine-House 2024-10-08 21:30:06 +01:00
Родитель fa10441981
Коммит ee290c94a3
7 изменённых файлов: 61 добавлений и 4 удалений

Просмотреть файл

@ -19555,6 +19555,7 @@ version.$(OBJEXT): $(CCAN_DIR)/str/str.h
version.$(OBJEXT): $(hdrdir)/ruby.h
version.$(OBJEXT): $(hdrdir)/ruby/ruby.h
version.$(OBJEXT): $(hdrdir)/ruby/version.h
version.$(OBJEXT): $(top_srcdir)/gc/gc.h
version.$(OBJEXT): $(top_srcdir)/internal/array.h
version.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
version.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h

21
gc.c
Просмотреть файл

@ -562,6 +562,8 @@ rb_gc_guarded_ptr_val(volatile VALUE *ptr, VALUE val)
static const char *obj_type_name(VALUE obj);
#define RB_AMALGAMATED_DEFAULT_GC
#include "gc/default.c"
static int external_gc_loaded = FALSE;
#if USE_SHARED_GC && !defined(HAVE_DLOPEN)
# error "Shared GC requires dlopen"
@ -696,6 +698,7 @@ ruby_external_gc_init(void)
fprintf(stderr, "ruby_external_gc_init: Shared library %s cannot be opened: %s\n", gc_so_path, dlerror());
exit(1);
}
external_gc_loaded = TRUE;
}
rb_gc_function_map_t gc_functions;
@ -2767,10 +2770,26 @@ rb_gc_copy_attributes(VALUE dest, VALUE obj)
rb_gc_impl_copy_attributes(rb_gc_get_objspace(), dest, obj);
}
int
rb_gc_external_gc_loaded_p(void) {
return external_gc_loaded;
}
const char *
rb_gc_active_gc_name(void)
{
return rb_gc_impl_active_gc_name();
const char *gc_name = rb_gc_impl_active_gc_name();
if (strlen(gc_name) > RB_GC_MAX_NAME_LEN) {
char *truncated_gc_name = ruby_xmalloc(RB_GC_MAX_NAME_LEN + 1);
rb_warn("GC module %s has a name larger than %d chars, it will be truncated\n",
gc_name, RB_GC_MAX_NAME_LEN);
strncpy(truncated_gc_name, gc_name, RB_GC_MAX_NAME_LEN);
return (const char *)truncated_gc_name;
}
return gc_name;
}
// TODO: rearchitect this function to work for a generic GC

Просмотреть файл

@ -234,6 +234,7 @@ size_t rb_gc_obj_slot_size(VALUE obj);
VALUE rb_gc_disable_no_rest(void);
#define RB_GC_MAX_NAME_LEN 20
/* gc.c (export) */
const char *rb_objspace_data_type_name(VALUE obj);
@ -248,6 +249,9 @@ void *ruby_sized_xrealloc(void *ptr, size_t new_size, size_t old_size) RUBY_ATTR
void *ruby_sized_xrealloc2(void *ptr, size_t new_count, size_t element_size, size_t old_count) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2, 3));
void ruby_sized_xfree(void *x, size_t size);
const char * rb_gc_active_gc_name(void);
int rb_gc_external_gc_loaded_p(void);
#if USE_SHARED_GC
void ruby_load_external_gc_from_argv(int argc, char **argv);
#endif

Просмотреть файл

@ -9,6 +9,7 @@ describe "The -v command line option" do
ruby_exe(nil, args: '-v').sub("+PRISM ", "").should include(RUBY_DESCRIPTION.sub("+PRISM ", ""))
end unless (defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?) ||
(defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?) ||
(ENV['RUBY_GC_LIBRARY'] && ENV['RUBY_GC_LIBRARY'].length > 0) ||
(ENV['RUBY_MN_THREADS'] == '1')
end
end

Просмотреть файл

@ -25,12 +25,12 @@ describe "Processing RUBYOPT" do
guard -> { RbConfig::CONFIG["CROSS_COMPILING"] != "yes" } do
it "prints the version number for '-v'" do
ENV["RUBYOPT"] = '-v'
ruby_exe("").sub("+PRISM ", "")[/\A.*/].should == RUBY_DESCRIPTION.sub("+PRISM ", "")
ruby_exe("").sub("+PRISM ", "").sub(/\+GC(\[\w+\]\s|\s)?/, "")[/\A.*/].should == RUBY_DESCRIPTION.sub("+PRISM ", "").sub(/\+GC(\[\w+\]\s|\s)?/, "")
end
it "ignores whitespace around the option" do
ENV["RUBYOPT"] = ' -v '
ruby_exe("").sub("+PRISM ", "")[/\A.*/].should == RUBY_DESCRIPTION.sub("+PRISM ", "")
ruby_exe("").sub("+PRISM ", "").sub(/\+GC(\[\w+\]\s|\s)?/, "")[/\A.*/].should == RUBY_DESCRIPTION.sub("+PRISM ", "").sub(/\+GC(\[\w+\]\s|\s)?/, "")
end
end

Просмотреть файл

@ -176,7 +176,7 @@ class TestRubyOptions < Test::Unit::TestCase
VERSION_PATTERN_WITH_RJIT =
case RUBY_ENGINE
when 'ruby'
/^ruby #{q[RUBY_VERSION]}(?:[p ]|dev|rc).*? \+RJIT (\+MN )?(\+PRISM )?\[#{q[RUBY_PLATFORM]}\]$/
/^ruby #{q[RUBY_VERSION]}(?:[p ]|dev|rc).*? \+RJIT (\+MN )?(\+PRISM )?(\+GC)?(\[\w+\]\s|\s)?\[#{q[RUBY_PLATFORM]}\]$/
else
VERSION_PATTERN
end
@ -307,6 +307,16 @@ class TestRubyOptions < Test::Unit::TestCase
end
end
def test_enabled_gc
omit unless /linux|darwin/ =~ RUBY_PLATFORM
if RbConfig::CONFIG['shared_gc_dir'].length > 0
assert_match(/\+GC/, RUBY_DESCRIPTION)
else
assert_no_match(/\+GC/, RUBY_DESCRIPTION)
end
end
def test_parser_flag
assert_in_out_err(%w(--parser=prism -e) + ["puts :hi"], "", %w(hi), [])
assert_in_out_err(%w(--parser=prism --dump=parsetree -e _=:hi), "", /"hi"/, [])

Просмотреть файл

@ -11,6 +11,7 @@
#include "internal/cmdlineopt.h"
#include "internal/parse.h"
#include "internal/gc.h"
#include "ruby/ruby.h"
#include "version.h"
#include "vm_core.h"
@ -61,6 +62,11 @@ const int ruby_api_version[] = {
#else
#define YJIT_DESCRIPTION " +YJIT"
#endif
#if USE_SHARED_GC
#define GC_DESCRIPTION " +GC"
#else
#define GC_DESCRIPTION ""
#endif
const char ruby_version[] = RUBY_VERSION;
const char ruby_revision[] = RUBY_FULL_REVISION;
const char ruby_release_date[] = RUBY_RELEASE_DATE;
@ -167,6 +173,14 @@ define_ruby_description(const char *const jit_opt)
+ rb_strlen_lit(YJIT_DESCRIPTION)
+ rb_strlen_lit(" +MN")
+ rb_strlen_lit(" +PRISM")
#if USE_SHARED_GC
+ rb_strlen_lit(GC_DESCRIPTION)
// Assume the active GC name can not be longer than 20 chars
// so that we don't have to use strlen and remove the static
// qualifier from desc.
+ RB_GC_MAX_NAME_LEN + 3
#endif
];
int n = ruby_description_opt_point;
@ -176,6 +190,14 @@ define_ruby_description(const char *const jit_opt)
RUBY_ASSERT(n <= ruby_description_opt_point + (int)rb_strlen_lit(YJIT_DESCRIPTION));
if (ruby_mn_threads_enabled) append(" +MN");
if (rb_ruby_prism_p()) append(" +PRISM");
#if USE_SHARED_GC
append(GC_DESCRIPTION);
if (rb_gc_external_gc_loaded_p()) {
append("[");
append(rb_gc_active_gc_name());
append("]");
}
#endif
append(ruby_description + ruby_description_opt_point);
# undef append