summaryrefslogtreecommitdiff
path: root/string.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-10-05 17:29:40 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-10-05 17:29:40 +0000
commit237332fceaf3e9f57d0be8295942d3347209ec75 (patch)
tree1c342bfb34217369462b41a88f119b842a2f45f2 /string.c
parent355a0d8af1170db6249cd1269257cfcf2fd36050 (diff)
string.c: optimize rb_str_resurrect
* string.c (rb_str_resurrect): optimize by short circuit to copy hidden string without checking length, encoding and so on. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52048 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'string.c')
-rw-r--r--string.c21
1 files changed, 20 insertions, 1 deletions
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;
}
/*