Avoid pinning storage_head in iseq_mark_and_move (#12880)

* Avoid pinning `storage_head` in `iseq_mark_and_move`

This refactor changes the behavior of `iseq_mark_and_move` to avoid
pinning the `storage_head`. Previously pinning was required because they
could be gc'd during `iseq_set_sequence` it would be possible to end
up with a half build array of instructions. However, in order to
implement a moving immix algorithm we can't pin these objects so this
rafactoring changes the code to mark and move. To accomplish this, it was
required to add `iseq_size`, `iseq_encoded`, and the `mark_bits` union
to the `iseq_compile_data` struct. In addition `iseq_compile_data` sets
a bool for whether there is a single or list of mark bits. While this
change is needed for moving immix, it should be better for Ruby's GC
as well.

* Don't allocate mark_offset_bits for one word

If only one word is needed, we don't need to allocate mark_offset_bits
and can instead directly write to it.

---------

Co-authored-by: Peter Zhu <peter@peterzhu.ca>
This commit is contained in:
Eileen M. Uchitelle 2025-03-17 10:42:48 -04:00 committed by GitHub
parent 8d6f153fba
commit c85dffeee2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
Notes: git 2025-03-17 14:43:06 +00:00
Merged-By: eileencodes <eileencodes@gmail.com>
3 changed files with 60 additions and 29 deletions

12
iseq.h
View file

@ -104,6 +104,16 @@ struct iseq_compile_data {
const VALUE err_info;
const VALUE catch_table_ary; /* Array */
/* Mirror fields from ISEQ_BODY so they are accessible during iseq setup */
unsigned int iseq_size;
VALUE *iseq_encoded; /* half-encoded iseq (insn addr and operands) */
bool is_single_mark_bit; /* identifies whether mark bits are single or a list */
union {
iseq_bits_t * list; /* Find references for GC */
iseq_bits_t single;
} mark_bits;
/* GC is not needed */
struct iseq_label_data *start_label;
struct iseq_label_data *end_label;
@ -194,7 +204,7 @@ VALUE *rb_iseq_original_iseq(const rb_iseq_t *iseq);
void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc,
VALUE locals, VALUE args,
VALUE exception, VALUE body);
void rb_iseq_mark_and_pin_insn_storage(struct iseq_compile_data_storage *arena);
void rb_iseq_mark_and_move_insn_storage(struct iseq_compile_data_storage *arena);
VALUE rb_iseq_load(VALUE data, VALUE parent, VALUE opt);
VALUE rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc);