From 3be2acfafd3b3c6168e2266c7c6561d143d7ae5c Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 6 Jan 2023 09:09:18 -0500 Subject: Fix re-embedding of strings during compaction The reference updating code for strings is not re-embedding strings because the code is incorrectly wrapped inside of a `if (STR_SHARED_P(obj))` clause. Shared strings can't be re-embedded so this ends up being a no-op. This means that strings can be moved to a large size pool during compaction, but won't be re-embedded, which would waste the space. --- string.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'string.c') diff --git a/string.c b/string.c index fc5629638c..9fa482dbc7 100644 --- a/string.c +++ b/string.c @@ -312,14 +312,18 @@ rb_str_make_embedded(VALUE str) RUBY_ASSERT(rb_str_reembeddable_p(str)); RUBY_ASSERT(!STR_EMBED_P(str)); - char *buf = RSTRING_PTR(str); - long len = RSTRING_LEN(str); + char *buf = RSTRING(str)->as.heap.ptr; + long len = RSTRING(str)->as.heap.len; STR_SET_EMBED(str); STR_SET_EMBED_LEN(str, len); - memmove(RSTRING_PTR(str), buf, len); - ruby_xfree(buf); + if (len > 0) { + memcpy(RSTRING_PTR(str), buf, len); + ruby_xfree(buf); + } + + TERM_FILL(RSTRING(str)->as.embed.ary + len, TERM_LEN(str)); } void -- cgit v1.2.1