summaryrefslogtreecommitdiff
path: root/string.c
diff options
context:
space:
mode:
Diffstat (limited to 'string.c')
-rw-r--r--string.c103
1 files changed, 63 insertions, 40 deletions
diff --git a/string.c b/string.c
index e193539f4f..b8213ea085 100644
--- a/string.c
+++ b/string.c
@@ -1811,41 +1811,9 @@ ec_str_alloc_heap(struct rb_execution_context_struct *ec, VALUE klass)
}
static inline VALUE
-str_duplicate_setup(VALUE klass, VALUE str, VALUE dup)
+str_duplicate_setup_encoding(VALUE str, VALUE dup, VALUE flags)
{
- const VALUE flag_mask =
- ENC_CODERANGE_MASK | ENCODING_MASK |
- FL_FREEZE
- ;
- VALUE flags = FL_TEST_RAW(str, flag_mask);
int encidx = 0;
- if (STR_EMBED_P(str)) {
- long len = RSTRING_LEN(str);
-
- RUBY_ASSERT(STR_EMBED_P(dup));
- RUBY_ASSERT(str_embed_capa(dup) >= len + 1);
- MEMCPY(RSTRING(dup)->as.embed.ary, RSTRING(str)->as.embed.ary, char, len + 1);
- }
- else {
- VALUE root = str;
- if (FL_TEST_RAW(str, STR_SHARED)) {
- root = RSTRING(str)->as.heap.aux.shared;
- }
- else if (UNLIKELY(!(flags & FL_FREEZE))) {
- root = str = str_new_frozen(klass, str);
- flags = FL_TEST_RAW(str, flag_mask);
- }
- RUBY_ASSERT(!STR_SHARED_P(root));
- RUBY_ASSERT(RB_OBJ_FROZEN_RAW(root));
-
- RSTRING(dup)->as.heap.ptr = RSTRING_PTR(str);
- FL_SET(root, STR_SHARED_ROOT);
- RB_OBJ_WRITE(dup, &RSTRING(dup)->as.heap.aux.shared, root);
- flags |= RSTRING_NOEMBED | STR_SHARED;
- }
-
- STR_SET_LEN(dup, RSTRING_LEN(str));
-
if ((flags & ENCODING_MASK) == (ENCODING_INLINE_MAX<<ENCODING_SHIFT)) {
encidx = rb_enc_get_index(str);
flags &= ~ENCODING_MASK;
@@ -1855,18 +1823,54 @@ str_duplicate_setup(VALUE klass, VALUE str, VALUE dup)
return dup;
}
+static const VALUE flag_mask = ENC_CODERANGE_MASK | ENCODING_MASK | FL_FREEZE;
+
static inline VALUE
-ec_str_duplicate(struct rb_execution_context_struct *ec, VALUE klass, VALUE str)
+str_duplicate_setup_embed(VALUE klass, VALUE str, VALUE dup)
+{
+ VALUE flags = FL_TEST_RAW(str, flag_mask);
+ long len = RSTRING_LEN(str);
+
+ RUBY_ASSERT(STR_EMBED_P(dup));
+ RUBY_ASSERT(str_embed_capa(dup) >= len + 1);
+ MEMCPY(RSTRING(dup)->as.embed.ary, RSTRING(str)->as.embed.ary, char, len + 1);
+ STR_SET_LEN(dup, RSTRING_LEN(str));
+ return str_duplicate_setup_encoding(str, dup, flags);
+}
+
+static inline VALUE
+str_duplicate_setup_heap(VALUE klass, VALUE str, VALUE dup)
+{
+ VALUE flags = FL_TEST_RAW(str, flag_mask);
+ VALUE root = str;
+ if (FL_TEST_RAW(str, STR_SHARED)) {
+ root = RSTRING(str)->as.heap.aux.shared;
+ }
+ else if (UNLIKELY(!(flags & FL_FREEZE))) {
+ root = str = str_new_frozen(klass, str);
+ flags = FL_TEST_RAW(str, flag_mask);
+ }
+ RUBY_ASSERT(!STR_SHARED_P(root));
+ RUBY_ASSERT(RB_OBJ_FROZEN_RAW(root));
+
+ RSTRING(dup)->as.heap.ptr = RSTRING_PTR(str);
+ FL_SET(root, STR_SHARED_ROOT);
+ RB_OBJ_WRITE(dup, &RSTRING(dup)->as.heap.aux.shared, root);
+ flags |= RSTRING_NOEMBED | STR_SHARED;
+
+ STR_SET_LEN(dup, RSTRING_LEN(str));
+ return str_duplicate_setup_encoding(str, dup, flags);
+}
+
+static inline VALUE
+str_duplicate_setup(VALUE klass, VALUE str, VALUE dup)
{
- VALUE dup;
if (STR_EMBED_P(str)) {
- dup = ec_str_alloc_embed(ec, klass, RSTRING_LEN(str) + TERM_LEN(str));
+ return str_duplicate_setup_embed(klass, str, dup);
}
else {
- dup = ec_str_alloc_heap(ec, klass);
+ return str_duplicate_setup_heap(klass, str, dup);
}
-
- return str_duplicate_setup(klass, str, dup);
}
static inline VALUE
@@ -1912,13 +1916,32 @@ VALUE
rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str, bool chilled)
{
RUBY_DTRACE_CREATE_HOOK(STRING, RSTRING_LEN(str));
- VALUE new_str = ec_str_duplicate(ec, rb_cString, str);
+ VALUE new_str, klass = rb_cString;
+
+ if (!(chilled && RTEST(rb_ivar_defined(str, id_debug_created_info))) && STR_EMBED_P(str)) {
+ new_str = ec_str_alloc_embed(ec, klass, RSTRING_LEN(str) + TERM_LEN(str));
+ str_duplicate_setup_embed(klass, str, new_str);
+ }
+ else {
+ new_str = ec_str_alloc_heap(ec, klass);
+ str_duplicate_setup_heap(klass, str, new_str);
+ }
if (chilled) {
STR_CHILL_RAW(new_str);
}
return new_str;
}
+VALUE
+rb_str_with_debug_created_info(VALUE str, VALUE path, int line)
+{
+ VALUE debug_info = rb_ary_new_from_args(2, path, INT2FIX(line));
+ if (OBJ_FROZEN_RAW(str)) str = rb_str_dup(str);
+ rb_ivar_set(str, id_debug_created_info, rb_ary_freeze(debug_info));
+ STR_CHILL_RAW(str);
+ return rb_str_freeze(str);
+}
+
/*
*
* call-seq: