Skip to content

Commit e3748b9

Browse files
committed
WIP
1 parent cec84ff commit e3748b9

1 file changed

Lines changed: 94 additions & 13 deletions

File tree

variable.c

Lines changed: 94 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1679,12 +1679,12 @@ rb_obj_init_too_complex(VALUE obj, st_table *table)
16791679
obj_transition_too_complex(obj, table);
16801680
}
16811681

1682+
void rb_obj_copy_fields_to_hash_table(VALUE obj, st_table *table);
1683+
16821684
// Copy all object fields, including ivars and internal object_id, etc
16831685
shape_id_t
16841686
rb_evict_fields_to_hash(VALUE obj)
16851687
{
1686-
void rb_obj_copy_fields_to_hash_table(VALUE obj, st_table *table);
1687-
16881688
RUBY_ASSERT(!rb_shape_obj_too_complex_p(obj));
16891689

16901690
st_table *table = st_init_numtable_with_size(RSHAPE_LEN(RBASIC_SHAPE_ID(obj)));
@@ -1900,18 +1900,99 @@ generic_ivar_set_too_complex_table(VALUE obj, void *data)
19001900
static void
19011901
generic_ivar_set(VALUE obj, ID id, VALUE val)
19021902
{
1903-
struct gen_fields_lookup_ensure_size fields_lookup = {
1904-
.obj = obj,
1905-
.id = id,
1906-
.resize = false,
1907-
};
1903+
const VALUE original_fields_obj = 0;
1904+
st_table *generic_tbl;
1905+
bool existing = true;
1906+
1907+
RB_VM_LOCKING() {
1908+
generic_tbl = generic_fields_tbl(obj, id, false);
1909+
st_lookup(generic_tbl, obj, (st_data_t *)&original_fields_obj);
1910+
}
1911+
1912+
VALUE fields_obj = original_fields_obj;
1913+
if (!fields_obj) {
1914+
fields_obj = rb_imemo_fields_new(rb_obj_class(obj), 1);
1915+
RUBY_ASSERT(RBASIC_SHAPE_ID(obj) == ROOT_SHAPE_ID);
1916+
}
1917+
1918+
shape_id_t current_shape_id = RBASIC_SHAPE_ID(fields_obj);
1919+
shape_id_t next_shape_id = current_shape_id;
1920+
1921+
if (UNLIKELY(rb_shape_too_complex_p(current_shape_id))) {
1922+
goto too_complex;
1923+
}
1924+
1925+
attr_index_t index;
1926+
if (!rb_shape_get_iv_index(current_shape_id, id, &index)) {
1927+
existing = false;
1928+
1929+
index = RSHAPE_LEN(current_shape_id);
1930+
if (index >= SHAPE_MAX_FIELDS) {
1931+
rb_raise(rb_eArgError, "too many instance variables");
1932+
}
1933+
1934+
next_shape_id = rb_shape_transition_add_ivar(fields_obj, id);
1935+
if (UNLIKELY(rb_shape_too_complex_p(next_shape_id))) {
1936+
attr_index_t current_len = RSHAPE_LEN(current_shape_id);
1937+
fields_obj = rb_imemo_fields_new_complex(rb_obj_class(obj), current_len + 1);
1938+
if (current_len) {
1939+
rb_obj_copy_fields_to_hash_table(original_fields_obj, rb_imemo_fields_complex_tbl(fields_obj));
1940+
RBASIC_SET_SHAPE_ID(fields_obj, next_shape_id);
1941+
}
1942+
goto too_complex;
1943+
}
1944+
1945+
attr_index_t next_capacity = RSHAPE_CAPACITY(next_shape_id);
1946+
attr_index_t current_capacity = RSHAPE_CAPACITY(current_shape_id);
1947+
1948+
if (next_capacity != current_capacity) {
1949+
RUBY_ASSERT(next_capacity > current_capacity);
1950+
1951+
fields_obj = rb_imemo_fields_new(rb_obj_class(obj), next_capacity);
1952+
if (original_fields_obj) {
1953+
MEMCPY(rb_imemo_fields_ptr(fields_obj), rb_imemo_fields_ptr(original_fields_obj), VALUE, RSHAPE_LEN(current_shape_id));
1954+
}
1955+
}
1956+
1957+
RUBY_ASSERT(RSHAPE(next_shape_id)->type == SHAPE_IVAR);
1958+
RUBY_ASSERT(index == (RSHAPE_LEN(next_shape_id) - 1));
1959+
}
1960+
1961+
VALUE *fields = rb_imemo_fields_ptr(fields_obj);
1962+
RB_OBJ_WRITE(fields_obj, &fields[index], val);
19081963

1909-
general_ivar_set(obj, id, val, &fields_lookup,
1910-
generic_ivar_set_shape_fields,
1911-
generic_ivar_set_shape_resize_fields,
1912-
generic_ivar_set_set_shape_id,
1913-
generic_ivar_set_transition_too_complex,
1914-
generic_ivar_set_too_complex_table);
1964+
if (!existing) {
1965+
RBASIC_SET_SHAPE_ID(fields_obj, next_shape_id);
1966+
}
1967+
1968+
if (fields_obj != original_fields_obj) {
1969+
RB_VM_LOCKING() {
1970+
st_insert(generic_tbl, obj, fields_obj);
1971+
}
1972+
if (!existing) {
1973+
RBASIC_SET_SHAPE_ID(obj, next_shape_id);
1974+
}
1975+
}
1976+
1977+
return;
1978+
1979+
too_complex:
1980+
{
1981+
st_table *table = rb_imemo_fields_complex_tbl(fields_obj);
1982+
existing = st_insert(table, (st_data_t)id, (st_data_t)val);
1983+
RB_OBJ_WRITTEN(fields_obj, Qundef, val);
1984+
1985+
if (fields_obj != original_fields_obj) {
1986+
RB_VM_LOCKING() {
1987+
st_insert(generic_tbl, obj, fields_obj);
1988+
}
1989+
if (!existing) {
1990+
RBASIC_SET_SHAPE_ID(obj, next_shape_id);
1991+
}
1992+
}
1993+
}
1994+
1995+
return;
19151996
}
19161997

19171998
static void

0 commit comments

Comments
 (0)