diff options
author | Nobuyoshi Nakada <[email protected]> | 2023-11-11 15:44:35 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <[email protected]> | 2023-11-11 16:58:14 +0900 |
commit | 2a442121d1404f9519d83ac72ac24c58a8389b15 (patch) | |
tree | bd5c85323c0204b9ff39d2c14a601bc954745f0c /compile.c | |
parent | 1fe2bc4b22dc262e3a84d1f722f556267a0e0172 (diff) |
Stabilize outer variable list
Sort outer variables by names to make dumped binary data stable.
Diffstat (limited to 'compile.c')
-rw-r--r-- | compile.c | 53 |
1 files changed, 43 insertions, 10 deletions
@@ -11997,15 +11997,36 @@ ibf_dump_ci_entries(struct ibf_dump *dump, const rb_iseq_t *iseq) return offset; } +struct outer_variable_pair { + ID id; + VALUE name; + VALUE val; +}; + +struct outer_variable_list { + size_t num; + struct outer_variable_pair pairs[1]; +}; + static enum rb_id_table_iterator_result -dump_outer_variable(ID id, VALUE val, void *dump) +store_outer_variable(ID id, VALUE val, void *dump) { - ibf_dump_write_small_value(dump, ibf_dump_id(dump, id)); - ibf_dump_write_small_value(dump, val); - + struct outer_variable_list *ovlist = dump; + struct outer_variable_pair *pair = &ovlist->pairs[ovlist->num++]; + pair->id = id; + pair->name = rb_id2str(id); + pair->val = val; return ID_TABLE_CONTINUE; } +static int +outer_variable_cmp(const void *a, const void *b, void *arg) +{ + const struct outer_variable_pair *ap = (const struct outer_variable_pair *)a; + const struct outer_variable_pair *bp = (const struct outer_variable_pair *)b; + return rb_str_cmp(ap->name, bp->name); +} + static ibf_offset_t ibf_dump_outer_variables(struct ibf_dump *dump, const rb_iseq_t *iseq) { @@ -12013,12 +12034,24 @@ ibf_dump_outer_variables(struct ibf_dump *dump, const rb_iseq_t *iseq) ibf_offset_t offset = ibf_dump_pos(dump); - if (ovs) { - ibf_dump_write_small_value(dump, (VALUE)rb_id_table_size(ovs)); - rb_id_table_foreach(ovs, dump_outer_variable, (void *)dump); - } - else { - ibf_dump_write_small_value(dump, (VALUE)0); + size_t size = ovs ? rb_id_table_size(ovs) : 0; + ibf_dump_write_small_value(dump, (VALUE)size); + if (size > 0) { + VALUE buff; + size_t buffsize = + rb_size_mul_add_or_raise(sizeof(struct outer_variable_pair), size, + offsetof(struct outer_variable_list, pairs), + rb_eArgError); + struct outer_variable_list *ovlist = RB_ALLOCV(buff, buffsize); + ovlist->num = 0; + rb_id_table_foreach(ovs, store_outer_variable, ovlist); + ruby_qsort(ovlist->pairs, size, sizeof(struct outer_variable_pair), outer_variable_cmp, NULL); + for (size_t i = 0; i < size; ++i) { + ID id = ovlist->pairs[i].id; + ID val = ovlist->pairs[i].val; + ibf_dump_write_small_value(dump, ibf_dump_id(dump, id)); + ibf_dump_write_small_value(dump, val); + } } return offset; |