e41f67
From 4d9cc9afa47981520d991d19fd78b322f1ba9f2a Mon Sep 17 00:00:00 2001
e41f67
From: Jarek Prokop <jprokop@redhat.com>
e41f67
Date: Wed, 22 Jun 2022 01:03:49 +0200
e41f67
Subject: [PATCH] Detect compaction support during runtime.
e41f67
e41f67
The patch is created by backporting 3 commits from
e41f67
the upstream Ruby master branch in the chronological order below.
e41f67
e41f67
https://github.com/ruby/ruby/commit/52d42e702375446746164a0251e1a10bce813b78
e41f67
https://github.com/ruby/ruby/commit/79eaaf2d0b641710613f16525e4b4c439dfe854e
e41f67
https://github.com/ruby/ruby/commit/2c190863239bee3f54cfb74b16bb6ea4cae6ed20
e41f67
e41f67
== How to create this patch ==
e41f67
e41f67
Download Ruby source code.
e41f67
```
e41f67
$ git clone https://github.com/ruby/ruby.git
e41f67
$ cd ruby
e41f67
```
e41f67
e41f67
First create a commit squashed from the 3 commits above.
e41f67
Checkout the second commmit above, and create a temporary branch.
e41f67
```
e41f67
$ git checkout 79eaaf2d0b641710613f16525e4b4c439dfe854e
e41f67
$ git checkout -b wip/detect-compaction-runtime-tmp
e41f67
```
e41f67
e41f67
Cherry pick the third commit on the second commit.
e41f67
```
e41f67
$ git cherry-pick 2c190863239bee3f54cfb74b16bb6ea4cae6ed20
e41f67
```
e41f67
e41f67
Squash the last 3 commits on the branch.
e41f67
```
e41f67
$ git rebase -i 2223eb082afa6d05321b69df783d4133b9aacba6
e41f67
```
e41f67
e41f67
Then checkout Ruby 3.1.2 branch.
e41f67
Create a new branch.
e41f67
Merge the Fedora Ruby's
e41f67
ruby-3.2.0-define-unsupported-gc-compaction-methods-as-rb_f_notimplement.patch.
e41f67
```
e41f67
$ git checkout v3_1_2
e41f67
$ git checkout -b wip/detect-compaction-runtime
e41f67
$ patch -p1 <
e41f67
~/fed/ruby/ruby-3.2.0-define-unsupported-gc-compaction-methods-as-rb_f_notimplement.patch
e41f67
$ git add gc.c gc.rb test/ruby/test_gc_compact.rb
e41f67
$ git commit
e41f67
```
e41f67
e41f67
Merge the squashed one commit on the
e41f67
`wip/detect-compaction-runtime-tmp` branch
e41f67
into the `wip/detect-compaction-runtime` branch.
e41f67
```
e41f67
$ git cherry-pick <the squashed commit above>
e41f67
```
e41f67
e41f67
Fix conflicts seeing the difference by `git show 
e41f67
above>`
e41f67
on another terminal.
e41f67
```
e41f67
$ vi gc.c
e41f67
$ git add gc.c
e41f67
$ git commit
e41f67
```
e41f67
e41f67
== Original commit messages ==
e41f67
e41f67
This is a combination of 3 commits.
e41f67
This is the 1st commit message:
e41f67
~~~
e41f67
Rename GC_COMPACTION_SUPPORTED
e41f67
e41f67
Naming this macro GC_COMPACTION_SUPPORTED is misleading because it
e41f67
only checks whether compaction is supported at compile time.
e41f67
e41f67
[Bug #18829]
e41f67
~~~
e41f67
e41f67
This is the commit message #2:
e41f67
~~~
e41f67
Include runtime checks for compaction support
e41f67
e41f67
Commit 0c36ba53192c5a0d245c9b626e4346a32d7d144e changed GC compaction
e41f67
methods to not be implemented when not supported. However, that commit
e41f67
only does compile time checks (which currently only checks for WASM),
e41f67
but there are additional compaction support checks during run time.
e41f67
e41f67
This commit changes it so that GC compaction methods aren't defined
e41f67
during run time if the platform does not support GC compaction.
e41f67
e41f67
[Bug #18829]
e41f67
~~~
e41f67
e41f67
This is the commit message #3:
e41f67
~~~
e41f67
Suppress code unused unless GC_CAN_COMPILE_COMPACTION
e41f67
~~~
e41f67
---
e41f67
 gc.c | 63 +++++++++++++++++++++++++++++++++++++++++-------------------
e41f67
 1 file changed, 43 insertions(+), 20 deletions(-)
e41f67
e41f67
diff --git a/gc.c b/gc.c
e41f67
index 1c35856c44..bff0666a17 100644
e41f67
--- a/gc.c
e41f67
+++ b/gc.c
e41f67
@@ -4980,6 +4980,23 @@ gc_unprotect_pages(rb_objspace_t *objspace, rb_heap_t *heap)
e41f67
 static void gc_update_references(rb_objspace_t * objspace);
e41f67
 static void invalidate_moved_page(rb_objspace_t *objspace, struct heap_page *page);
e41f67
 
e41f67
+#ifndef GC_CAN_COMPILE_COMPACTION
e41f67
+#if defined(__wasi__) /* WebAssembly doesn't support signals */
e41f67
+# define GC_CAN_COMPILE_COMPACTION 0
e41f67
+#else
e41f67
+# define GC_CAN_COMPILE_COMPACTION 1
e41f67
+#endif
e41f67
+#endif
e41f67
+
e41f67
+#if defined(__MINGW32__) || defined(_WIN32)
e41f67
+# define GC_COMPACTION_SUPPORTED 1
e41f67
+#else
e41f67
+/* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for
e41f67
+ * the read barrier, so we must disable compaction. */
e41f67
+# define GC_COMPACTION_SUPPORTED (GC_CAN_COMPILE_COMPACTION && USE_MMAP_ALIGNED_ALLOC)
e41f67
+#endif
e41f67
+
e41f67
+#if GC_CAN_COMPILE_COMPACTION
e41f67
 static void
e41f67
 read_barrier_handler(uintptr_t address)
e41f67
 {
e41f67
@@ -5000,6 +5017,7 @@ read_barrier_handler(uintptr_t address)
e41f67
     }
e41f67
     RB_VM_LOCK_LEAVE();
e41f67
 }
e41f67
+#endif
e41f67
 
e41f67
 #if defined(_WIN32)
e41f67
 static LPTOP_LEVEL_EXCEPTION_FILTER old_handler;
e41f67
@@ -9250,13 +9268,7 @@ gc_start_internal(rb_execution_context_t *ec, VALUE self, VALUE full_mark, VALUE
e41f67
 
e41f67
     /* For now, compact implies full mark / sweep, so ignore other flags */
e41f67
     if (RTEST(compact)) {
e41f67
-        /* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for
e41f67
-         * the read barrier, so we must disable compaction. */
e41f67
-#if !defined(__MINGW32__) && !defined(_WIN32)
e41f67
-        if (!USE_MMAP_ALIGNED_ALLOC) {
e41f67
-            rb_raise(rb_eNotImpError, "Compaction isn't available on this platform");
e41f67
-        }
e41f67
-#endif
e41f67
+        GC_ASSERT(GC_COMPACTION_SUPPORTED);
e41f67
 
e41f67
         reason |= GPR_FLAG_COMPACT;
e41f67
     }
e41f67
@@ -9421,7 +9433,7 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, size_t slot_size)
e41f67
     return (VALUE)src;
e41f67
 }
e41f67
 
e41f67
-#if GC_COMPACTION_SUPPORTED
e41f67
+#if GC_CAN_COMPILE_COMPACTION
e41f67
 static int
e41f67
 compare_free_slots(const void *left, const void *right, void *dummy)
e41f67
 {
e41f67
@@ -10149,7 +10161,7 @@ gc_update_references(rb_objspace_t *objspace)
e41f67
     gc_update_table_refs(objspace, finalizer_table);
e41f67
 }
e41f67
 
e41f67
-#if GC_COMPACTION_SUPPORTED
e41f67
+#if GC_CAN_COMPILE_COMPACTION
e41f67
 /*
e41f67
  *  call-seq:
e41f67
  *     GC.latest_compact_info -> {:considered=>{:T_CLASS=>11}, :moved=>{:T_CLASS=>11}}
e41f67
@@ -10190,7 +10202,7 @@ gc_compact_stats(VALUE self)
e41f67
 #  define gc_compact_stats rb_f_notimplement
e41f67
 #endif
e41f67
 
e41f67
-#if GC_COMPACTION_SUPPORTED
e41f67
+#if GC_CAN_COMPILE_COMPACTION
e41f67
 static void
e41f67
 root_obj_check_moved_i(const char *category, VALUE obj, void *data)
e41f67
 {
e41f67
@@ -10269,7 +10281,7 @@ gc_compact(VALUE self)
e41f67
 #  define gc_compact rb_f_notimplement
e41f67
 #endif
e41f67
 
e41f67
-#if GC_COMPACTION_SUPPORTED
e41f67
+#if GC_CAN_COMPILE_COMPACTION
e41f67
 /*
e41f67
  * call-seq:
e41f67
  *    GC.verify_compaction_references(toward: nil, double_heap: false) -> hash
e41f67
@@ -10800,7 +10812,7 @@ gc_disable(rb_execution_context_t *ec, VALUE _)
e41f67
     return rb_gc_disable();
e41f67
 }
e41f67
 
e41f67
-#if GC_COMPACTION_SUPPORTED
e41f67
+#if GC_CAN_COMPILE_COMPACTION
e41f67
 /*
e41f67
  *  call-seq:
e41f67
  *     GC.auto_compact = flag
e41f67
@@ -10814,8 +10826,7 @@ gc_disable(rb_execution_context_t *ec, VALUE _)
e41f67
 static VALUE
e41f67
 gc_set_auto_compact(VALUE _, VALUE v)
e41f67
 {
e41f67
-    /* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for
e41f67
-     * the read barrier, so we must disable automatic compaction. */
e41f67
+    GC_ASSERT(GC_COMPACTION_SUPPORTED);
e41f67
 
e41f67
     ruby_enable_autocompact = RTEST(v);
e41f67
     return v;
e41f67
@@ -10824,7 +10835,8 @@ gc_set_auto_compact(VALUE _, VALUE v)
e41f67
 #  define gc_set_auto_compact rb_f_notimplement
e41f67
 #endif
e41f67
 
e41f67
-#if GC_COMPACTION_SUPPORTED
e41f67
+
e41f67
+#if GC_CAN_COMPILE_COMPACTION
e41f67
 /*
e41f67
  *  call-seq:
e41f67
  *     GC.auto_compact    -> true or false
e41f67
@@ -13696,11 +13708,21 @@ Init_GC(void)
e41f67
     rb_define_singleton_method(rb_mGC, "malloc_allocated_size", gc_malloc_allocated_size, 0);
e41f67
     rb_define_singleton_method(rb_mGC, "malloc_allocations", gc_malloc_allocations, 0);
e41f67
 #endif
e41f67
-    rb_define_singleton_method(rb_mGC, "compact", gc_compact, 0);
e41f67
-    rb_define_singleton_method(rb_mGC, "auto_compact", gc_get_auto_compact, 0);
e41f67
-    rb_define_singleton_method(rb_mGC, "auto_compact=", gc_set_auto_compact, 1);
e41f67
-    rb_define_singleton_method(rb_mGC, "latest_compact_info", gc_compact_stats, 0);
e41f67
-    rb_define_singleton_method(rb_mGC, "verify_compaction_references", gc_verify_compaction_references, -1);
e41f67
+    if (GC_COMPACTION_SUPPORTED) {
e41f67
+        rb_define_singleton_method(rb_mGC, "compact", gc_compact, 0);
e41f67
+        rb_define_singleton_method(rb_mGC, "auto_compact", gc_get_auto_compact, 0);
e41f67
+        rb_define_singleton_method(rb_mGC, "auto_compact=", gc_set_auto_compact, 1);
e41f67
+        rb_define_singleton_method(rb_mGC, "latest_compact_info", gc_compact_stats, 0);
e41f67
+        rb_define_singleton_method(rb_mGC, "verify_compaction_references", gc_verify_compaction_references, -1);
e41f67
+    }
e41f67
+    else {
e41f67
+        rb_define_singleton_method(rb_mGC, "compact", rb_f_notimplement, 0);
e41f67
+        rb_define_singleton_method(rb_mGC, "auto_compact", rb_f_notimplement, 0);
e41f67
+        rb_define_singleton_method(rb_mGC, "auto_compact=", rb_f_notimplement, 1);
e41f67
+        rb_define_singleton_method(rb_mGC, "latest_compact_info", rb_f_notimplement, 0);
e41f67
+        /* When !GC_COMPACTION_SUPPORTED, this method is not defined in gc.rb */
e41f67
+        rb_define_singleton_method(rb_mGC, "verify_compaction_references", rb_f_notimplement, -1);
e41f67
+    }
e41f67
 
e41f67
 #if GC_DEBUG_STRESS_TO_CLASS
e41f67
     rb_define_singleton_method(rb_mGC, "add_stress_to_class", rb_gcdebug_add_stress_to_class, -1);
e41f67
@@ -13724,6 +13746,7 @@ Init_GC(void)
e41f67
 	OPT(MALLOC_ALLOCATED_SIZE);
e41f67
 	OPT(MALLOC_ALLOCATED_SIZE_CHECK);
e41f67
 	OPT(GC_PROFILE_DETAIL_MEMORY);
e41f67
+	OPT(GC_COMPACTION_SUPPORTED);
e41f67
 #undef OPT
e41f67
 	OBJ_FREEZE(opts);
e41f67
     }
e41f67
-- 
e41f67
2.36.1
e41f67