summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gc.c5
-rw-r--r--process.c2
-rw-r--r--test/ruby/test_process.rb12
3 files changed, 18 insertions, 1 deletions
diff --git a/gc.c b/gc.c
index 3c9adf3b00..ca018b7ae1 100644
--- a/gc.c
+++ b/gc.c
@@ -9596,6 +9596,11 @@ gc_set_candidate_object_i(void *vstart, void *vend, size_t stride, void *data)
case T_NONE:
case T_ZOMBIE:
break;
+ case T_STRING:
+ // precompute the string coderange. This both save time for when it will be
+ // eventually needed, and avoid mutating heap pages after a potential fork.
+ rb_enc_str_coderange(v);
+ // fall through
default:
if (!RVALUE_OLD_P(v) && !RVALUE_WB_UNPROTECTED(v)) {
RVALUE_AGE_SET_CANDIDATE(objspace, v);
diff --git a/process.c b/process.c
index 5761aea718..91f434f5e2 100644
--- a/process.c
+++ b/process.c
@@ -8555,6 +8555,7 @@ static VALUE rb_mProcID_Syscall;
* * Perform a major GC.
* * Compacts the heap.
* * Promotes all surviving objects to the old generation.
+ * * Precompute the coderange of all strings.
*/
static VALUE
@@ -8566,7 +8567,6 @@ proc_warmup(VALUE _)
return Qtrue;
}
-
/*
* Document-module: Process
*
diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb
index 6ca16733bb..9846f5e2db 100644
--- a/test/ruby/test_process.rb
+++ b/test/ruby/test_process.rb
@@ -2709,4 +2709,16 @@ EOS
assert_equal compact_count + 1, GC.stat(:compact_count)
end;
end
+
+ def test_warmup_precompute_string_coderange
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ require 'objspace'
+ begin;
+ obj = "a" * 12
+ obj.force_encoding(Encoding::BINARY)
+ assert_include(ObjectSpace.dump(obj), '"coderange":"unknown"')
+ Process.warmup
+ assert_include(ObjectSpace.dump(obj), '"coderange":"7bit"')
+ end;
+ end
end