summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--string.c21
2 files changed, 25 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 759402f9a8..71615b1033 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Tue Oct 6 02:29:38 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_resurrect): optimize by short circuit to copy
+ hidden string without checking length, encoding and so on.
+
Mon Oct 5 23:08:17 2015 CHIKANAGA Tomoyuki <nagachika@ruby-lang.org>
* test/ruby/test_thread.rb (test_handle_interrupt_blocking): check if
diff --git a/string.c b/string.c
index d80f43d715..907b47c1a4 100644
--- a/string.c
+++ b/string.c
@@ -1250,11 +1250,30 @@ rb_str_dup(VALUE str)
VALUE
rb_str_resurrect(VALUE str)
{
+ VALUE dup;
+ VALUE flags = FL_TEST_RAW(str,
+ RSTRING_NOEMBED |
+ RSTRING_EMBED_LEN_MASK |
+ ENC_CODERANGE_MASK |
+ ENCODING_MASK |
+ FL_TAINT | FL_FREEZE);
+
if (RUBY_DTRACE_STRING_CREATE_ENABLED()) {
RUBY_DTRACE_STRING_CREATE(RSTRING_LEN(str),
rb_sourcefile(), rb_sourceline());
}
- return str_duplicate(rb_cString, str);
+ dup = str_alloc(rb_cString);
+ MEMCPY(RSTRING(dup)->as.ary, RSTRING(str)->as.ary, VALUE, 3);
+ if (flags & STR_NOEMBED) {
+ if (UNLIKELY(!(flags & FL_FREEZE))) {
+ str = str_new_frozen(rb_cString, str);
+ FL_SET_RAW(str, flags & FL_TAINT);
+ }
+ RB_OBJ_WRITE(dup, &RSTRING(dup)->as.heap.aux.shared, str);
+ flags |= STR_SHARED;
+ }
+ FL_SET_RAW(dup, flags & ~FL_FREEZE);
+ return dup;
}
/*