summaryrefslogtreecommitdiff
path: root/string.c
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2022-09-27 14:50:40 -0400
committerPeter Zhu <peter@peterzhu.ca>2022-09-28 09:05:23 -0400
commit6f8d17e43c7b9b3b8bf42df0ef1ca085080b65f0 (patch)
treedd949236ac18be9a9fc1282783a6dd0d257287e2 /string.c
parent247d598477ba0c2424d1e42fa4b5af0dfe1ae1d1 (diff)
downloadruby-6f8d17e43c7b9b3b8bf42df0ef1ca085080b65f0.tar.gz
Make string slices views rather than copies
Just like commit 1c16645 for arrays, this commit changes string slices to be a view rather than a copy even if it can be allocated through VWA.
Diffstat (limited to 'string.c')
-rw-r--r--string.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/string.c b/string.c
index b9c567cbe2..bdab6fa143 100644
--- a/string.c
+++ b/string.c
@@ -2802,18 +2802,20 @@ str_subseq(VALUE str, long beg, long len)
{
VALUE str2;
- if (!STR_EMBEDDABLE_P(len, TERM_LEN(str)) &&
- SHARABLE_SUBSTRING_P(beg, len, RSTRING_LEN(str))) {
- str2 = rb_str_new_shared(str);
+ const long rstring_embed_capa_max = ((sizeof(struct RString) - offsetof(struct RString, as.embed.ary)) / sizeof(char)) - 1;
+
+ if (!SHARABLE_SUBSTRING_P(beg, len, RSTRING_LEN(str)) ||
+ len <= rstring_embed_capa_max) {
+ str2 = rb_str_new(RSTRING_PTR(str) + beg, len);
+ RB_GC_GUARD(str);
+ }
+ else {
+ str2 = str_new_shared(rb_cString, str);
RSTRING(str2)->as.heap.ptr += beg;
if (RSTRING(str2)->as.heap.len > len) {
RSTRING(str2)->as.heap.len = len;
}
}
- else {
- str2 = rb_str_new(RSTRING_PTR(str) + beg, len);
- RB_GC_GUARD(str);
- }
return str2;
}