summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootstraptest/test_ractor.rb10
-rw-r--r--internal/string.h2
-rw-r--r--ractor.c2
-rw-r--r--string.c12
4 files changed, 23 insertions, 3 deletions
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb
index 2ae6602c82..a960d9d00f 100644
--- a/bootstraptest/test_ractor.rb
+++ b/bootstraptest/test_ractor.rb
@@ -1022,13 +1022,21 @@ assert_equal 'can not make a Proc shareable because it accesses outer variables
end
}
-# Ractor deep copies frozen objects
+# Ractor deep copies frozen objects (ary)
assert_equal '[true, false]', %q{
Ractor.new([[]].freeze) { |ary|
[ary.frozen?, ary.first.frozen? ]
}.take
}
+# Ractor deep copies frozen objects (str)
+assert_equal '[true, false]', %q{
+ s = String.new.instance_eval { @x = []; freeze}
+ Ractor.new(s) { |s|
+ [s.frozen?, s.instance_variable_get(:@x).frozen?]
+ }.take
+}
+
###
### Synchronization tests
###
diff --git a/internal/string.h b/internal/string.h
index 5c9f615ac5..091035d92c 100644
--- a/internal/string.h
+++ b/internal/string.h
@@ -42,6 +42,8 @@ VALUE rb_str_initialize(VALUE str, const char *ptr, long len, rb_encoding *enc);
size_t rb_str_memsize(VALUE);
char *rb_str_to_cstr(VALUE str);
const char *ruby_escaped_char(int c);
+void rb_str_make_independent(VALUE str);
+
static inline bool STR_EMBED_P(VALUE str);
static inline bool STR_SHARED_P(VALUE str);
static inline VALUE QUOTE(VALUE v);
diff --git a/ractor.c b/ractor.c
index c895aab980..fcdf5cf14a 100644
--- a/ractor.c
+++ b/ractor.c
@@ -2294,7 +2294,7 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
case T_MATCH:
break;
case T_STRING:
- rb_str_modify(obj);
+ rb_str_make_independent(obj);
break;
case T_OBJECT:
diff --git a/string.c b/string.c
index 086e97a770..2ce0fd2e05 100644
--- a/string.c
+++ b/string.c
@@ -214,6 +214,16 @@ str_make_independent(VALUE str)
str_make_independent_expand((str), len, 0L, termlen);
}
+static inline int str_dependent_p(VALUE str);
+
+void
+rb_str_make_independent(VALUE str)
+{
+ if (str_dependent_p(str)) {
+ str_make_independent(str);
+ }
+}
+
/* symbols for [up|down|swap]case/capitalize options */
static VALUE sym_ascii, sym_turkic, sym_lithuanian, sym_fold;
@@ -324,7 +334,7 @@ fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t data, int exist
str = str_new_frozen(rb_cString, str);
if (STR_SHARED_P(str)) { /* str should not be shared */
/* shared substring */
- str_make_independent(str);
+ str_make_independent(str);
assert(OBJ_FROZEN(str));
}
if (!BARE_STRING_P(str)) {