Make sure VM lock is not held when calling `load_transcoder_entry`, as
that causes deadlock inside ractors. `String#encode` now works inside
ractors, among others.
Atomic load the rb_encoding_list
Without this, wbcheck would sometimes hit a missing write barrier.
Co-authored-by: John Hawthorn <john.hawthorn@shopify.com>
Hold VM lock when iterating over global_enc_table.names
This st_table can be inserted into at runtime when autoloading
encodings.
minor optimization when calling Encoding.list
We don't need to delay the freeing of the fstr for the symbol if we store
the hash of the fstr in the dynamic symbol and we use compare-by-identity
for removing the dynamic symbol from the sym_set.
Hash#rehash checks whether the hash is iterating, and with VWA,
RHASH_ST_TABLE() always returns the same thing for the same
hash.
RHASH_ST_TABLE(VALUE h)
{
return (st_table *)((uintptr_t)h + sizeof(struct RHash));
}
So this check can never fail and raise an exception. Remove it.
The write barriers must be run after the st_update callback returns,
as the objects are not on the object until then and there may be
allocation when there is a new object inserted.
This is hard to reproduce, and I haven't seen an actual crash due to it,
but it is detected by wbcheck
RUBY_GC_LIBRARY=wbcheck WBCHECK_VERIFY_AFTER_WB=1 ./miniruby -e '("a".."zz").uniq.to_a'
WBCHECK ERROR: Missed write barrier detected!
Parent object: 0x720db01f99c0 (wb_protected: true)
rb_obj_info_dump: 0x0000720db01f99c0 T_HASH/[S] 18
Reference counts - snapshot: 32, writebarrier: 2, current: 36, missed: 2
Missing reference to: 0x716db02e3450
rb_obj_info_dump: 0x0000716db02e3450 T_STRING/String len: 1, capa: 15 "q"
Missing reference to: 0x716db02e3450
rb_obj_info_dump: 0x0000716db02e3450 T_STRING/String len: 1, capa: 15 "q"
A part of why this is hard to reproduce and it's unlikely to crash is
that the insertion only rarely allocates.
Co-authored-by: Luke Gruber <luke.gruber@shopify.com>
Prior to 49b306ecb9
the `optional_arg` passed from `rb_hash_update_block_i` to `tbl_update`
was a hash value (i.e. a VALUE). After that commit it changed to an
`update_call_args`.
If the block sets or changes the value, `tbl_update_modify` will set the
`arg.value` back to an actual value and we won't crash. But in the case
where the block returns the original value we end up calling
`RB_OBJ_WRITTEN` with the `update_call_args` which is not expected and
may crash.
`arg.value` appears to only be used to pass to `RB_OBJ_WRITTEN` (others
who need the `update_call_args` get it from `arg.arg`), so I don't think
it needs to be set to anything upfront. And `tbl_update_modify` will set
the `arg.value` in the cases we need the write barrier.
This was missed when adding core Set, because it's handled
implicitly for T_OBJECT.
Keep marshal compatibility between core Set and stdlib Set,
so you can unmarshal core Set with stdlib Set and vice versa.
Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>