diff options
author | Kasumi Hanazuki <[email protected]> | 2025-04-01 19:45:37 +0000 |
---|---|---|
committer | Jean Boussier <[email protected]> | 2025-06-17 07:57:02 +0200 |
commit | 8aac19d5987150cf5c45fee73c7a949ca472f488 () | |
tree | 9534d20eaf5accf6efbb99f9a36d71a96318c6f4 | |
parent | 4cc58c3a6fdb70de36f585e4ce8ad66b5db43938 (diff) |
io_buffer: Reimplement dcompact for IO::Buffer
The `source` field in IO::Buffer can have a String or an IO::Buffer object, if not nil. - When the `source` is a String object. The `base` field points to the memory location of the String content, which can be embedded in RSTRING, and in that case, GC compaction can move the memory region along with the String object. Thus, IO::Buffer needs to pin the `source` object to prevent `base` pointer from becoming invalid. - When the `source` is an IO::Buffer, then `base` is a pointer to a malloced or mmapped memory region, managed by the source IO::Buffer. In this case, we don't need to pin the source IO::Buffer object, since the referred memory region won't get moved by GC. Closes: [Bug #21210]
Notes: Merged: https://.com/ruby/ruby/pull/13033
-rw-r--r-- | io_buffer.c | 15 | ||||
-rw-r--r-- | test/ruby/test_io_buffer.rb | 13 |
2 files changed, 25 insertions, 3 deletions
@@ -273,10 +273,18 @@ io_buffer_free(struct rb_io_buffer *buffer) } static void -rb_io_buffer_type_mark(void *_buffer) { struct rb_io_buffer *buffer = _buffer; - rb_gc_mark(buffer->source); } static void @@ -303,9 +311,10 @@ rb_io_buffer_type_size(const void *_buffer) static const rb_data_type_t rb_io_buffer_type = { .wrap_struct_name = "IO::Buffer", .function = { - .dmark = rb_io_buffer_type_mark, .dfree = rb_io_buffer_type_free, .dsize = rb_io_buffer_type_size, }, .data = NULL, .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE, @@ -693,4 +693,17 @@ class TestIOBuffer < Test::Unit::TestCase buf.set_string('a', 0, 0) assert_predicate buf, :empty? end end |