string.c (rb_str_tmp_frozen_release): release embedded strings

Handle the embedded case first, since we may have an embedded
duplicate and non-embedded original string.

* string.c (rb_str_tmp_frozen_release): handled embedded strings
* test/ruby/test_io.rb (test_write_no_garbage): new test
  [ruby-core:78898] [Bug #13085]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57471 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
normal 2017-01-30 21:54:32 +00:00
Родитель fb3313bf2b
Коммит 5c988df0dd
2 изменённых файлов: 21 добавлений и 5 удалений

Просмотреть файл

@ -1150,7 +1150,11 @@ rb_str_tmp_frozen_release(VALUE orig, VALUE tmp)
if (RBASIC_CLASS(tmp) != 0)
return;
if (FL_TEST_RAW(orig, STR_SHARED) &&
if (STR_EMBED_P(tmp)) {
assert(OBJ_FROZEN_RAW(tmp));
rb_gc_force_recycle(tmp);
}
else if (FL_TEST_RAW(orig, STR_SHARED) &&
!FL_TEST_RAW(orig, STR_TMPLOCK|RUBY_FL_FREEZE)) {
VALUE shared = RSTRING(orig)->as.heap.aux.shared;
@ -1164,10 +1168,6 @@ rb_str_tmp_frozen_release(VALUE orig, VALUE tmp)
rb_gc_force_recycle(tmp);
}
}
else if (STR_EMBED_P(tmp)) {
assert(OBJ_FROZEN_RAW(tmp));
rb_gc_force_recycle(tmp);
}
}
static VALUE

Просмотреть файл

@ -3504,5 +3504,21 @@ __END__
end
end
end
def test_write_no_garbage
res = {}
ObjectSpace.count_objects(res) # creates strings on first call
[ 'foo'.b, '*' * 24 ].each do |buf|
with_pipe do |r, w|
before = ObjectSpace.count_objects(res)[:T_STRING]
n = w.write(buf)
after = ObjectSpace.count_objects(res)[:T_STRING]
assert_equal before, after,
'no strings left over after write [ruby-core:78898] [Bug #13085]'
assert_not_predicate buf, :frozen?, 'no inadvertant freeze'
assert_equal buf.bytesize, n, 'wrote expected size'
end
end
end
end
end