Define compaction methods as rb_f_notimplement on unsupported platforms.

The patch implements the methods as rb_f_notimplement.
To test for compaction users can now use `GC.respond_to?(:compact)`.

The upstream patch relies on the macro `GC_COMPACTION_SUPPORTED`
that is defined when the `__wasi__` is false. The define is defined by
an arch conditional in the specfile, which is not optimal but works in our case.
663833b08f
https://bugs.ruby-lang.org/issues/18829

This also requires regenerating the gc.rbinc and miniprelude.c
since the patch touches gc.rb. This patch is available in
ruby-3.2.0-define-unsupported-gc-compaction-methods_generated-files.patch.

To regenerate the gc.rbinc and miniprelude.c files patch:
~~~
tar -Jxvf ./ruby-3.1.2.tar.xz
git clone https://github.com/ruby/ruby.git
cd ruby && git checkout v3_1_2
patch -p1 < ../ruby-3.2.0-define-unsupported-gc-compaction-methods-as-rb_f_notimplement.patch
./autogen.sh && ./configure
make gc.rbinc miniprelude.c
cd ..
diff -u {ruby-3.1.2,ruby}/gc.rbinc > ruby-3.2.0-define-unsupported-gc-compaction-methods_generated-files.patch
diff -u {ruby-3.1.2,ruby}/miniprelude.c >> ruby-3.2.0-define-unsupported-gc-compaction-methods_generated-files.patch
~~~

Uptream bug: https://bugs.ruby-lang.org/issues/18779
Upstream PR: https://github.com/ruby/ruby/pull/5934
This commit is contained in:
Jarek Prokop 2022-05-26 12:37:01 +02:00
parent 2c91b113bb
commit b7b5473796
3 changed files with 932 additions and 1 deletions

View File

@ -0,0 +1,402 @@
commit 6d1ca6737f31b2e24664a093f1827dd74a121a9f
Author: Jarek Prokop <jprokop@redhat.com>
Date: Thu May 26 11:28:13 2022 +0200
Gc ppc64le fix
diff --git a/gc.c b/gc.c
index ef9327df1f..1c35856c44 100644
--- a/gc.c
+++ b/gc.c
@@ -9421,6 +9421,7 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, size_t slot_size)
return (VALUE)src;
}
+#if GC_COMPACTION_SUPPORTED
static int
compare_free_slots(const void *left, const void *right, void *dummy)
{
@@ -9468,6 +9469,7 @@ gc_sort_heap_by_empty_slots(rb_objspace_t *objspace)
free(page_list);
}
}
+#endif
static void
gc_ref_update_array(rb_objspace_t * objspace, VALUE v)
@@ -10147,8 +10149,21 @@ gc_update_references(rb_objspace_t *objspace)
gc_update_table_refs(objspace, finalizer_table);
}
+#if GC_COMPACTION_SUPPORTED
+/*
+ * call-seq:
+ * GC.latest_compact_info -> {:considered=>{:T_CLASS=>11}, :moved=>{:T_CLASS=>11}}
+ *
+ * Returns information about object moved in the most recent GC compaction.
+ *
+ * The returned hash has two keys :considered and :moved. The hash for
+ * :considered lists the number of objects that were considered for movement
+ * by the compactor, and the :moved hash lists the number of objects that
+ * were actually moved. Some objects can't be moved (maybe they were pinned)
+ * so these numbers can be used to calculate compaction efficiency.
+ */
static VALUE
-gc_compact_stats(rb_execution_context_t *ec, VALUE self)
+gc_compact_stats(VALUE self)
{
size_t i;
rb_objspace_t *objspace = &rb_objspace;
@@ -10171,7 +10186,11 @@ gc_compact_stats(rb_execution_context_t *ec, VALUE self)
return h;
}
+#else
+# define gc_compact_stats rb_f_notimplement
+#endif
+#if GC_COMPACTION_SUPPORTED
static void
root_obj_check_moved_i(const char *category, VALUE obj, void *data)
{
@@ -10221,22 +10240,78 @@ heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data)
return 0;
}
+/*
+ * call-seq:
+ * GC.compact
+ *
+ * This function compacts objects together in Ruby's heap. It eliminates
+ * unused space (or fragmentation) in the heap by moving objects in to that
+ * unused space. This function returns a hash which contains statistics about
+ * which objects were moved. See `GC.latest_gc_info` for details about
+ * compaction statistics.
+ *
+ * This method is implementation specific and not expected to be implemented
+ * in any implementation besides MRI.
+ *
+ * To test whether GC compaction is supported, use the idiom:
+ *
+ * GC.respond_to?(:compact)
+ */
static VALUE
-gc_compact(rb_execution_context_t *ec, VALUE self)
+gc_compact(VALUE self)
{
/* Run GC with compaction enabled */
- gc_start_internal(ec, self, Qtrue, Qtrue, Qtrue, Qtrue);
+ gc_start_internal(NULL, self, Qtrue, Qtrue, Qtrue, Qtrue);
- return gc_compact_stats(ec, self);
+ return gc_compact_stats(self);
}
+#else
+# define gc_compact rb_f_notimplement
+#endif
+#if GC_COMPACTION_SUPPORTED
+/*
+ * call-seq:
+ * GC.verify_compaction_references(toward: nil, double_heap: false) -> hash
+ *
+ * Verify compaction reference consistency.
+ *
+ * This method is implementation specific. During compaction, objects that
+ * were moved are replaced with T_MOVED objects. No object should have a
+ * reference to a T_MOVED object after compaction.
+ *
+ * This function doubles the heap to ensure room to move all objects,
+ * compacts the heap to make sure everything moves, updates all references,
+ * then performs a full GC. If any object contains a reference to a T_MOVED
+ * object, that object should be pushed on the mark stack, and will
+ * make a SEGV.
+ */
static VALUE
-gc_verify_compaction_references(rb_execution_context_t *ec, VALUE self, VALUE double_heap, VALUE toward_empty)
+gc_verify_compaction_references(int argc, VALUE *argv, VALUE self)
{
rb_objspace_t *objspace = &rb_objspace;
+ VALUE kwargs, double_heap = Qfalse, toward_empty = Qfalse;
+ static ID id_toward, id_double_heap, id_empty;
+
+ if (!id_toward) {
+ id_toward = rb_intern("toward");
+ id_double_heap = rb_intern("double_heap");
+ id_empty = rb_intern("empty");
+ }
+
+ rb_scan_args(argc, argv, ":", &kwargs);
+ if (!NIL_P(kwargs)) {
+ if (rb_hash_has_key(kwargs, ID2SYM(id_toward))) {
+ VALUE toward = rb_hash_aref(kwargs, ID2SYM(id_toward));
+ toward_empty = (toward == ID2SYM(id_empty)) ? Qtrue : Qfalse;
+ }
+ if (rb_hash_has_key(kwargs, ID2SYM(id_double_heap))) {
+ double_heap = rb_hash_aref(kwargs, ID2SYM(id_double_heap));
+ }
+ }
/* Clear the heap. */
- gc_start_internal(ec, self, Qtrue, Qtrue, Qtrue, Qfalse);
+ gc_start_internal(NULL, self, Qtrue, Qtrue, Qtrue, Qfalse);
RB_VM_LOCK_ENTER();
{
@@ -10256,13 +10331,16 @@ gc_verify_compaction_references(rb_execution_context_t *ec, VALUE self, VALUE do
}
RB_VM_LOCK_LEAVE();
- gc_start_internal(ec, self, Qtrue, Qtrue, Qtrue, Qtrue);
+ gc_start_internal(NULL, self, Qtrue, Qtrue, Qtrue, Qtrue);
objspace_reachable_objects_from_root(objspace, root_obj_check_moved_i, NULL);
objspace_each_objects(objspace, heap_check_moved_i, NULL, TRUE);
- return gc_compact_stats(ec, self);
+ return gc_compact_stats(self);
}
+#else
+# define gc_verify_compaction_references rb_f_notimplement
+#endif
VALUE
rb_gc_start(void)
@@ -10722,26 +10800,45 @@ gc_disable(rb_execution_context_t *ec, VALUE _)
return rb_gc_disable();
}
+#if GC_COMPACTION_SUPPORTED
+/*
+ * call-seq:
+ * GC.auto_compact = flag
+ *
+ * Updates automatic compaction mode.
+ *
+ * When enabled, the compactor will execute on every major collection.
+ *
+ * Enabling compaction will degrade performance on major collections.
+ */
static VALUE
-gc_set_auto_compact(rb_execution_context_t *ec, VALUE _, VALUE v)
+gc_set_auto_compact(VALUE _, VALUE v)
{
/* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for
* the read barrier, so we must disable automatic compaction. */
-#if !defined(__MINGW32__) && !defined(_WIN32)
- if (!USE_MMAP_ALIGNED_ALLOC) {
- rb_raise(rb_eNotImpError, "Automatic compaction isn't available on this platform");
- }
-#endif
ruby_enable_autocompact = RTEST(v);
return v;
}
+#else
+# define gc_set_auto_compact rb_f_notimplement
+#endif
+#if GC_COMPACTION_SUPPORTED
+/*
+ * call-seq:
+ * GC.auto_compact -> true or false
+ *
+ * Returns whether or not automatic compaction has been enabled.
+ */
static VALUE
-gc_get_auto_compact(rb_execution_context_t *ec, VALUE _)
+gc_get_auto_compact(VALUE _)
{
return RBOOL(ruby_enable_autocompact);
}
+#else
+# define gc_get_auto_compact rb_f_notimplement
+#endif
static int
get_envparam_size(const char *name, size_t *default_value, size_t lower_bound)
@@ -13599,6 +13696,11 @@ Init_GC(void)
rb_define_singleton_method(rb_mGC, "malloc_allocated_size", gc_malloc_allocated_size, 0);
rb_define_singleton_method(rb_mGC, "malloc_allocations", gc_malloc_allocations, 0);
#endif
+ rb_define_singleton_method(rb_mGC, "compact", gc_compact, 0);
+ rb_define_singleton_method(rb_mGC, "auto_compact", gc_get_auto_compact, 0);
+ rb_define_singleton_method(rb_mGC, "auto_compact=", gc_set_auto_compact, 1);
+ rb_define_singleton_method(rb_mGC, "latest_compact_info", gc_compact_stats, 0);
+ rb_define_singleton_method(rb_mGC, "verify_compaction_references", gc_verify_compaction_references, -1);
#if GC_DEBUG_STRESS_TO_CLASS
rb_define_singleton_method(rb_mGC, "add_stress_to_class", rb_gcdebug_add_stress_to_class, -1);
diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb
index 42ad028530..411d5eab69 100644
--- a/test/ruby/test_gc_compact.rb
+++ b/test/ruby/test_gc_compact.rb
@@ -9,14 +9,7 @@
end
class TestGCCompact < Test::Unit::TestCase
- module SupportsCompact
- def setup
- skip "autocompact not supported on this platform" unless supports_auto_compact?
- super
- end
-
- private
-
+ module CompactionSupportInspector
def supports_auto_compact?
return true unless defined?(Etc::SC_PAGE_SIZE)
@@ -30,10 +23,19 @@ def supports_auto_compact?
end
end
- include SupportsCompact
+ module OmitUnlessCompactSupported
+ include CompactionSupportInspector
+
+ def setup
+ omit "autocompact not supported on this platform" unless supports_auto_compact?
+ super
+ end
+ end
+
+ include OmitUnlessCompactSupported
class AutoCompact < Test::Unit::TestCase
- include SupportsCompact
+ include OmitUnlessCompactSupported
def test_enable_autocompact
before = GC.auto_compact
@@ -87,13 +89,39 @@ def test_implicit_compaction_does_something
end
end
- def os_page_size
- return true unless defined?(Etc::SC_PAGE_SIZE)
+ class CompactMethodsNotImplemented < Test::Unit::TestCase
+ include CompactionSupportInspector
+
+ def assert_not_implemented(method, *args)
+ omit "autocompact is supported on this platform" if supports_auto_compact?
+
+ assert_raise(NotImplementedError) { GC.send(method, *args) }
+ refute(GC.respond_to?(method), "GC.#{method} should be defined as rb_f_notimplement")
+ end
+
+ def test_gc_compact_not_implemented
+ assert_not_implemented(:compact)
+ end
+
+ def test_gc_auto_compact_get_not_implemented
+ assert_not_implemented(:auto_compact)
+ end
+
+ def test_gc_auto_compact_set_not_implemented
+ assert_not_implemented(:auto_compact=, true)
+ end
+
+ def test_gc_latest_compact_info_not_implemented
+ assert_not_implemented(:latest_compact_info)
+ end
+
+ def test_gc_verify_compaction_references_not_implemented
+ assert_not_implemented(:verify_compaction_references)
+ end
end
- def setup
- skip "autocompact not supported on this platform" unless supports_auto_compact?
- super
+ def os_page_size
+ return true unless defined?(Etc::SC_PAGE_SIZE)
end
def test_gc_compact_stats
diff --git a/gc.rb b/gc.rb
index 72637f3796..9265dd7b57 100644
--- a/gc.rb
+++ b/gc.rb
@@ -38,27 +38,6 @@ def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true
Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false
end
- # call-seq:
- # GC.auto_compact -> true or false
- #
- # Returns whether or not automatic compaction has been enabled.
- #
- def self.auto_compact
- Primitive.gc_get_auto_compact
- end
-
- # call-seq:
- # GC.auto_compact = flag
- #
- # Updates automatic compaction mode.
- #
- # When enabled, the compactor will execute on every major collection.
- #
- # Enabling compaction will degrade performance on major collections.
- def self.auto_compact=(flag)
- Primitive.gc_set_auto_compact(flag)
- end
-
# call-seq:
# GC.enable -> true or false
#
@@ -210,53 +189,6 @@ def self.latest_gc_info hash_or_key = nil
Primitive.gc_latest_gc_info hash_or_key
end
- # call-seq:
- # GC.latest_compact_info -> {:considered=>{:T_CLASS=>11}, :moved=>{:T_CLASS=>11}}
- #
- # Returns information about object moved in the most recent GC compaction.
- #
- # The returned hash has two keys :considered and :moved. The hash for
- # :considered lists the number of objects that were considered for movement
- # by the compactor, and the :moved hash lists the number of objects that
- # were actually moved. Some objects can't be moved (maybe they were pinned)
- # so these numbers can be used to calculate compaction efficiency.
- def self.latest_compact_info
- Primitive.gc_compact_stats
- end
-
- # call-seq:
- # GC.compact
- #
- # This function compacts objects together in Ruby's heap. It eliminates
- # unused space (or fragmentation) in the heap by moving objects in to that
- # unused space. This function returns a hash which contains statistics about
- # which objects were moved. See `GC.latest_gc_info` for details about
- # compaction statistics.
- #
- # This method is implementation specific and not expected to be implemented
- # in any implementation besides MRI.
- def self.compact
- Primitive.gc_compact
- end
-
- # call-seq:
- # GC.verify_compaction_references(toward: nil, double_heap: false) -> hash
- #
- # Verify compaction reference consistency.
- #
- # This method is implementation specific. During compaction, objects that
- # were moved are replaced with T_MOVED objects. No object should have a
- # reference to a T_MOVED object after compaction.
- #
- # This function doubles the heap to ensure room to move all objects,
- # compacts the heap to make sure everything moves, updates all references,
- # then performs a full GC. If any object contains a reference to a T_MOVED
- # object, that object should be pushed on the mark stack, and will
- # make a SEGV.
- def self.verify_compaction_references(toward: nil, double_heap: false)
- Primitive.gc_verify_compaction_references(double_heap, toward == :empty)
- end
-
# call-seq:
# GC.using_rvargc? -> true or false
#

View File

@ -0,0 +1,502 @@
--- ruby-3.1.2/gc.rbinc 2022-04-12 13:11:17.000000000 +0200
+++ ruby/gc.rbinc 2022-06-08 12:49:16.288024971 +0200
@@ -9,27 +9,27 @@
#include "builtin.h" /* for RB_BUILTIN_FUNCTION */
struct rb_execution_context_struct; /* in vm_core.h */
-static VALUE builtin_inline_class_277(struct rb_execution_context_struct *ec, const VALUE self)
+static VALUE builtin_inline_class_209(struct rb_execution_context_struct *ec, const VALUE self)
{
MAYBE_UNUSED(const VALUE) flag = rb_vm_lvar(ec, -3);
-#line 277 "gc.rb"
+#line 209 "gc.rb"
rb_objspace.flags.measure_gc = RTEST(flag) ? TRUE : FALSE;
return flag;
#line 20 "gc.rbinc"
}
-static VALUE builtin_inline_class_289(struct rb_execution_context_struct *ec, const VALUE self)
+static VALUE builtin_inline_class_221(struct rb_execution_context_struct *ec, const VALUE self)
{
-#line 289 "gc.rb"
+#line 221 "gc.rb"
return
RBOOL(rb_objspace.flags.measure_gc);
#line 28 "gc.rbinc"
}
-static VALUE builtin_inline_class_299(struct rb_execution_context_struct *ec, const VALUE self)
+static VALUE builtin_inline_class_231(struct rb_execution_context_struct *ec, const VALUE self)
{
-#line 299 "gc.rb"
+#line 231 "gc.rb"
return
ULL2NUM(rb_objspace.profile.total_time_ns);
#line 36 "gc.rbinc"
@@ -52,31 +52,6 @@
}
static void
-mjit_compile_invokebuiltin_for_gc_get_auto_compact(FILE *f, long index, unsigned stack_size, bool inlinable_p)
-{
- fprintf(f, " VALUE self = GET_SELF();\n");
- fprintf(f, " typedef VALUE (*func)(rb_execution_context_t *, VALUE);\n");
- fprintf(f, " func f = (func)%"PRIuVALUE"; /* == gc_get_auto_compact */\n", (VALUE)gc_get_auto_compact);
- fprintf(f, " val = f(ec, self);\n");
-}
-
-static void
-mjit_compile_invokebuiltin_for_gc_set_auto_compact(FILE *f, long index, unsigned stack_size, bool inlinable_p)
-{
- fprintf(f, " VALUE self = GET_SELF();\n");
- fprintf(f, " typedef VALUE (*func)(rb_execution_context_t *, VALUE, VALUE);\n");
- if (index == -1) {
- fprintf(f, " const VALUE *argv = &stack[%d];\n", stack_size - 1);
- }
- else {
- fprintf(f, " const unsigned int lnum = GET_ISEQ()->body->local_table_size;\n");
- fprintf(f, " const VALUE *argv = GET_EP() - lnum - VM_ENV_DATA_SIZE + 1 + %ld;\n", index);
- }
- fprintf(f, " func f = (func)%"PRIuVALUE"; /* == gc_set_auto_compact */\n", (VALUE)gc_set_auto_compact);
- fprintf(f, " val = f(ec, self, argv[0]);\n");
-}
-
-static void
mjit_compile_invokebuiltin_for_gc_enable(FILE *f, long index, unsigned stack_size, bool inlinable_p)
{
fprintf(f, " VALUE self = GET_SELF();\n");
@@ -161,40 +136,6 @@
}
static void
-mjit_compile_invokebuiltin_for_gc_compact_stats(FILE *f, long index, unsigned stack_size, bool inlinable_p)
-{
- fprintf(f, " VALUE self = GET_SELF();\n");
- fprintf(f, " typedef VALUE (*func)(rb_execution_context_t *, VALUE);\n");
- fprintf(f, " func f = (func)%"PRIuVALUE"; /* == gc_compact_stats */\n", (VALUE)gc_compact_stats);
- fprintf(f, " val = f(ec, self);\n");
-}
-
-static void
-mjit_compile_invokebuiltin_for_gc_compact(FILE *f, long index, unsigned stack_size, bool inlinable_p)
-{
- fprintf(f, " VALUE self = GET_SELF();\n");
- fprintf(f, " typedef VALUE (*func)(rb_execution_context_t *, VALUE);\n");
- fprintf(f, " func f = (func)%"PRIuVALUE"; /* == gc_compact */\n", (VALUE)gc_compact);
- fprintf(f, " val = f(ec, self);\n");
-}
-
-static void
-mjit_compile_invokebuiltin_for_gc_verify_compaction_references(FILE *f, long index, unsigned stack_size, bool inlinable_p)
-{
- fprintf(f, " VALUE self = GET_SELF();\n");
- fprintf(f, " typedef VALUE (*func)(rb_execution_context_t *, VALUE, VALUE, VALUE);\n");
- if (index == -1) {
- fprintf(f, " const VALUE *argv = &stack[%d];\n", stack_size - 2);
- }
- else {
- fprintf(f, " const unsigned int lnum = GET_ISEQ()->body->local_table_size;\n");
- fprintf(f, " const VALUE *argv = GET_EP() - lnum - VM_ENV_DATA_SIZE + 1 + %ld;\n", index);
- }
- fprintf(f, " func f = (func)%"PRIuVALUE"; /* == gc_verify_compaction_references */\n", (VALUE)gc_verify_compaction_references);
- fprintf(f, " val = f(ec, self, argv[0], argv[1]);\n");
-}
-
-static void
mjit_compile_invokebuiltin_for__bi0(FILE *f, long index, unsigned stack_size, bool inlinable_p)
{
fprintf(f, " VALUE self = GET_SELF();\n");
@@ -202,7 +143,7 @@
if (inlinable_p) {
fprintf(f, "%s", " {\n");
fprintf(f, "%s", " MAYBE_UNUSED(const VALUE) flag = rb_vm_lvar(ec, -3);\n");
- fprintf(f, "%s", "#line 277 \"gc.rb\"\n");
+ fprintf(f, "%s", "#line 209 \"gc.rb\"\n");
fprintf(f, "%s", " \n");
fprintf(f, "%s", " rb_objspace.flags.measure_gc = RTEST(flag) ? TRUE : FALSE;\n");
fprintf(f, "%s", " return flag;\n");
@@ -211,7 +152,7 @@
fprintf(f, "%s", " \n");
return;
}
- fprintf(f, " func f = (func)%"PRIuVALUE"; /* == builtin_inline_class_277 */\n", (VALUE)builtin_inline_class_277);
+ fprintf(f, " func f = (func)%"PRIuVALUE"; /* == builtin_inline_class_209 */\n", (VALUE)builtin_inline_class_209);
fprintf(f, " val = f(ec, self);\n");
}
@@ -222,7 +163,7 @@
fprintf(f, " typedef VALUE (*func)(rb_execution_context_t *, VALUE);\n");
if (inlinable_p) {
fprintf(f, "%s", " {\n");
- fprintf(f, "%s", "#line 289 \"gc.rb\"\n");
+ fprintf(f, "%s", "#line 221 \"gc.rb\"\n");
fprintf(f, "%s", " return \n");
fprintf(f, "%s", " RBOOL(rb_objspace.flags.measure_gc);\n");
fprintf(f, "%s", "#line 52 \"gc.rbinc\"\n");
@@ -230,7 +171,7 @@
fprintf(f, "%s", " \n");
return;
}
- fprintf(f, " func f = (func)%"PRIuVALUE"; /* == builtin_inline_class_289 */\n", (VALUE)builtin_inline_class_289);
+ fprintf(f, " func f = (func)%"PRIuVALUE"; /* == builtin_inline_class_221 */\n", (VALUE)builtin_inline_class_221);
fprintf(f, " val = f(ec, self);\n");
}
@@ -241,7 +182,7 @@
fprintf(f, " typedef VALUE (*func)(rb_execution_context_t *, VALUE);\n");
if (inlinable_p) {
fprintf(f, "%s", " {\n");
- fprintf(f, "%s", "#line 299 \"gc.rb\"\n");
+ fprintf(f, "%s", "#line 231 \"gc.rb\"\n");
fprintf(f, "%s", " return \n");
fprintf(f, "%s", " ULL2NUM(rb_objspace.profile.total_time_ns);\n");
fprintf(f, "%s", "#line 59 \"gc.rbinc\"\n");
@@ -249,7 +190,7 @@
fprintf(f, "%s", " \n");
return;
}
- fprintf(f, " func f = (func)%"PRIuVALUE"; /* == builtin_inline_class_299 */\n", (VALUE)builtin_inline_class_299);
+ fprintf(f, " func f = (func)%"PRIuVALUE"; /* == builtin_inline_class_231 */\n", (VALUE)builtin_inline_class_231);
fprintf(f, " val = f(ec, self);\n");
}
@@ -258,21 +199,16 @@
// table definition
static const struct rb_builtin_function gc_table[] = {
RB_BUILTIN_FUNCTION(0, gc_start_internal, gc_start_internal, 4, mjit_compile_invokebuiltin_for_gc_start_internal),
- RB_BUILTIN_FUNCTION(1, gc_get_auto_compact, gc_get_auto_compact, 0, mjit_compile_invokebuiltin_for_gc_get_auto_compact),
- RB_BUILTIN_FUNCTION(2, gc_set_auto_compact, gc_set_auto_compact, 1, mjit_compile_invokebuiltin_for_gc_set_auto_compact),
- RB_BUILTIN_FUNCTION(3, gc_enable, gc_enable, 0, mjit_compile_invokebuiltin_for_gc_enable),
- RB_BUILTIN_FUNCTION(4, gc_disable, gc_disable, 0, mjit_compile_invokebuiltin_for_gc_disable),
- RB_BUILTIN_FUNCTION(5, gc_stress_get, gc_stress_get, 0, mjit_compile_invokebuiltin_for_gc_stress_get),
- RB_BUILTIN_FUNCTION(6, gc_stress_set_m, gc_stress_set_m, 1, mjit_compile_invokebuiltin_for_gc_stress_set_m),
- RB_BUILTIN_FUNCTION(7, gc_count, gc_count, 0, mjit_compile_invokebuiltin_for_gc_count),
- RB_BUILTIN_FUNCTION(8, gc_stat, gc_stat, 1, mjit_compile_invokebuiltin_for_gc_stat),
- RB_BUILTIN_FUNCTION(9, gc_latest_gc_info, gc_latest_gc_info, 1, mjit_compile_invokebuiltin_for_gc_latest_gc_info),
- RB_BUILTIN_FUNCTION(10, gc_compact_stats, gc_compact_stats, 0, mjit_compile_invokebuiltin_for_gc_compact_stats),
- RB_BUILTIN_FUNCTION(11, gc_compact, gc_compact, 0, mjit_compile_invokebuiltin_for_gc_compact),
- RB_BUILTIN_FUNCTION(12, gc_verify_compaction_references, gc_verify_compaction_references, 2, mjit_compile_invokebuiltin_for_gc_verify_compaction_references),
- RB_BUILTIN_FUNCTION(13, _bi0, builtin_inline_class_277, 0, mjit_compile_invokebuiltin_for__bi0),
- RB_BUILTIN_FUNCTION(14, _bi1, builtin_inline_class_289, 0, mjit_compile_invokebuiltin_for__bi1),
- RB_BUILTIN_FUNCTION(15, _bi2, builtin_inline_class_299, 0, mjit_compile_invokebuiltin_for__bi2),
+ RB_BUILTIN_FUNCTION(1, gc_enable, gc_enable, 0, mjit_compile_invokebuiltin_for_gc_enable),
+ RB_BUILTIN_FUNCTION(2, gc_disable, gc_disable, 0, mjit_compile_invokebuiltin_for_gc_disable),
+ RB_BUILTIN_FUNCTION(3, gc_stress_get, gc_stress_get, 0, mjit_compile_invokebuiltin_for_gc_stress_get),
+ RB_BUILTIN_FUNCTION(4, gc_stress_set_m, gc_stress_set_m, 1, mjit_compile_invokebuiltin_for_gc_stress_set_m),
+ RB_BUILTIN_FUNCTION(5, gc_count, gc_count, 0, mjit_compile_invokebuiltin_for_gc_count),
+ RB_BUILTIN_FUNCTION(6, gc_stat, gc_stat, 1, mjit_compile_invokebuiltin_for_gc_stat),
+ RB_BUILTIN_FUNCTION(7, gc_latest_gc_info, gc_latest_gc_info, 1, mjit_compile_invokebuiltin_for_gc_latest_gc_info),
+ RB_BUILTIN_FUNCTION(8, _bi0, builtin_inline_class_209, 0, mjit_compile_invokebuiltin_for__bi0),
+ RB_BUILTIN_FUNCTION(9, _bi1, builtin_inline_class_221, 0, mjit_compile_invokebuiltin_for__bi1),
+ RB_BUILTIN_FUNCTION(10, _bi2, builtin_inline_class_231, 0, mjit_compile_invokebuiltin_for__bi2),
RB_BUILTIN_FUNCTION(-1, NULL, NULL, 0, 0),
};
@@ -282,8 +218,6 @@
COMPILER_WARNING_ERROR(-Wincompatible-pointer-types)
#endif
if (0) rb_builtin_function_check_arity4(gc_start_internal);
- if (0) rb_builtin_function_check_arity0(gc_get_auto_compact);
- if (0) rb_builtin_function_check_arity1(gc_set_auto_compact);
if (0) rb_builtin_function_check_arity0(gc_enable);
if (0) rb_builtin_function_check_arity0(gc_disable);
if (0) rb_builtin_function_check_arity0(gc_stress_get);
@@ -291,12 +225,9 @@
if (0) rb_builtin_function_check_arity0(gc_count);
if (0) rb_builtin_function_check_arity1(gc_stat);
if (0) rb_builtin_function_check_arity1(gc_latest_gc_info);
- if (0) rb_builtin_function_check_arity0(gc_compact_stats);
- if (0) rb_builtin_function_check_arity0(gc_compact);
- if (0) rb_builtin_function_check_arity2(gc_verify_compaction_references);
- if (0) rb_builtin_function_check_arity0(builtin_inline_class_277);
- if (0) rb_builtin_function_check_arity0(builtin_inline_class_289);
- if (0) rb_builtin_function_check_arity0(builtin_inline_class_299);
+ if (0) rb_builtin_function_check_arity0(builtin_inline_class_209);
+ if (0) rb_builtin_function_check_arity0(builtin_inline_class_221);
+ if (0) rb_builtin_function_check_arity0(builtin_inline_class_231);
COMPILER_WARNING_POP
// load
--- ruby-3.1.2/miniprelude.c 2022-04-12 13:11:17.000000000 +0200
+++ ruby/miniprelude.c 2022-06-08 12:49:16.377024871 +0200
@@ -545,11 +545,10 @@
static const char prelude_name2[] = "<internal:gc>";
static const struct {
- char L0[479]; /* 1..58 */
- char L58[508]; /* 59..204 */
- char L204[504]; /* 205..275 */
- char L275[490]; /* 276..306 */
- char L306[128]; /* 307..312 */
+ char L0[492]; /* 1..70 */
+ char L70[468]; /* 71..197 */
+ char L197[470]; /* 198..237 */
+ char L237[211]; /* 238..244 */
} prelude_code2 = {
#line 1 "gc.rb"
""/* for gc.c */
@@ -593,29 +592,6 @@
" end\n"
"\n"
"\n"/* call-seq: */
-"\n"/* GC.auto_compact -> true or false */
-"\n"/* */
-"\n"/* Returns whether or not automatic compaction has been enabled. */
-"\n"/* */
-" def self.auto_compact\n"
-" Primitive.gc_get_auto_compact\n"
-" end\n"
-"\n"
-"\n"/* call-seq: */
-"\n"/* GC.auto_compact = flag */
-"\n"/* */
-"\n"/* Updates automatic compaction mode. */
-"\n"/* */
-"\n"/* When enabled, the compactor will execute on every major collection. */
-"\n"/* */
-"\n"/* Enabling compaction will degrade performance on major collections. */
-" def self.auto_compact=(flag)\n"
-,
-#line 59 "gc.rb"
-" Primitive.gc_set_auto_compact(flag)\n"
-" end\n"
-"\n"
-"\n"/* call-seq: */
"\n"/* GC.enable -> true or false */
"\n"/* */
"\n"/* Enables garbage collection, returning +true+ if garbage */
@@ -645,6 +621,8 @@
"\n"/* GC.stress -> integer, true or false */
"\n"/* */
"\n"/* Returns current status of GC stress mode. */
+,
+#line 71 "gc.rb"
" def self.stress\n"
" Primitive.gc_stress_get\n"
" end\n"
@@ -758,8 +736,6 @@
"\n"/* GC.latest_gc_info(:major_by) -> :malloc */
"\n"/* */
"\n"/* Returns information about the most recent garbage collection. */
-,
-#line 205 "gc.rb"
"\n"/* */
"\n"/* If the optional argument, hash, is given, */
"\n"/* it is overwritten and returned. */
@@ -768,59 +744,14 @@
" Primitive.gc_latest_gc_info hash_or_key\n"
" end\n"
"\n"
-"\n"/* call-seq: */
-"\n"/* GC.latest_compact_info -> {:considered=>{:T_CLASS=>11}, :moved=>{:T_CLASS=>11}} */
-"\n"/* */
-"\n"/* Returns information about object moved in the most recent GC compaction. */
-"\n"/* */
-"\n"/* The returned hash has two keys :considered and :moved. The hash for */
-"\n"/* :considered lists the number of objects that were considered for movement */
-"\n"/* by the compactor, and the :moved hash lists the number of objects that */
-"\n"/* were actually moved. Some objects can't be moved (maybe they were pinned) */
-"\n"/* so these numbers can be used to calculate compaction efficiency. */
-" def self.latest_compact_info\n"
-" Primitive.gc_compact_stats\n"
-" end\n"
-"\n"
-"\n"/* call-seq: */
-"\n"/* GC.compact */
-"\n"/* */
-"\n"/* This function compacts objects together in Ruby's heap. It eliminates */
-"\n"/* unused space (or fragmentation) in the heap by moving objects in to that */
-"\n"/* unused space. This function returns a hash which contains statistics about */
-"\n"/* which objects were moved. See `GC.latest_gc_info` for details about */
-"\n"/* compaction statistics. */
-"\n"/* */
-"\n"/* This method is implementation specific and not expected to be implemented */
-"\n"/* in any implementation besides MRI. */
-" def self.compact\n"
-" Primitive.gc_compact\n"
-" end\n"
-"\n"
-"\n"/* call-seq: */
-"\n"/* GC.verify_compaction_references(toward: nil, double_heap: false) -> hash */
-"\n"/* */
-"\n"/* Verify compaction reference consistency. */
-"\n"/* */
-"\n"/* This method is implementation specific. During compaction, objects that */
-"\n"/* were moved are replaced with T_MOVED objects. No object should have a */
-"\n"/* reference to a T_MOVED object after compaction. */
-"\n"/* */
-"\n"/* This function doubles the heap to ensure room to move all objects, */
-"\n"/* compacts the heap to make sure everything moves, updates all references, */
-"\n"/* then performs a full GC. If any object contains a reference to a T_MOVED */
-"\n"/* object, that object should be pushed on the mark stack, and will */
-"\n"/* make a SEGV. */
-" def self.verify_compaction_references(toward: nil, double_heap: false)\n"
-" Primitive.gc_verify_compaction_references(double_heap, toward == :empty)\n"
-" end\n"
-"\n"
"\n"/* call-seq: */
"\n"/* GC.using_rvargc? -> true or false */
"\n"/* */
"\n"/* Returns true if using experimental feature Variable Width Allocation, false */
"\n"/* otherwise. */
" def self.using_rvargc?\n"/* :nodoc: */
+,
+#line 198 "gc.rb"
" GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] > 1\n"
" end\n"
"\n"
@@ -831,8 +762,6 @@
"\n"/* Enable to measure GC time. */
"\n"/* You can get the result with <tt>GC.stat(:time)</tt>. */
"\n"/* Note that GC time measurement can cause some performance overhead. */
-,
-#line 276 "gc.rb"
" def self.measure_total_time=(flag)\n"
" Primitive.cstmt! %{\n"
" rb_objspace.flags.measure_gc = RTEST(flag) ? TRUE : FALSE;\n"
@@ -863,15 +792,15 @@
"end\n"
"\n"
"module ObjectSpace\n"
-" def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true\n"
,
-#line 307 "gc.rb"
+#line 238 "gc.rb"
+" def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true\n"
" Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false\n"
" end\n"
"\n"
" module_function :garbage_collect\n"
"end\n"
-#line 875 "miniprelude.c"
+#line 804 "miniprelude.c"
};
static const char prelude_name3[] = "<internal:numeric>";
@@ -1223,7 +1152,7 @@
" end\n"
"\n"
"end\n"
-#line 1227 "miniprelude.c"
+#line 1156 "miniprelude.c"
};
static const char prelude_name4[] = "<internal:io>";
@@ -1354,7 +1283,7 @@
" Primitive.io_write_nonblock(buf, exception)\n"
" end\n"
"end\n"
-#line 1358 "miniprelude.c"
+#line 1287 "miniprelude.c"
};
static const char prelude_name5[] = "<internal:marshal>";
@@ -1402,7 +1331,7 @@
" alias restore load\n"
" end\n"
"end\n"
-#line 1406 "miniprelude.c"
+#line 1335 "miniprelude.c"
};
static const char prelude_name6[] = "<internal:pack>";
@@ -1724,7 +1653,7 @@
" Primitive.pack_unpack1(fmt, offset)\n"
" end\n"
"end\n"
-#line 1728 "miniprelude.c"
+#line 1657 "miniprelude.c"
};
static const char prelude_name7[] = "<internal:trace_point>";
@@ -2111,7 +2040,7 @@
" Primitive.tracepoint_attr_instruction_sequence\n"
" end\n"
"end\n"
-#line 2115 "miniprelude.c"
+#line 2044 "miniprelude.c"
};
static const char prelude_name8[] = "<internal:warning>";
@@ -2172,7 +2101,7 @@
" Primitive.rb_warn_m(msgs, uplevel, category)\n"
" end\n"
"end\n"
-#line 2176 "miniprelude.c"
+#line 2105 "miniprelude.c"
};
static const char prelude_name9[] = "<internal:array>";
@@ -2249,7 +2178,7 @@
" end\n"
" end\n"
"end\n"
-#line 2253 "miniprelude.c"
+#line 2182 "miniprelude.c"
};
static const char prelude_name10[] = "<internal:kernel>";
@@ -2438,7 +2367,7 @@
" end\n"
" end\n"
"end\n"
-#line 2442 "miniprelude.c"
+#line 2371 "miniprelude.c"
};
static const char prelude_name11[] = "<internal:ractor>";
@@ -3305,7 +3234,7 @@
" }\n"
" end\n"
"end\n"
-#line 3309 "miniprelude.c"
+#line 3238 "miniprelude.c"
};
static const char prelude_name12[] = "<internal:timev>";
@@ -3628,7 +3557,7 @@
" Primitive.time_init_args(year, mon, mday, hour, min, sec, zone)\n"
" end\n"
"end\n"
-#line 3632 "miniprelude.c"
+#line 3561 "miniprelude.c"
};
static const char prelude_name13[] = "<internal:nilclass>";
@@ -3661,7 +3590,7 @@
" return 0.0\n"
" end\n"
"end\n"
-#line 3665 "miniprelude.c"
+#line 3594 "miniprelude.c"
};
static const char prelude_name14[] = "<internal:prelude>";
@@ -3691,7 +3620,7 @@
"\n"
" private :pp\n"
"end\n"
-#line 3695 "miniprelude.c"
+#line 3624 "miniprelude.c"
};
static const char prelude_name15[] = "<internal:gem_prelude>";
@@ -3718,7 +3647,7 @@
"rescue LoadError\n"
" warn \"`did_you_mean' was not loaded.\"\n"
"end if defined?(DidYouMean)\n"
-#line 3722 "miniprelude.c"
+#line 3651 "miniprelude.c"
};
static const char prelude_name16[] = "<internal:yjit>";
@@ -4059,7 +3988,7 @@
" end\n"
" end\n"
"end\n"
-#line 4063 "miniprelude.c"
+#line 3992 "miniprelude.c"
};
COMPILER_WARNING_POP

View File

@ -22,7 +22,7 @@
%endif
%global release 164
%global release 165
%{!?release_string:%define release_string %{?development_release:0.}%{release}%{?development_release:.%{development_release}}%{?dist}}
# The RubyGems library has to stay out of Ruby directory tree, since the
@ -171,6 +171,22 @@ Patch20: ruby-bundler-2.4.0-bundle-update-bundler-test-in-ruby.patch
# https://bugs.ruby-lang.org/issues/18373
# https://github.com/ruby/ruby/pull/5774
Patch21: ruby-3.2.0-Build-extension-libraries-in-bundled-gems.patch
# If GC compaction is not supported on platform, define the
# corresponding GC methods as not implemented.
# https://bugs.ruby-lang.org/issues/18779
# https://github.com/ruby/ruby/pull/5934
Patch22: ruby-3.2.0-define-unsupported-gc-compaction-methods-as-rb_f_notimplement.patch
# To regenerate the patch you need to have ruby, autoconf, xz, tar and make installed:
# tar -Jxvf ./ruby-3.1.2.tar.xz
# git clone https://github.com/ruby/ruby.git
# cd ruby && git checkout v3_1_2
# patch -p1 < ../ruby-3.2.0-define-unsupported-gc-compaction-methods-as-rb_f_notimplement.patch
# ./autogen.sh && ./configure
# make gc.rbinc miniprelude.c
# cd ..
# diff -u {ruby-3.1.2,ruby}/gc.rbinc > ruby-3.2.0-define-unsupported-gc-compaction-methods_generated-files.patch
# diff -u {ruby-3.1.2,ruby}/miniprelude.c >> ruby-3.2.0-define-unsupported-gc-compaction-methods_generated-files.patch
Patch23: ruby-3.2.0-define-unsupported-gc-compaction-methods_generated-files.patch
Requires: %{name}-libs%{?_isa} = %{version}-%{release}
Suggests: rubypick
@ -643,6 +659,8 @@ rm -rf ext/fiddle/libffi*
mkdir .bundle/specifications
find .bundle/gems -name '*-[0-9]*.gemspec' -exec cp -t .bundle/specifications/ {} +
%patch21 -p1
%patch22 -p1
%patch23 -p1
# Provide an example of usage of the tapset:
cp -a %{SOURCE3} .
@ -650,6 +668,12 @@ cp -a %{SOURCE3} .
%build
autoconf
# Some platforms do not support compaction and upstream does not seem to provide the
# right mechanism for the enablement of the preprocessor macros.
# https://bugs.ruby-lang.org/issues/18829
%ifnarch ppc64le
CFLAGS="%{build_cflags} -DGC_COMPACTION_SUPPORTED"
%endif
%configure \
--with-rubylibprefix='%{ruby_libdir}' \
--with-archlibdir='%{_libdir}' \
@ -1499,6 +1523,9 @@ mv test/fiddle/test_import.rb{,.disable}
%changelog
* Tue Jun 07 2022 Jarek Prokop <jprokop@redhat.com> - 3.1.2-165
- Define GC compaction methods as rb_f_notimplement on unsupported platforms.
* Thu Apr 14 2022 Vít Ondruch <vondruch@redhat.com> - 3.1.2-164
- Upgrade to Ruby 3.1.2.
- Use upstream patch for correct build of gem extensions.