diff options
author | John Hawthorn <[email protected]> | 2019-06-25 09:01:57 -0700 |
---|---|---|
committer | Nobuyoshi Nakada <[email protected]> | 2019-06-26 15:01:48 +0900 |
commit | 04bc4c0662344238a556aa92f5f8f6d42586bab3 (patch) | |
tree | c3570330a2b7573f8d4aa42489c6cad2156cb4fa | |
parent | fe0ddf0e58e65ab3ae3d6e73382c3bebcd4541e5 (diff) |
Resize capacity for fstring
When a string is #frozen, it's capacity is resized to fit (if it is much
larger), since we know it will no longer be mutated.
> puts ObjectSpace.dump(String.new("a"*30, capacity: 1000))
{"type":"STRING", "class":"0x7feaf00b7bf0", "bytesize":30, "capacity":1000, "value":"...
> puts ObjectSpace.dump(String.new("a"*30, capacity: 1000).freeze)
{"type":"STRING", "class":"0x7feaf00b7bf0", "frozen":true, "bytesize":30, "value":"...
(ObjectSpace.dump doesn't show capacity if capacity is equal to bytesize)
Previously, if we dedup into an fstring, using String#-@, capacity would
not be reduced.
> puts ObjectSpace.dump(-String.new("a"*30, capacity: 1000))
{"type":"STRING", "class":"0x7feaf00b7bf0", "frozen":true, "fstring":true, "bytesize":30, "capacity":1000, "value":"...
This commit makes rb_fstring call rb_str_resize, the same as
rb_str_freeze does.
Closes: https://github.com/ruby/ruby/pull/2256
-rw-r--r-- | string.c | 3 | ||||
-rw-r--r-- | test/-ext-/string/test_capacity.rb | 19 |
2 files changed, 22 insertions, 0 deletions
@@ -321,6 +321,9 @@ rb_fstring(VALUE str) return str; } + if (!OBJ_FROZEN(str)) + rb_str_resize(str, RSTRING_LEN(str)); + fstr = register_fstring(str); if (!bare) { diff --git a/test/-ext-/string/test_capacity.rb b/test/-ext-/string/test_capacity.rb index 65444123a7..df59e76778 100644 --- a/test/-ext-/string/test_capacity.rb +++ b/test/-ext-/string/test_capacity.rb @@ -37,4 +37,23 @@ class Test_StringCapacity < Test::Unit::TestCase open(__FILE__) {|f|s = f.read(1024*1024)} assert_operator(capa(s), :<=, s.bytesize+4096) end + + def test_literal_capacity + s = "I am testing string literal capacity" + assert_equal(s.length, capa(s)) + end + + def test_capacity_frozen + s = String.new("I am testing", capacity: 1000) + s << "fstring capacity" + s.freeze + assert_equal(s.length, capa(s)) + end + + def test_capacity_fstring + s = String.new("I am testing", capacity: 1000) + s << "fstring capacity" + s = -s + assert_equal(s.length, capa(s)) + end end |