import UBI ruby-3.0.7-165.el9_5
This commit is contained in:
parent
b905eb2d00
commit
87ae0a7ca0
@ -0,0 +1,283 @@
|
||||
From ec992161c3ca346061fb5b1b9c44402a03105b79 Mon Sep 17 00:00:00 2001
|
||||
From: Jarek Prokop <jprokop@redhat.com>
|
||||
Date: Wed, 22 Jun 2022 01:03:49 +0200
|
||||
Subject: [PATCH] Detect compaction support during runtime.
|
||||
|
||||
The patch is created by backporting 3 commits from
|
||||
the upstream Ruby master branch in the chronological order below.
|
||||
|
||||
https://github.com/ruby/ruby/commit/52d42e702375446746164a0251e1a10bce813b78
|
||||
https://github.com/ruby/ruby/commit/79eaaf2d0b641710613f16525e4b4c439dfe854e
|
||||
https://github.com/ruby/ruby/commit/2c190863239bee3f54cfb74b16bb6ea4cae6ed20
|
||||
|
||||
== How to create this patch ==
|
||||
|
||||
Download Ruby source code.
|
||||
```
|
||||
$ git clone https://github.com/ruby/ruby.git
|
||||
$ cd ruby
|
||||
```
|
||||
|
||||
First create a commit squashed from the 3 commits above.
|
||||
Checkout the second commmit above, and create a temporary branch.
|
||||
```
|
||||
$ git checkout 79eaaf2d0b641710613f16525e4b4c439dfe854e
|
||||
$ git checkout -b wip/detect-compaction-runtime-tmp
|
||||
```
|
||||
|
||||
Cherry pick the third commit on the second commit.
|
||||
```
|
||||
$ git cherry-pick 2c190863239bee3f54cfb74b16bb6ea4cae6ed20
|
||||
```
|
||||
|
||||
Squash the last 3 commits on the branch.
|
||||
```
|
||||
$ git rebase -i 2223eb082afa6d05321b69df783d4133b9aacba6
|
||||
```
|
||||
|
||||
Then checkout Ruby 3.1.2 branch.
|
||||
Create a new branch.
|
||||
Merge the Fedora Ruby's
|
||||
ruby-3.2.0-define-unsupported-gc-compaction-methods-as-rb_f_notimplement.patch.
|
||||
```
|
||||
$ git checkout v3_1_2
|
||||
$ git checkout -b wip/detect-compaction-runtime
|
||||
$ patch -p1 <
|
||||
~/fed/ruby/ruby-3.2.0-define-unsupported-gc-compaction-methods-as-rb_f_notimplement.patch
|
||||
$ git add gc.c gc.rb test/ruby/test_gc_compact.rb
|
||||
$ git commit
|
||||
```
|
||||
|
||||
Merge the squashed one commit on the
|
||||
`wip/detect-compaction-runtime-tmp` branch
|
||||
into the `wip/detect-compaction-runtime` branch.
|
||||
```
|
||||
$ git cherry-pick <the squashed commit above>
|
||||
```
|
||||
|
||||
Fix conflicts seeing the difference by `git show <the squashed commit
|
||||
above>`
|
||||
on another terminal.
|
||||
```
|
||||
$ vi gc.c
|
||||
$ git add gc.c
|
||||
$ git commit
|
||||
```
|
||||
|
||||
== Notes for the patch ==
|
||||
|
||||
```
|
||||
+# define GC_COMPACTION_SUPPORTED (GC_CAN_COMPILE_COMPACTION && USE_MMAP_ALIGNED_ALLOC)
|
||||
```
|
||||
|
||||
We use the USE_MMAP_ALIGNED_ALLOC instead of HEAP_PAGE_ALLOC_USE_MMAP on
|
||||
the line above. Because while the Ruby on the master branch replaced the
|
||||
USE_MMAP_ALIGNED_ALLOC with HEAP_PAGE_ALLOC_USE_MMAP, Ruby 3.1.2 doesn't.
|
||||
See <https://github.com/ruby/ruby/commit/fe21b7794af0cdb7ebd502e2c0da38c68fd89839>.
|
||||
|
||||
```
|
||||
+ rb_define_singleton_method(rb_mGC, "verify_compaction_references", gc_verify_compaction_references, -1);
|
||||
```
|
||||
|
||||
We added the line in the case that GC_COMPACTION_SUPPORTED is true.
|
||||
Because while the Ruby on the master branch defines the
|
||||
GC.verify_compaction_references in the gc.rb in
|
||||
the case that GC_COMPACTION_SUPPORTED is true, Ruby 3.1.2
|
||||
doesn't define it in the gc.rb.
|
||||
See <https://github.com/ruby/ruby/commit/b96a3a6fd2093e1dbea5491c002da515652dd347>.
|
||||
|
||||
```
|
||||
+ OPT(GC_COMPACTION_SUPPORTED);
|
||||
```
|
||||
|
||||
We added the line to expose the C macro to Ruby level.
|
||||
In Ruby the macro existance can then be checked like so:
|
||||
```Ruby
|
||||
GC::OPTS.include?("GC_COMPACTION_SUPPORTED")
|
||||
```
|
||||
It will return `true` if the GC_COMPACTION_SUPPORTED evaluates to `true` on the
|
||||
C level, `false` otherwise.
|
||||
See <https://github.com/ruby/ruby/blob/b96a3a6fd2093e1dbea5491c002da515652dd347/gc.c#L14091>
|
||||
|
||||
== Original commit messages ==
|
||||
|
||||
This is a combination of 3 commits.
|
||||
This is the 1st commit message:
|
||||
~~~
|
||||
Rename GC_COMPACTION_SUPPORTED
|
||||
|
||||
Naming this macro GC_COMPACTION_SUPPORTED is misleading because it
|
||||
only checks whether compaction is supported at compile time.
|
||||
|
||||
[Bug #18829]
|
||||
~~~
|
||||
|
||||
This is the commit message #2:
|
||||
~~~
|
||||
Include runtime checks for compaction support
|
||||
|
||||
Commit 0c36ba53192c5a0d245c9b626e4346a32d7d144e changed GC compaction
|
||||
methods to not be implemented when not supported. However, that commit
|
||||
only does compile time checks (which currently only checks for WASM),
|
||||
but there are additional compaction support checks during run time.
|
||||
|
||||
This commit changes it so that GC compaction methods aren't defined
|
||||
during run time if the platform does not support GC compaction.
|
||||
|
||||
[Bug #18829]
|
||||
~~~
|
||||
|
||||
This is the commit message #3:
|
||||
~~~
|
||||
Suppress code unused unless GC_CAN_COMPILE_COMPACTION
|
||||
~~~
|
||||
---
|
||||
gc.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++------------
|
||||
1 file changed, 46 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/gc.c b/gc.c
|
||||
index 6a5c739cc4..a3e40d9aac 100644
|
||||
--- a/gc.c
|
||||
+++ b/gc.c
|
||||
@@ -4632,7 +4632,25 @@ gc_unprotect_pages(rb_objspace_t *objspace, rb_heap_t *heap)
|
||||
static void gc_update_references(rb_objspace_t * objspace, rb_heap_t *heap);
|
||||
static void invalidate_moved_page(rb_objspace_t *objspace, struct heap_page *page);
|
||||
|
||||
-static void read_barrier_handler(intptr_t address)
|
||||
+#ifndef GC_CAN_COMPILE_COMPACTION
|
||||
+#if defined(__wasi__) /* WebAssembly doesn't support signals */
|
||||
+# define GC_CAN_COMPILE_COMPACTION 0
|
||||
+#else
|
||||
+# define GC_CAN_COMPILE_COMPACTION 1
|
||||
+#endif
|
||||
+#endif
|
||||
+
|
||||
+#if defined(__MINGW32__) || defined(_WIN32)
|
||||
+# define GC_COMPACTION_SUPPORTED 1
|
||||
+#else
|
||||
+/* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for
|
||||
+ * the read barrier, so we must disable compaction. */
|
||||
+# define GC_COMPACTION_SUPPORTED (GC_CAN_COMPILE_COMPACTION && USE_MMAP_ALIGNED_ALLOC)
|
||||
+#endif
|
||||
+
|
||||
+#if GC_CAN_COMPILE_COMPACTION
|
||||
+static void
|
||||
+read_barrier_handler(uintptr_t address)
|
||||
{
|
||||
VALUE obj;
|
||||
rb_objspace_t * objspace = &rb_objspace;
|
||||
@@ -4651,6 +4669,7 @@ static void read_barrier_handler(intptr_t address)
|
||||
}
|
||||
RB_VM_LOCK_LEAVE();
|
||||
}
|
||||
+#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER old_handler;
|
||||
@@ -8562,6 +8581,8 @@ gc_start_internal(rb_execution_context_t *ec, VALUE self, VALUE full_mark, VALUE
|
||||
|
||||
/* For now, compact implies full mark / sweep, so ignore other flags */
|
||||
if (RTEST(compact)) {
|
||||
+ GC_ASSERT(GC_COMPACTION_SUPPORTED);
|
||||
+
|
||||
/* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for
|
||||
* the read barrier, so we must disable compaction. */
|
||||
#if !defined(__MINGW32__) && !defined(_WIN32)
|
||||
@@ -8732,7 +8753,7 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free)
|
||||
return (VALUE)src;
|
||||
}
|
||||
|
||||
-#if GC_COMPACTION_SUPPORTED
|
||||
+#if GC_CAN_COMPILE_COMPACTION
|
||||
static int
|
||||
compare_free_slots(const void *left, const void *right, void *dummy)
|
||||
{
|
||||
@@ -9412,7 +9433,7 @@ gc_update_references(rb_objspace_t * objspace, rb_heap_t *heap)
|
||||
|
||||
static VALUE type_sym(size_t type);
|
||||
|
||||
-#if GC_COMPACTION_SUPPORTED
|
||||
+#if GC_CAN_COMPILE_COMPACTION
|
||||
/*
|
||||
* call-seq:
|
||||
* GC.latest_compact_info -> {:considered=>{:T_CLASS=>11}, :moved=>{:T_CLASS=>11}}
|
||||
@@ -9453,7 +9474,7 @@ gc_compact_stats(VALUE self)
|
||||
# define gc_compact_stats rb_f_notimplement
|
||||
#endif
|
||||
|
||||
-#if GC_COMPACTION_SUPPORTED
|
||||
+#if GC_CAN_COMPILE_COMPACTION
|
||||
static void
|
||||
root_obj_check_moved_i(const char *category, VALUE obj, void *data)
|
||||
{
|
||||
@@ -9532,7 +9553,7 @@ gc_compact(VALUE self)
|
||||
# define gc_compact rb_f_notimplement
|
||||
#endif
|
||||
|
||||
-#if GC_COMPACTION_SUPPORTED
|
||||
+#if GC_CAN_COMPILE_COMPACTION
|
||||
/*
|
||||
* call-seq:
|
||||
* GC.verify_compaction_references(toward: nil, double_heap: false) -> hash
|
||||
@@ -10056,7 +10077,7 @@ gc_disable(rb_execution_context_t *ec, VALUE _)
|
||||
return rb_gc_disable();
|
||||
}
|
||||
|
||||
-#if GC_COMPACTION_SUPPORTED
|
||||
+#if GC_CAN_COMPILE_COMPACTION
|
||||
/*
|
||||
* call-seq:
|
||||
* GC.auto_compact = flag
|
||||
@@ -10077,6 +10098,7 @@ gc_set_auto_compact(VALUE _, VALUE v)
|
||||
rb_raise(rb_eNotImpError, "Automatic compaction isn't available on this platform");
|
||||
}
|
||||
#endif
|
||||
+ GC_ASSERT(GC_COMPACTION_SUPPORTED);
|
||||
|
||||
ruby_enable_autocompact = RTEST(v);
|
||||
return v;
|
||||
@@ -10085,7 +10107,8 @@ gc_set_auto_compact(VALUE _, VALUE v)
|
||||
# define gc_set_auto_compact rb_f_notimplement
|
||||
#endif
|
||||
|
||||
-#if GC_COMPACTION_SUPPORTED
|
||||
+
|
||||
+#if GC_CAN_COMPILE_COMPACTION
|
||||
/*
|
||||
* call-seq:
|
||||
* GC.auto_compact -> true or false
|
||||
@@ -12926,11 +12949,21 @@ 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_COMPACTION_SUPPORTED) {
|
||||
+ 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);
|
||||
+ }
|
||||
+ else {
|
||||
+ rb_define_singleton_method(rb_mGC, "compact", rb_f_notimplement, 0);
|
||||
+ rb_define_singleton_method(rb_mGC, "auto_compact", rb_f_notimplement, 0);
|
||||
+ rb_define_singleton_method(rb_mGC, "auto_compact=", rb_f_notimplement, 1);
|
||||
+ rb_define_singleton_method(rb_mGC, "latest_compact_info", rb_f_notimplement, 0);
|
||||
+ /* When !GC_COMPACTION_SUPPORTED, this method is not defined in gc.rb */
|
||||
+ rb_define_singleton_method(rb_mGC, "verify_compaction_references", rb_f_notimplement, -1);
|
||||
+ }
|
||||
|
||||
#if GC_DEBUG_STRESS_TO_CLASS
|
||||
rb_define_singleton_method(rb_mGC, "add_stress_to_class", rb_gcdebug_add_stress_to_class, -1);
|
||||
@@ -12954,6 +12987,7 @@ Init_GC(void)
|
||||
OPT(MALLOC_ALLOCATED_SIZE);
|
||||
OPT(MALLOC_ALLOCATED_SIZE_CHECK);
|
||||
OPT(GC_PROFILE_DETAIL_MEMORY);
|
||||
+ OPT(GC_COMPACTION_SUPPORTED);
|
||||
#undef OPT
|
||||
OBJ_FREEZE(opts);
|
||||
}
|
@ -0,0 +1,493 @@
|
||||
From 2b48aa5d9d7bfcf80ea23c352ceb10f0cf4e4ee0 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Dalessio <mike.dalessio@gmail.com>
|
||||
Date: Mon, 23 May 2022 15:40:22 -0400
|
||||
Subject: [PATCH 1/2] Move compaction-related methods into gc.c
|
||||
|
||||
These methods are removed from gc.rb and added to gc.c:
|
||||
|
||||
- GC.compact
|
||||
- GC.auto_compact
|
||||
- GC.auto_compact=
|
||||
- GC.latest_compact_info
|
||||
- GC.verify_compaction_references
|
||||
|
||||
This is a prefactor to allow setting these methods to
|
||||
`rb_f_notimplement` in a followup commit.
|
||||
---
|
||||
gc.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
|
||||
gc.rb | 68 ---------------------------------------
|
||||
2 files changed, 91 insertions(+), 78 deletions(-)
|
||||
|
||||
diff --git a/gc.c b/gc.c
|
||||
index b821310934..ef0e66ee46 100644
|
||||
--- a/gc.c
|
||||
+++ b/gc.c
|
||||
@@ -9410,8 +9410,20 @@ gc_update_references(rb_objspace_t * objspace, rb_heap_t *heap)
|
||||
|
||||
static VALUE type_sym(size_t type);
|
||||
|
||||
+/*
|
||||
+ * 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;
|
||||
@@ -9484,22 +9496,70 @@ 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.
|
||||
+ */
|
||||
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);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * 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();
|
||||
{
|
||||
@@ -9515,12 +9575,12 @@ 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);
|
||||
|
||||
- return gc_compact_stats(ec, self);
|
||||
+ return gc_compact_stats(self);
|
||||
}
|
||||
|
||||
VALUE
|
||||
@@ -9978,8 +10038,18 @@ gc_disable(rb_execution_context_t *ec, VALUE _)
|
||||
return rb_gc_disable();
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * 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. */
|
||||
@@ -9993,8 +10063,14 @@ gc_set_auto_compact(rb_execution_context_t *ec, VALUE _, VALUE v)
|
||||
return v;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * 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 ruby_enable_autocompact ? Qtrue : Qfalse;
|
||||
}
|
||||
@@ -12824,6 +12900,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/gc.rb b/gc.rb
|
||||
index 8a00b406ce..4a80e09443 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
|
||||
#
|
||||
@@ -183,53 +162,6 @@ def self.stat hash_or_key = nil
|
||||
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
|
||||
end
|
||||
|
||||
module ObjectSpace
|
||||
|
||||
From 5c73c78da0ffca162b2dad6f217ae0ec1565ad52 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Dalessio <mike.dalessio@gmail.com>
|
||||
Date: Mon, 23 May 2022 17:31:14 -0400
|
||||
Subject: [PATCH 2/2] Define unsupported GC compaction methods as
|
||||
rb_f_notimplement
|
||||
|
||||
Fixes [Bug #18779]
|
||||
|
||||
Define the following methods as `rb_f_notimplement` on unsupported
|
||||
platforms:
|
||||
|
||||
- GC.compact
|
||||
- GC.auto_compact
|
||||
- GC.auto_compact=
|
||||
- GC.latest_compact_info
|
||||
- GC.verify_compaction_references
|
||||
|
||||
This change allows users to call `GC.respond_to?(:compact)` to
|
||||
properly test for compaction support. Previously, it was necessary to
|
||||
invoke `GC.compact` or `GC.verify_compaction_references` and check if
|
||||
those methods raised `NotImplementedError` to determine if compaction
|
||||
was supported.
|
||||
|
||||
This follows the precedent set for other platform-specific
|
||||
methods. For example, in `process.c` for methods such as
|
||||
`Process.fork`, `Process.setpgid`, and `Process.getpriority`.
|
||||
---
|
||||
gc.c | 26 ++++++++++++++++
|
||||
test/ruby/test_gc_compact.rb | 58 ++++++++++++++++++++++++++----------
|
||||
2 files changed, 69 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/gc.c b/gc.c
|
||||
index ef0e66ee46..6a5c739cc4 100644
|
||||
--- a/gc.c
|
||||
+++ b/gc.c
|
||||
@@ -8732,6 +8732,7 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free)
|
||||
return (VALUE)src;
|
||||
}
|
||||
|
||||
+#if GC_COMPACTION_SUPPORTED
|
||||
static int
|
||||
compare_free_slots(const void *left, const void *right, void *dummy)
|
||||
{
|
||||
@@ -8775,6 +8776,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)
|
||||
@@ -9410,6 +9412,7 @@ gc_update_references(rb_objspace_t * objspace, rb_heap_t *heap)
|
||||
|
||||
static VALUE type_sym(size_t type);
|
||||
|
||||
+#if GC_COMPACTION_SUPPORTED
|
||||
/*
|
||||
* call-seq:
|
||||
* GC.latest_compact_info -> {:considered=>{:T_CLASS=>11}, :moved=>{:T_CLASS=>11}}
|
||||
@@ -9446,7 +9449,11 @@ gc_compact_stats(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)
|
||||
{
|
||||
@@ -9508,6 +9515,10 @@ heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data)
|
||||
*
|
||||
* 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(VALUE self)
|
||||
@@ -9517,7 +9528,11 @@ gc_compact(VALUE 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
|
||||
@@ -9582,6 +9597,9 @@ gc_verify_compaction_references(int argc, VALUE *argv, VALUE self)
|
||||
|
||||
return gc_compact_stats(self);
|
||||
}
|
||||
+#else
|
||||
+# define gc_verify_compaction_references rb_f_notimplement
|
||||
+#endif
|
||||
|
||||
VALUE
|
||||
rb_gc_start(void)
|
||||
@@ -10038,6 +10056,7 @@ gc_disable(rb_execution_context_t *ec, VALUE _)
|
||||
return rb_gc_disable();
|
||||
}
|
||||
|
||||
+#if GC_COMPACTION_SUPPORTED
|
||||
/*
|
||||
* call-seq:
|
||||
* GC.auto_compact = flag
|
||||
@@ -10062,7 +10081,11 @@ gc_set_auto_compact(VALUE _, VALUE v)
|
||||
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
|
||||
@@ -10074,6 +10097,9 @@ gc_get_auto_compact(VALUE _)
|
||||
{
|
||||
return ruby_enable_autocompact ? Qtrue : Qfalse;
|
||||
}
|
||||
+#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)
|
||||
diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb
|
||||
index f5cab55ba7..c9c96a7c9c 100644
|
||||
--- a/test/ruby/test_gc_compact.rb
|
||||
+++ b/test/ruby/test_gc_compact.rb
|
||||
@@ -4,14 +4,7 @@
|
||||
require 'etc'
|
||||
|
||||
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)
|
||||
|
||||
@@ -25,10 +18,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
|
||||
@@ -81,13 +83,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
|
@ -0,0 +1,336 @@
|
||||
--- ruby-3.0.7/gc.rbinc 2024-04-23 12:23:28.000000000 +0200
|
||||
+++ ruby/gc.rbinc 2025-02-27 13:20:54.803133890 +0100
|
||||
@@ -26,31 +26,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)%"PRIdPTR"; /* == gc_get_auto_compact */\n", (intptr_t)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)%"PRIdPTR"; /* == gc_set_auto_compact */\n", (intptr_t)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");
|
||||
@@ -134,57 +109,18 @@
|
||||
fprintf(f, " val = f(ec, self, argv[0]);\n");
|
||||
}
|
||||
|
||||
-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)%"PRIdPTR"; /* == gc_compact_stats */\n", (intptr_t)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)%"PRIdPTR"; /* == gc_compact */\n", (intptr_t)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)%"PRIdPTR"; /* == gc_verify_compaction_references */\n", (intptr_t)gc_verify_compaction_references);
|
||||
- fprintf(f, " val = f(ec, self, argv[0], argv[1]);\n");
|
||||
-}
|
||||
-
|
||||
void Init_builtin_gc(void)
|
||||
{
|
||||
// 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(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(-1, NULL, NULL, 0, 0),
|
||||
};
|
||||
|
||||
@@ -194,8 +130,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);
|
||||
@@ -203,9 +137,6 @@
|
||||
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);
|
||||
COMPILER_WARNING_POP
|
||||
|
||||
// load
|
||||
--- ruby-3.0.7/miniprelude.c 2024-04-23 12:23:28.000000000 +0200
|
||||
+++ ruby/miniprelude.c 2025-02-27 13:20:54.853135007 +0100
|
||||
@@ -320,10 +320,9 @@
|
||||
|
||||
static const char prelude_name2[] = "<internal:gc>";
|
||||
static const struct {
|
||||
- char L0[489]; /* 1..58 */
|
||||
- char L58[486]; /* 59..182 */
|
||||
- char L182[430]; /* 183..235 */
|
||||
- char L235[211]; /* 236..242 */
|
||||
+ char L0[502]; /* 1..70 */
|
||||
+ char L70[435]; /* 71..167 */
|
||||
+ char L167[211]; /* 168..174 */
|
||||
} prelude_code2 = {
|
||||
#line 1 "gc.rb"
|
||||
"\n"/* for gc.c */
|
||||
@@ -367,29 +366,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 */
|
||||
@@ -419,6 +395,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"
|
||||
@@ -510,70 +488,21 @@
|
||||
"\n"/* If the optional argument, hash, is given, */
|
||||
"\n"/* it is overwritten and returned. */
|
||||
"\n"/* This is intended to avoid probe effect. */
|
||||
-,
|
||||
-#line 183 "gc.rb"
|
||||
" def self.latest_gc_info hash_or_key = nil\n"
|
||||
" 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"
|
||||
"end\n"
|
||||
"\n"
|
||||
"module ObjectSpace\n"
|
||||
,
|
||||
-#line 236 "gc.rb"
|
||||
+#line 168 "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 577 "miniprelude.c"
|
||||
+#line 506 "miniprelude.c"
|
||||
};
|
||||
|
||||
static const char prelude_name3[] = "<internal:integer>";
|
||||
@@ -734,7 +663,7 @@
|
||||
" Primitive.cexpr! 'rb_int_zero_p(self)'\n"
|
||||
" end\n"
|
||||
"end\n"
|
||||
-#line 738 "miniprelude.c"
|
||||
+#line 667 "miniprelude.c"
|
||||
};
|
||||
|
||||
static const char prelude_name4[] = "<internal:io>";
|
||||
@@ -865,7 +794,7 @@
|
||||
" Primitive.io_write_nonblock(buf, exception)\n"
|
||||
" end\n"
|
||||
"end\n"
|
||||
-#line 869 "miniprelude.c"
|
||||
+#line 798 "miniprelude.c"
|
||||
};
|
||||
|
||||
static const char prelude_name5[] = "<internal:pack>";
|
||||
@@ -1156,7 +1085,7 @@
|
||||
" Primitive.pack_unpack1(fmt)\n"
|
||||
" end\n"
|
||||
"end\n"
|
||||
-#line 1160 "miniprelude.c"
|
||||
+#line 1089 "miniprelude.c"
|
||||
};
|
||||
|
||||
static const char prelude_name6[] = "<internal:trace_point>";
|
||||
@@ -1521,7 +1450,7 @@
|
||||
" Primitive.tracepoint_attr_instruction_sequence\n"
|
||||
" end\n"
|
||||
"end\n"
|
||||
-#line 1525 "miniprelude.c"
|
||||
+#line 1454 "miniprelude.c"
|
||||
};
|
||||
|
||||
static const char prelude_name7[] = "<internal:warning>";
|
||||
@@ -1582,7 +1511,7 @@
|
||||
" Primitive.rb_warn_m(msgs, uplevel, category)\n"
|
||||
" end\n"
|
||||
"end\n"
|
||||
-#line 1586 "miniprelude.c"
|
||||
+#line 1515 "miniprelude.c"
|
||||
};
|
||||
|
||||
static const char prelude_name8[] = "<internal:array>";
|
||||
@@ -1651,7 +1580,7 @@
|
||||
" Primitive.rb_ary_sample(random, n, ary)\n"
|
||||
" end\n"
|
||||
"end\n"
|
||||
-#line 1655 "miniprelude.c"
|
||||
+#line 1584 "miniprelude.c"
|
||||
};
|
||||
|
||||
static const char prelude_name9[] = "<internal:kernel>";
|
||||
@@ -1836,7 +1765,7 @@
|
||||
" Primitive.rb_f_float(arg, exception)\n"
|
||||
" end\n"
|
||||
"end\n"
|
||||
-#line 1840 "miniprelude.c"
|
||||
+#line 1769 "miniprelude.c"
|
||||
};
|
||||
|
||||
static const char prelude_name10[] = "<internal:ractor>";
|
||||
@@ -2703,7 +2632,7 @@
|
||||
" }\n"
|
||||
" end\n"
|
||||
"end\n"
|
||||
-#line 2707 "miniprelude.c"
|
||||
+#line 2636 "miniprelude.c"
|
||||
};
|
||||
|
||||
static const char prelude_name11[] = "<internal:prelude>";
|
||||
@@ -2733,7 +2662,7 @@
|
||||
"\n"
|
||||
" private :pp\n"
|
||||
"end\n"
|
||||
-#line 2737 "miniprelude.c"
|
||||
+#line 2666 "miniprelude.c"
|
||||
};
|
||||
|
||||
static const char prelude_name12[] = "<internal:gem_prelude>";
|
||||
@@ -2752,7 +2681,7 @@
|
||||
"rescue LoadError\n"
|
||||
" warn \"`did_you_mean' was not loaded.\"\n"
|
||||
"end if defined?(DidYouMean)\n"
|
||||
-#line 2756 "miniprelude.c"
|
||||
+#line 2685 "miniprelude.c"
|
||||
};
|
||||
|
||||
COMPILER_WARNING_POP
|
@ -0,0 +1,27 @@
|
||||
From fd8162a42ff3e4004b940030cfe34ce7a44a7e23 Mon Sep 17 00:00:00 2001
|
||||
From: Hiroshi SHIBATA <hsbt@ruby-lang.org>
|
||||
Date: Fri, 21 Feb 2025 16:01:17 +0900
|
||||
Subject: [PATCH] Use String#concat instead of String#+ for reducing cpu usage
|
||||
|
||||
Co-authored-by: "Yusuke Endoh" <mame@ruby-lang.org>
|
||||
---
|
||||
lib/cgi/cookie.rb | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/cgi/cookie.rb b/lib/cgi/cookie.rb
|
||||
index 1a9c1a82c1..7b8e761a94 100644
|
||||
--- a/lib/cgi/cookie.rb
|
||||
+++ b/lib/cgi/cookie.rb
|
||||
@@ -190,9 +190,10 @@ def self.parse(raw_cookie)
|
||||
values ||= ""
|
||||
values = values.split('&').collect{|v| CGI.unescape(v,@@accept_charset) }
|
||||
if cookies.has_key?(name)
|
||||
- values = cookies[name].value + values
|
||||
+ cookies[name].concat(values)
|
||||
+ else
|
||||
+ cookies[name] = Cookie.new(name, *values)
|
||||
end
|
||||
- cookies[name] = Cookie.new(name, *values)
|
||||
end
|
||||
|
||||
cookies
|
@ -0,0 +1,68 @@
|
||||
From 725d6f699f589d9b5454e189d33292027532984d Mon Sep 17 00:00:00 2001
|
||||
From: Hiroshi SHIBATA <hsbt@ruby-lang.org>
|
||||
Date: Fri, 21 Feb 2025 15:53:31 +0900
|
||||
Subject: [PATCH] Escape/unescape unclosed tags as well
|
||||
|
||||
Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
---
|
||||
lib/cgi/util.rb | 4 ++--
|
||||
test/cgi/test_cgi_util.rb | 18 ++++++++++++++++++
|
||||
2 files changed, 20 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/cgi/util.rb b/lib/cgi/util.rb
|
||||
index aab8b000cb..5ff8ba58eb 100644
|
||||
--- a/lib/cgi/util.rb
|
||||
+++ b/lib/cgi/util.rb
|
||||
@@ -140,7 +140,7 @@ def unescapeHTML(string)
|
||||
def escapeElement(string, *elements)
|
||||
elements = elements[0] if elements[0].kind_of?(Array)
|
||||
unless elements.empty?
|
||||
- string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do
|
||||
+ string.gsub(/<\/?(?:#{elements.join("|")})\b[^<>]*+>?/im) do
|
||||
CGI.escapeHTML($&)
|
||||
end
|
||||
else
|
||||
@@ -160,7 +160,7 @@ def escapeElement(string, *elements)
|
||||
def unescapeElement(string, *elements)
|
||||
elements = elements[0] if elements[0].kind_of?(Array)
|
||||
unless elements.empty?
|
||||
- string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do
|
||||
+ string.gsub(/<\/?(?:#{elements.join("|")})\b(?>[^&]+|&(?![gl]t;)\w+;)*(?:>)?/im) do
|
||||
unescapeHTML($&)
|
||||
end
|
||||
else
|
||||
diff --git a/test/cgi/test_cgi_util.rb b/test/cgi/test_cgi_util.rb
|
||||
index b7bb7b8eae..e93be474b3 100644
|
||||
--- a/test/cgi/test_cgi_util.rb
|
||||
+++ b/test/cgi/test_cgi_util.rb
|
||||
@@ -181,6 +181,14 @@ def test_cgi_escapeElement
|
||||
assert_equal("<BR><A HREF="url"></A>", escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"]))
|
||||
assert_equal("<BR><A HREF="url"></A>", escape_element('<BR><A HREF="url"></A>', "A", "IMG"))
|
||||
assert_equal("<BR><A HREF="url"></A>", escape_element('<BR><A HREF="url"></A>', ["A", "IMG"]))
|
||||
+
|
||||
+ assert_equal("<A <A HREF="url"></A>", escapeElement('<A <A HREF="url"></A>', "A", "IMG"))
|
||||
+ assert_equal("<A <A HREF="url"></A>", escapeElement('<A <A HREF="url"></A>', ["A", "IMG"]))
|
||||
+ assert_equal("<A <A HREF="url"></A>", escape_element('<A <A HREF="url"></A>', "A", "IMG"))
|
||||
+ assert_equal("<A <A HREF="url"></A>", escape_element('<A <A HREF="url"></A>', ["A", "IMG"]))
|
||||
+
|
||||
+ assert_equal("<A <A ", escapeElement('<A <A ', "A", "IMG"))
|
||||
+ assert_equal("<A <A ", escapeElement('<A <A ', ["A", "IMG"]))
|
||||
end
|
||||
|
||||
|
||||
@@ -189,5 +197,15 @@ def test_cgi_unescapeElement
|
||||
assert_equal('<BR><A HREF="url"></A>', unescapeElement(escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"]))
|
||||
assert_equal('<BR><A HREF="url"></A>', unescape_element(escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG"))
|
||||
assert_equal('<BR><A HREF="url"></A>', unescape_element(escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"]))
|
||||
+
|
||||
+ assert_equal('<A <A HREF="url"></A>', unescapeElement(escapeHTML('<A <A HREF="url"></A>'), "A", "IMG"))
|
||||
+ assert_equal('<A <A HREF="url"></A>', unescapeElement(escapeHTML('<A <A HREF="url"></A>'), ["A", "IMG"]))
|
||||
+ assert_equal('<A <A HREF="url"></A>', unescape_element(escapeHTML('<A <A HREF="url"></A>'), "A", "IMG"))
|
||||
+ assert_equal('<A <A HREF="url"></A>', unescape_element(escapeHTML('<A <A HREF="url"></A>'), ["A", "IMG"]))
|
||||
+
|
||||
+ assert_equal('<A <A ', unescapeElement(escapeHTML('<A <A '), "A", "IMG"))
|
||||
+ assert_equal('<A <A ', unescapeElement(escapeHTML('<A <A '), ["A", "IMG"]))
|
||||
+ assert_equal('<A <A ', unescape_element(escapeHTML('<A <A '), "A", "IMG"))
|
||||
+ assert_equal('<A <A ', unescape_element(escapeHTML('<A <A '), ["A", "IMG"]))
|
||||
end
|
||||
end
|
@ -0,0 +1,255 @@
|
||||
From 44dda22bf13d571067cfc5321ed72cad67256767 Mon Sep 17 00:00:00 2001
|
||||
From: st0012 <stan001212@gmail.com>
|
||||
Date: Sun, 16 Jan 2022 22:20:05 +0000
|
||||
Subject: [PATCH 1/3] Use require_relative to require lib files
|
||||
|
||||
1. `require` can mislead Ruby to load system irb's files and cause
|
||||
constant redefined warnings as other code loads the same module/class
|
||||
from lib folder.
|
||||
2. Most files already use `require_relative`.
|
||||
---
|
||||
lib/irb/color.rb | 2 +-
|
||||
lib/irb/color_printer.rb | 2 +-
|
||||
lib/irb/inspector.rb | 2 +-
|
||||
libexec/irb | 2 +-
|
||||
4 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/lib/irb/color.rb b/lib/irb/color.rb
|
||||
index cfbb3cc668..4f6258adf8 100644
|
||||
--- a/lib/irb/color.rb
|
||||
+++ b/lib/irb/color.rb
|
||||
@@ -1,7 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
require 'reline'
|
||||
require 'ripper'
|
||||
-require 'irb/ruby-lex'
|
||||
+require_relative 'ruby-lex'
|
||||
|
||||
module IRB # :nodoc:
|
||||
module Color
|
||||
diff --git a/lib/irb/color_printer.rb b/lib/irb/color_printer.rb
|
||||
index 30c6825750..78f0b51520 100644
|
||||
--- a/lib/irb/color_printer.rb
|
||||
+++ b/lib/irb/color_printer.rb
|
||||
@@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
require 'pp'
|
||||
-require 'irb/color'
|
||||
+require_relative 'color'
|
||||
|
||||
module IRB
|
||||
class ColorPrinter < ::PP
|
||||
diff --git a/lib/irb/inspector.rb b/lib/irb/inspector.rb
|
||||
index c2f3b605db..8c37c0f174 100644
|
||||
--- a/lib/irb/inspector.rb
|
||||
+++ b/lib/irb/inspector.rb
|
||||
@@ -114,7 +114,7 @@ def inspect_value(v)
|
||||
end
|
||||
result
|
||||
}
|
||||
- Inspector.def_inspector([true, :pp, :pretty_inspect], proc{require "irb/color_printer"}){|v|
|
||||
+ Inspector.def_inspector([true, :pp, :pretty_inspect], proc{require_relative "color_printer"}){|v|
|
||||
if IRB.conf[:MAIN_CONTEXT]&.use_colorize?
|
||||
IRB::ColorPrinter.pp(v, '').chomp
|
||||
else
|
||||
diff --git a/libexec/irb b/libexec/irb
|
||||
index c64ee85fbd..ffc97867d0 100755
|
||||
--- a/libexec/irb
|
||||
+++ b/libexec/irb
|
||||
@@ -6,6 +6,6 @@
|
||||
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
|
||||
#
|
||||
|
||||
-require "irb"
|
||||
+require_relative '../lib/irb'
|
||||
|
||||
IRB.start(__FILE__)
|
||||
|
||||
From e885a5bf9d20b45737746c5f2ae91059c09830cc Mon Sep 17 00:00:00 2001
|
||||
From: st0012 <stan001212@gmail.com>
|
||||
Date: Mon, 17 Jan 2022 11:45:16 +0000
|
||||
Subject: [PATCH 2/3] Use require_relative to load extensions/commands
|
||||
|
||||
---
|
||||
lib/irb/extend-command.rb | 48 +++++++++++++++++++--------------------
|
||||
1 file changed, 24 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/lib/irb/extend-command.rb b/lib/irb/extend-command.rb
|
||||
index 339e9e6084..d6fb19038d 100644
|
||||
--- a/lib/irb/extend-command.rb
|
||||
+++ b/lib/irb/extend-command.rb
|
||||
@@ -47,7 +47,7 @@ def irb_context
|
||||
|
||||
@EXTEND_COMMANDS = [
|
||||
[
|
||||
- :irb_current_working_workspace, :CurrentWorkingWorkspace, "irb/cmd/chws",
|
||||
+ :irb_current_working_workspace, :CurrentWorkingWorkspace, "cmd/chws",
|
||||
[:irb_print_working_workspace, OVERRIDE_ALL],
|
||||
[:irb_cwws, OVERRIDE_ALL],
|
||||
[:irb_pwws, OVERRIDE_ALL],
|
||||
@@ -59,7 +59,7 @@ def irb_context
|
||||
[:irb_pwb, OVERRIDE_ALL],
|
||||
],
|
||||
[
|
||||
- :irb_change_workspace, :ChangeWorkspace, "irb/cmd/chws",
|
||||
+ :irb_change_workspace, :ChangeWorkspace, "cmd/chws",
|
||||
[:irb_chws, OVERRIDE_ALL],
|
||||
[:irb_cws, OVERRIDE_ALL],
|
||||
[:chws, NO_OVERRIDE],
|
||||
@@ -70,13 +70,13 @@ def irb_context
|
||||
],
|
||||
|
||||
[
|
||||
- :irb_workspaces, :Workspaces, "irb/cmd/pushws",
|
||||
+ :irb_workspaces, :Workspaces, "cmd/pushws",
|
||||
[:workspaces, NO_OVERRIDE],
|
||||
[:irb_bindings, OVERRIDE_ALL],
|
||||
[:bindings, NO_OVERRIDE],
|
||||
],
|
||||
[
|
||||
- :irb_push_workspace, :PushWorkspace, "irb/cmd/pushws",
|
||||
+ :irb_push_workspace, :PushWorkspace, "cmd/pushws",
|
||||
[:irb_pushws, OVERRIDE_ALL],
|
||||
[:pushws, NO_OVERRIDE],
|
||||
[:irb_push_binding, OVERRIDE_ALL],
|
||||
@@ -84,7 +84,7 @@ def irb_context
|
||||
[:pushb, NO_OVERRIDE],
|
||||
],
|
||||
[
|
||||
- :irb_pop_workspace, :PopWorkspace, "irb/cmd/pushws",
|
||||
+ :irb_pop_workspace, :PopWorkspace, "cmd/pushws",
|
||||
[:irb_popws, OVERRIDE_ALL],
|
||||
[:popws, NO_OVERRIDE],
|
||||
[:irb_pop_binding, OVERRIDE_ALL],
|
||||
@@ -93,55 +93,55 @@ def irb_context
|
||||
],
|
||||
|
||||
[
|
||||
- :irb_load, :Load, "irb/cmd/load"],
|
||||
+ :irb_load, :Load, "cmd/load"],
|
||||
[
|
||||
- :irb_require, :Require, "irb/cmd/load"],
|
||||
+ :irb_require, :Require, "cmd/load"],
|
||||
[
|
||||
- :irb_source, :Source, "irb/cmd/load",
|
||||
+ :irb_source, :Source, "cmd/load",
|
||||
[:source, NO_OVERRIDE],
|
||||
],
|
||||
|
||||
[
|
||||
- :irb, :IrbCommand, "irb/cmd/subirb"],
|
||||
+ :irb, :IrbCommand, "cmd/subirb"],
|
||||
[
|
||||
- :irb_jobs, :Jobs, "irb/cmd/subirb",
|
||||
+ :irb_jobs, :Jobs, "cmd/subirb",
|
||||
[:jobs, NO_OVERRIDE],
|
||||
],
|
||||
[
|
||||
- :irb_fg, :Foreground, "irb/cmd/subirb",
|
||||
+ :irb_fg, :Foreground, "cmd/subirb",
|
||||
[:fg, NO_OVERRIDE],
|
||||
],
|
||||
[
|
||||
- :irb_kill, :Kill, "irb/cmd/subirb",
|
||||
+ :irb_kill, :Kill, "cmd/subirb",
|
||||
[:kill, OVERRIDE_PRIVATE_ONLY],
|
||||
],
|
||||
|
||||
[
|
||||
- :irb_help, :Help, "irb/cmd/help",
|
||||
+ :irb_help, :Help, "cmd/help",
|
||||
[:help, NO_OVERRIDE],
|
||||
],
|
||||
|
||||
[
|
||||
- :irb_info, :Info, "irb/cmd/info"
|
||||
+ :irb_info, :Info, "cmd/info"
|
||||
],
|
||||
|
||||
[
|
||||
- :irb_ls, :Ls, "irb/cmd/ls",
|
||||
+ :irb_ls, :Ls, "cmd/ls",
|
||||
[:ls, NO_OVERRIDE],
|
||||
],
|
||||
|
||||
[
|
||||
- :irb_measure, :Measure, "irb/cmd/measure",
|
||||
+ :irb_measure, :Measure, "cmd/measure",
|
||||
[:measure, NO_OVERRIDE],
|
||||
],
|
||||
|
||||
[
|
||||
- :irb_show_source, :ShowSource, "irb/cmd/show_source",
|
||||
+ :irb_show_source, :ShowSource, "cmd/show_source",
|
||||
[:show_source, NO_OVERRIDE],
|
||||
],
|
||||
|
||||
[
|
||||
- :irb_whereami, :Whereami, "irb/cmd/whereami",
|
||||
+ :irb_whereami, :Whereami, "cmd/whereami",
|
||||
[:whereami, NO_OVERRIDE],
|
||||
],
|
||||
|
||||
@@ -187,7 +187,7 @@ def self.def_extend_command(cmd_name, cmd_class, load_file = nil, *aliases)
|
||||
kwargs = ", **kwargs" if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.7.0"
|
||||
line = __LINE__; eval %[
|
||||
def #{cmd_name}(*opts#{kwargs}, &b)
|
||||
- require "#{load_file}"
|
||||
+ require_relative "#{load_file}"
|
||||
arity = ExtendCommand::#{cmd_class}.instance_method(:execute).arity
|
||||
args = (1..(arity < 0 ? ~arity : arity)).map {|i| "arg" + i.to_s }
|
||||
args << "*opts#{kwargs}" if arity < 0
|
||||
@@ -262,10 +262,10 @@ module ContextExtender
|
||||
CE = ContextExtender # :nodoc:
|
||||
|
||||
@EXTEND_COMMANDS = [
|
||||
- [:eval_history=, "irb/ext/history.rb"],
|
||||
- [:use_tracer=, "irb/ext/tracer.rb"],
|
||||
- [:use_loader=, "irb/ext/use-loader.rb"],
|
||||
- [:save_history=, "irb/ext/save-history.rb"],
|
||||
+ [:eval_history=, "ext/history.rb"],
|
||||
+ [:use_tracer=, "ext/tracer.rb"],
|
||||
+ [:use_loader=, "ext/use-loader.rb"],
|
||||
+ [:save_history=, "ext/save-history.rb"],
|
||||
]
|
||||
|
||||
# Installs the default context extensions as irb commands:
|
||||
@@ -288,7 +288,7 @@ def self.def_extend_command(cmd_name, load_file, *aliases)
|
||||
line = __LINE__; Context.module_eval %[
|
||||
def #{cmd_name}(*opts, &b)
|
||||
Context.module_eval {remove_method(:#{cmd_name})}
|
||||
- require "#{load_file}"
|
||||
+ require_relative "#{load_file}"
|
||||
__send__ :#{cmd_name}, *opts, &b
|
||||
end
|
||||
for ali in aliases
|
||||
|
||||
From 19431c7ccc23545b9e973d5e0993c20422f42796 Mon Sep 17 00:00:00 2001
|
||||
From: st0012 <stan001212@gmail.com>
|
||||
Date: Mon, 17 Jan 2022 15:17:18 +0000
|
||||
Subject: [PATCH 3/3] require_relative can't be used for default gems' exe
|
||||
files
|
||||
|
||||
The `exe` folder and `lib` folder of default gems don't locate under the
|
||||
same place. While `exe/irb` will be under the gem folder, `irb.rb` will be
|
||||
under `lib/ruby/VERSION/`.
|
||||
|
||||
So `require_relative` will make `irb` unuseable when shipped with Ruby.
|
||||
|
||||
Related discussion in the comments: https://github.com/ruby/irb/pull/335
|
||||
---
|
||||
libexec/irb | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libexec/irb b/libexec/irb
|
||||
index ffc97867d0..c64ee85fbd 100755
|
||||
--- a/libexec/irb
|
||||
+++ b/libexec/irb
|
||||
@@ -6,6 +6,6 @@
|
||||
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
|
||||
#
|
||||
|
||||
-require_relative '../lib/irb'
|
||||
+require "irb"
|
||||
|
||||
IRB.start(__FILE__)
|
@ -22,7 +22,7 @@
|
||||
%endif
|
||||
|
||||
|
||||
%global release 163
|
||||
%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
|
||||
@ -300,6 +300,45 @@ Patch70: ruby-3.3.1-Fix-test-session-reuse-but-expire.patch
|
||||
# Tests not included, this Ruby release does not include REXML tests.
|
||||
# https://github.com/ruby/rexml/commit/ce59f2eb1aeb371fe1643414f06618dbe031979f
|
||||
Patch71: rubygem-rexml-3.3.9-Fix-ReDoS-CVE-2024-49761.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
|
||||
Patch72: ruby-3.2.0-define-unsupported-gc-compaction-methods-as-rb_f_notimplement.patch
|
||||
# tar -Jxvf ./ruby-3.0.7.tar.xz
|
||||
# git clone https://github.com/ruby/ruby.git
|
||||
# cd ruby && git checkout v3_0_7
|
||||
# patch -p1 < ../ruby-3.1.0-Use-mmap-for-allocating-heap-pages-in-the-GC.patch
|
||||
# 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.0.7,ruby}/gc.rbinc > ruby-3.2.0-define-unsupported-gc-compaction-methods_generated-files.patch
|
||||
# diff -u {ruby-3.0.7,ruby}/miniprelude.c >> ruby-3.2.0-define-unsupported-gc-compaction-methods_generated-files.patch
|
||||
Patch73: ruby-3.2.0-define-unsupported-gc-compaction-methods_generated-files.patch
|
||||
# Define the GC compaction support macro at run time.
|
||||
# https://bugs.ruby-lang.org/issues/18829
|
||||
# https://github.com/ruby/ruby/pull/6019
|
||||
# https://github.com/ruby/ruby/commit/2c190863239bee3f54cfb74b16bb6ea4cae6ed20
|
||||
Patch74: ruby-3.2.0-Detect-compaction-support-during-runtime.patch
|
||||
# IRB, when used from within ruby code using simple `require 'irb'; binding.irb`,
|
||||
# a lot of warning messages about already initialized constants, similar to:
|
||||
# "/usr/share/ruby/irb/ruby-lex.rb:123: warning: already initialized constant RubyLex::ERROR_TOKENS"
|
||||
# "/usr/share/gems/gems/irb-1.3.5/lib/irb/ruby-lex.rb:123: warning: previous definition of ERROR_TOKENS was here"
|
||||
# are printed.
|
||||
# https://github.com/ruby/irb/pull/335
|
||||
# https://github.com/ruby/irb/commit/848d339f2e255f4b0dfc68568d818d4c3587b266
|
||||
# https://github.com/ruby/irb/pull/336
|
||||
# https://github.com/ruby/irb/commit/d5060f76687e3ff355583bfa5f073c67d558e2bd
|
||||
# https://github.com/ruby/irb/pull/338
|
||||
# https://github.com/ruby/irb/commit/99d3aa979dffece1fab06a7d5ebff4ae5da50aae
|
||||
Patch75: rubygem-irb-1.4.2-Fix-already-initialized-constant-messages-from-require-in-scripts.patch
|
||||
# Fix Denial of Service in CGI::Cookie.parse. (CVE-2025-27219)
|
||||
# https://github.com/ruby/cgi/commit/2f8ec73bb3eb71c4cf13e735f2d696603de2f34b
|
||||
Patch76: rubygem-cgi-0.3.5.1-Fix-DoS-in-CGI-Cookie-parse-CVE-2025-27219.patch
|
||||
# Fix ReDoS in CGI::Util#escapeElement. (CVE-2025-27220)
|
||||
# https://github.com/ruby/cgi/commit/bfa69e120df4e0131bb05df6c5e05c1dc982cd37
|
||||
Patch77: rubygem-cgi-0.3.5.1-Fix-ReDoS-in-CGI-CVE-2025-27220.patch
|
||||
|
||||
Requires: %{name}-libs%{?_isa} = %{version}-%{release}
|
||||
Suggests: rubypick
|
||||
@ -773,6 +812,12 @@ rm -rf ext/fiddle/libffi*
|
||||
%patch68 -p1
|
||||
%patch69 -p1
|
||||
%patch70 -p1
|
||||
%patch72 -p1
|
||||
%patch73 -p1
|
||||
%patch74 -p1
|
||||
%patch75 -p1
|
||||
%patch76 -p1
|
||||
%patch77 -p1
|
||||
|
||||
# Instead of adjusting patch's directory, use the following form where
|
||||
# we first enter the correct directory, this allows more general application
|
||||
@ -1555,6 +1600,18 @@ make runruby TESTRUN_SCRIPT=" \
|
||||
|
||||
|
||||
%changelog
|
||||
* Fri Apr 11 2025 Jarek Prokop <jprokop@redhat.com> - 3.0.7-165
|
||||
- Fix Denial of Service in CGI::Cookie.parse. (CVE-2025-27219)
|
||||
Resolves: RHEL-87183
|
||||
- Fix ReDoS in CGI::Util#escapeElement. (CVE-2025-27220)
|
||||
Resolves: RHEL-87184
|
||||
|
||||
* Thu Mar 06 2025 Jarek Prokop <jprokop@redhat.com> - 3.0.7-164
|
||||
- Undefine GC compaction methods on ppc64le.
|
||||
Resolves: RHEL-83135
|
||||
- Fix printing warnings when using IRB from a script.
|
||||
Resolves: RHEL-83137
|
||||
|
||||
* Tue Nov 26 2024 Jarek Prokop <jprokop@redhat.com> - 3.0.7-163
|
||||
- Fix REXML ReDoS vulnerability. (CVE-2024-49761)
|
||||
Resolves: RHEL-68521
|
||||
|
Loading…
Reference in New Issue
Block a user