The following falcon source: <https://github.com/socketry/falcon/blob/v0.42.3/lib/falcon/command/serve.rb#L153-L155> contains the following snippet: ~~~ if GC.respond_to?(:compact) GC.compact end ~~~ The `if` guard for this feature is recommended from documentation since Ruby >= 3.2: <https://docs.ruby-lang.org/en/3.2/GC.html#method-c-compact>: ``` To test whether GC compaction is supported, use the idiom: ~~~ GC.respond_to?(:compact) ~~~ ``` Gems make use of this idiom in various situations. However on Ruby 3.0 without this patch the `GC.respond_to?` method will return true for `GC.compact` and compaction related methods even though an attempt to call them will raise "NotImplementedError" exception. We observe this behavior due to the methods being implemented and the NotImplementedError is not returned because methods are not implemented, but because it is a runtime behavior from inside the called methods. The applied patchset undefines the methods in C code to ensure even the `GC.respond_to?` will return false and accomodate libraries that call `GC.compact` like falcon does: <https://github.com/socketry/falcon/blob/v0.42.3/lib/falcon/command/serve.rb#L153-L155> The methods are undefined on build time on affected platforms that do not support compaction. Currently this is only affecting ppc64le. The important portion of the patch undefines the `GC.compact` and other methods, so we can expect the following on ppc64le architecture: Before: ~~~ $ ruby -e 'p GC.respond_to? :compact' true ~~~ After: ~~~ $ ruby -e 'p GC.respond_to? :compact' false ~~~ As long as Ruby gems guard the call to `GC.compact` correctly, there should no longer be a situation where GC reports compaction methods as implemented even though it will throw an exception when trying to use the methods. Most importantly, this is only an issue with ppc64le. The other architectures such as x86_64, aarch64, s390x should continue to be able to compact. This is guarded on compile-time. However the patches touch the source for pre-generated files. Mainly meaning the file `gc.rb` that is the source for the `gc.rbinc` and `miniprelude.c` need to be re-generated. The files use Ruby to generate the C counterparts. To prevent cyclic dependency, they are re-generated and patches are created against the old version. The approach to regenerate the files for 3.0 is the same as for 3.1 with the exception of also having to first patch with the file `ruby-3.1.0-Use-mmap-for-allocating-heap-pages-in-the-GC.patch`, since the subsequent patches are made on top of that patch. The mmap patch changes parts of gc.c, that the required patch also changes, so it had to be backported on top of that patch. The sequence of actions is as follows: ~~~ 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 ~~~ Firstly we unpact the upstream tar archive, which creates `ruby-3.0.7` directory. Then we clone the upstream git repository and check out the Ruby version tag that is source for the tar archive which creates `ruby` repository. The `ruby-3.0.7` directory contains the pre-generated files we will use as the original for the patch. In the `ruby` repository we apply the patches mentioned in the code snippet. Then, generate configure script with autogen.sh, and we create the gc.rbinc and miniprelude.c files that are generated. Then create the patch for the generated files. `diff` is used as the generated files are not tracked via git in upstream, and the diff is executed against the expanded upstream tar archive that does not ship a git repository with it. While it would be possible to `git add` the files before patching them, this ensures that the files are applicable without a problem on top of the archive. This commit is partially backported from Ruby 3.1's Fedora counterparts:b7b5473796
ca94aff023
649a6e3083
instead of re-doing the entire patchset from 3.2 branch back to 3.0. There is less disruption in GC related code when comparing 3.0 to 3.1 than there is 3.1 to 3.2. Therefore the upstream sources for the patches were first applied in the Ruby upstream git repository on top of tag v3_1_2. Namely, the following is the patch source: https://github.com/ruby/ruby/pull/59340de1495f35
0c36ba5319
available in Fedora as part of:649a6e3083
The version of Ruby that is the version when the mentioned Fedora commits were introduced. And then cherry picked on top of patch "ruby-3.1.0-Use-mmap-for-allocating-heap-pages-in-the-GC.patch" applied in v3_0_7 tag that is present here in downstream as the difference brought by the patch is significant enough to disrupt patch application. Git allows easier resolution of the patches here. In short, 1. Take the upstream compaction patches, cherry-pick them on top of v3_1_2 so that the changes are present in the git tree, as they have not been backported to 3.1 upstream. 2. Apply the "ruby-3.1.0-Use-mmap-for-allocating-heap-pages-in-the-GC.patch" on top of v3_0_7. 3. Cherry pick the 3.1 patches to v3_0_7 and resolve differences. There might have been a few sections where git marked changes from both patches as a conflict to resolve. I preferred the approach where, despite the checks introduced from the 3.1 branch patches should be enough to guard against bad behavior around compaction, the "mmap" patch's checks are retained for safety. One of the reasons are that the checks are also present outside the compact methods in other parts of `gc.c` code. References for the specific Fedora patches:b7b5473796
649a6e3083
<b7b5473796
> <649a6e3083
> Uptream bug: <https://bugs.ruby-lang.org/issues/18779> Upstream PR: <https://github.com/ruby/ruby/pull/5934>ca94aff023
<ca94aff023
> Related upstream issue: <https://bugs.ruby-lang.org/issues/18829> <https://github.com/ruby/ruby/pull/6019> <2c19086323
> Resolves: RHEL-83136
337 lines
13 KiB
Diff
337 lines
13 KiB
Diff
--- 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
|