Functions like String#each_line (rb_str_enumerate_lines) performs modification check after every yield (ENUM_ELEM). GC may be triggered in the block and the GC may move objects.
The function rb_str_enumerate_lines gets the pointer to the underlying buffer using RSTRING_PTR. This is not a problem with vanilla CRuby because the buffer is either embedded in the string and the string is pinned by the stack root, or the buffer is allocated by xmalloc which never moves. When using MMTk, however, the buffer may be a separate imemo:mmtk_strbuf. Currently, a pointer to the strbuf is not brought onto the stack, therefore it is not pinned, and GC may move it. Once that happens, str_mod_check will report "string modified" while the string is not actually modified (it is frozen), but just moved by the GC.
Functions like
String#each_line
(rb_str_enumerate_lines
) performs modification check after every yield (ENUM_ELEM
). GC may be triggered in the block and the GC may move objects.The function
rb_str_enumerate_lines
gets the pointer to the underlying buffer usingRSTRING_PTR
. This is not a problem with vanilla CRuby because the buffer is either embedded in the string and the string is pinned by the stack root, or the buffer is allocated byxmalloc
which never moves. When using MMTk, however, the buffer may be a separateimemo:mmtk_strbuf
. Currently, a pointer to the strbuf is not brought onto the stack, therefore it is not pinned, and GC may move it. Once that happens,str_mod_check
will report "string modified" while the string is not actually modified (it is frozen), but just moved by the GC.