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