Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 92 additions & 31 deletions compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -2330,22 +2330,54 @@ static const struct st_hash_type cdhash_type = {
rb_iseq_cdhash_hash,
};

static VALUE
cdhash_new(size_t size)
{
VALUE cdhash = rb_imemo_cdhash_new(size, &cdhash_type);
RB_OBJ_SET_SHAREABLE(cdhash);
return cdhash;
}

static void
cdhash_aset(VALUE cdhash, VALUE key, VALUE val)
{
st_table *tbl = rb_imemo_cdhash_tbl(cdhash);
st_insert(tbl, key, val);
RB_OBJ_WRITTEN(cdhash, Qundef, key);
}

static void
cdhash_aset_if_missing(VALUE cdhash, VALUE key, VALUE val)
{
st_table *tbl = rb_imemo_cdhash_tbl(cdhash);
VALUE dontcare;
if (!st_lookup(tbl, key, &dontcare)) {
st_insert(tbl, key, val);
RB_OBJ_WRITTEN(cdhash, Qundef, key);
}
}

struct cdhash_set_label_struct {
VALUE hash;
int pos;
int len;
};

static int
cdhash_set_label_i(VALUE key, VALUE val, VALUE ptr)
cdhash_set_label_check_i(st_data_t key, st_data_t value, st_data_t argp, int error)
{
return ST_REPLACE;
}

static int
cdhash_set_label_replace_i(st_data_t *key, st_data_t *value, st_data_t ptr, int existing)
{
struct cdhash_set_label_struct *data = (struct cdhash_set_label_struct *)ptr;
LABEL *lobj = (LABEL *)(val & ~1);
rb_hash_aset(data->hash, key, INT2FIX(lobj->position - (data->pos+data->len)));
LABEL *lobj = (LABEL *)(*value & ~1);
*value = lobj->position - (data->pos+data->len);
return ST_CONTINUE;
}


static inline VALUE
get_ivar_ic_value(rb_iseq_t *iseq,ID id)
{
Expand Down Expand Up @@ -2729,10 +2761,8 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
data.hash = map;
data.pos = code_index;
data.len = len;
rb_hash_foreach(map, cdhash_set_label_i, (VALUE)&data);
st_foreach_with_replace(rb_imemo_cdhash_tbl(map), cdhash_set_label_check_i, cdhash_set_label_replace_i, (VALUE)&data);

freeze_hide_obj(map);
rb_ractor_make_shareable(map);
generated_iseq[code_index + 1 + j] = map;
ISEQ_MBITS_SET(mark_offset_bits, code_index + 1 + j);
RB_OBJ_WRITTEN(iseq, Qundef, map);
Expand Down Expand Up @@ -5526,8 +5556,8 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals,
if (UNDEF_P(lit)) {
only_special_literals = 0;
}
else if (NIL_P(rb_hash_lookup(literals, lit))) {
rb_hash_aset(literals, lit, (VALUE)(l1) | 1);
else {
cdhash_aset_if_missing(literals, lit, (VALUE)(l1));
}

if (nd_type_p(val, NODE_STR) || nd_type_p(val, NODE_FILE)) {
Expand Down Expand Up @@ -7069,7 +7099,7 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
DECL_ANCHOR(body_seq);
DECL_ANCHOR(cond_seq);
int only_special_literals = 1;
VALUE literals = rb_hash_new_with_size_and_type(0, 0, &cdhash_type);
VALUE literals = cdhash_new(0);
int line;
enum node_type type;
const NODE *line_node;
Expand Down Expand Up @@ -12166,7 +12196,7 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
case TS_CDHASH:
{
int i;
VALUE map = rb_hash_new_with_size_and_type(0, RARRAY_LEN(op)/2, &cdhash_type);
VALUE map = cdhash_new(RARRAY_LEN(op) / 2);

op = rb_to_array_type(op);
for (i=0; i<RARRAY_LEN(op); i+=2) {
Expand Down Expand Up @@ -13003,20 +13033,6 @@ ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq)
return offset;
}

static int
cdhash_copy_i(st_data_t key, st_data_t val, st_data_t arg)
{
rb_hash_aset((VALUE)arg, (VALUE)key, (VALUE)val);
return ST_CONTINUE;
}

static VALUE
cdhash_copy(VALUE dest, VALUE src)
{
rb_hash_stlike_foreach(src, cdhash_copy_i, dest);
return dest;
}

static VALUE *
ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecode_offset, ibf_offset_t bytecode_size, unsigned int iseq_size)
{
Expand Down Expand Up @@ -13070,10 +13086,7 @@ ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecod
case TS_CDHASH:
{
VALUE op = ibf_load_small_value(load, &reading_pos);
VALUE src = ibf_load_object(load, op);
VALUE v = rb_hash_new_with_size_and_type(0, RHASH_SIZE(src), &cdhash_type);
rb_hash_rehash(cdhash_copy(v, src));
RB_OBJ_SET_SHAREABLE(v);
VALUE v = ibf_load_object(load, op);

// Overwrite the existing hash in the object list. This
// is to keep the object alive during load time.
Expand Down Expand Up @@ -14355,6 +14368,54 @@ ibf_load_object_hash(const struct ibf_load *load, const struct ibf_object_header
return obj;
}

static int
ibf_dump_cdhash_i(st_data_t key, st_data_t val, st_data_t ptr)
{
struct ibf_dump *dump = (struct ibf_dump *)ptr;

VALUE key_index = ibf_dump_object(dump, (VALUE)key);

ibf_dump_write_small_value(dump, key_index);
ibf_dump_write_small_value(dump, val);
return ST_CONTINUE;
}

static void
ibf_dump_object_imemo(struct ibf_dump *dump, VALUE obj)
{
switch (imemo_type(obj)) {
case imemo_cdhash: {
st_table *tbl = rb_imemo_cdhash_tbl(obj);

long len = tbl->num_entries;
ibf_dump_write_small_value(dump, (VALUE)len);
if (len > 0) st_foreach(tbl, ibf_dump_cdhash_i, (VALUE)dump);
break;
}
default:
ibf_dump_object_unsupported(dump, obj);
break;
}
}

static VALUE
ibf_load_object_imemo(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
{
long len = (long)ibf_load_small_value(load, &offset);
VALUE obj = cdhash_new(len);

int i;
for (i = 0; i < len; i++) {
VALUE key_index = ibf_load_small_value(load, &offset);
VALUE val = ibf_load_small_value(load, &offset);

VALUE key = ibf_load_object(load, key_index);
cdhash_aset(obj, key, val);
}

return obj;
}

static void
ibf_dump_object_struct(struct ibf_dump *dump, VALUE obj)
{
Expand Down Expand Up @@ -14531,7 +14592,7 @@ static const ibf_dump_object_function dump_object_functions[RUBY_T_MASK+1] = {
ibf_dump_object_unsupported, /* 0x17 */
ibf_dump_object_unsupported, /* 0x18 */
ibf_dump_object_unsupported, /* 0x19 */
ibf_dump_object_unsupported, /* T_IMEMO 0x1a */
ibf_dump_object_imemo, /* T_IMEMO 0x1a */
ibf_dump_object_unsupported, /* T_NODE 0x1b */
ibf_dump_object_unsupported, /* T_ICLASS 0x1c */
ibf_dump_object_unsupported, /* T_ZOMBIE 0x1d */
Expand Down Expand Up @@ -14624,7 +14685,7 @@ static const ibf_load_object_function load_object_functions[RUBY_T_MASK+1] = {
ibf_load_object_unsupported, /* 0x17 */
ibf_load_object_unsupported, /* 0x18 */
ibf_load_object_unsupported, /* 0x19 */
ibf_load_object_unsupported, /* T_IMEMO 0x1a */
ibf_load_object_imemo, /* T_IMEMO 0x1a */
ibf_load_object_unsupported, /* T_NODE 0x1b */
ibf_load_object_unsupported, /* T_ICLASS 0x1c */
ibf_load_object_unsupported, /* T_ZOMBIE 0x1d */
Expand Down
1 change: 1 addition & 0 deletions debug_counter.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ RB_DEBUG_COUNTER(obj_imemo_callcache)
RB_DEBUG_COUNTER(obj_imemo_constcache)
RB_DEBUG_COUNTER(obj_imemo_fields)
RB_DEBUG_COUNTER(obj_imemo_subclasses)
RB_DEBUG_COUNTER(obj_imemo_cdhash)

RB_DEBUG_COUNTER(opt_new_hit)
RB_DEBUG_COUNTER(opt_new_miss)
Expand Down
1 change: 1 addition & 0 deletions ext/objspace/objspace.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ count_imemo_objects(int argc, VALUE *argv, VALUE self)
INIT_IMEMO_TYPE_ID(imemo_constcache);
INIT_IMEMO_TYPE_ID(imemo_fields);
INIT_IMEMO_TYPE_ID(imemo_subclasses);
INIT_IMEMO_TYPE_ID(imemo_cdhash);
#undef INIT_IMEMO_TYPE_ID
}

Expand Down
15 changes: 15 additions & 0 deletions gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1350,6 +1350,7 @@ rb_gc_imemo_needs_cleanup_p(VALUE obj)
case imemo_ment:
case imemo_iseq:
case imemo_callinfo:
case imemo_cdhash:
return true;

case imemo_subclasses:
Expand Down Expand Up @@ -3273,6 +3274,14 @@ rb_mark_tbl_no_pin(st_table *tbl)
gc_mark_tbl_no_pin(tbl);
}

void
rb_gc_mark_set_no_pin(st_table *tbl)
{
if (!tbl || tbl->num_entries == 0) return;

st_foreach(tbl, gc_mark_set_no_pin_i, 0);
}

static bool
gc_declarative_marking_p(const rb_data_type_t *type)
{
Expand Down Expand Up @@ -3918,6 +3927,12 @@ rb_gc_update_tbl_refs(st_table *ptr)
gc_update_table_refs(ptr);
}

void
rb_gc_update_set_refs(st_table *ptr)
{
gc_update_set_refs(ptr);
}

static void
gc_ref_update_hash(void *objspace, VALUE v)
{
Expand Down
38 changes: 38 additions & 0 deletions gc/gc.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,14 @@ gc_mark_tbl_no_pin_i(st_data_t key, st_data_t value, st_data_t data)
return ST_CONTINUE;
}

static int
gc_mark_set_no_pin_i(st_data_t key, st_data_t value, st_data_t data)
{
rb_gc_mark_movable((VALUE)key);

return ST_CONTINUE;
}

static int
hash_foreach_replace(st_data_t key, st_data_t value, st_data_t argp, int error)
{
Expand Down Expand Up @@ -232,6 +240,36 @@ gc_update_table_refs(st_table *tbl)
}
}

static int
rb_set_foreach_replace(st_data_t key, st_data_t value, st_data_t argp, int error)
{
if (rb_gc_location((VALUE)key) != (VALUE)key) {
return ST_REPLACE;
}

return ST_CONTINUE;
}

static int
rb_set_replace_ref(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
{
if (rb_gc_location((VALUE)*key) != (VALUE)*key) {
*key = rb_gc_location((VALUE)*key);
}

return ST_CONTINUE;
}

static void
gc_update_set_refs(st_table *tbl)
{
if (!tbl || tbl->num_entries == 0) return;

if (st_foreach_with_replace(tbl, rb_set_foreach_replace, rb_set_replace_ref, 0)) {
rb_raise(rb_eRuntimeError, "hash modified during iteration");
}
}

static inline size_t
xmalloc2_size(const size_t count, const size_t elsize)
{
Expand Down
8 changes: 0 additions & 8 deletions hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -1469,14 +1469,6 @@ rb_hash_new_with_size(st_index_t size)
return ret;
}

VALUE
rb_hash_new_with_size_and_type(VALUE klass, st_index_t size, const struct st_hash_type *type)
{
VALUE ret = hash_alloc_flags(klass, 0, Qnil, true);
hash_st_table_init(ret, type, size);
return ret;
}

VALUE
rb_hash_new_capa(long capa)
{
Expand Down
Loading