get_next_shape_internal
should always return a shape
If it runs out of shapes, or new variations aren't allowed, it will return "too complex"
This commit is contained in:
parent
cfd7c1a276
commit
afae8df373
2
object.c
2
object.c
@ -292,7 +292,7 @@ rb_obj_copy_ivar(VALUE dest, VALUE obj)
|
|||||||
RUBY_ASSERT(BUILTIN_TYPE(dest) == BUILTIN_TYPE(obj));
|
RUBY_ASSERT(BUILTIN_TYPE(dest) == BUILTIN_TYPE(obj));
|
||||||
rb_shape_t * src_shape = rb_shape_get_shape(obj);
|
rb_shape_t * src_shape = rb_shape_get_shape(obj);
|
||||||
|
|
||||||
if (rb_shape_id(src_shape) == OBJ_TOO_COMPLEX_SHAPE_ID) {
|
if (rb_shape_obj_too_complex(obj)) {
|
||||||
st_table * table = rb_st_init_numtable_with_size(rb_st_table_size(ROBJECT_IV_HASH(obj)));
|
st_table * table = rb_st_init_numtable_with_size(rb_st_table_size(ROBJECT_IV_HASH(obj)));
|
||||||
|
|
||||||
rb_ivar_foreach(obj, rb_obj_evacuate_ivs_to_hash_table, (st_data_t)table);
|
rb_ivar_foreach(obj, rb_obj_evacuate_ivs_to_hash_table, (st_data_t)table);
|
||||||
|
14
shape.c
14
shape.c
@ -484,6 +484,9 @@ get_next_shape_internal(rb_shape_t * shape, ID id, enum shape_type shape_type, b
|
|||||||
rb_id_table_insert(shape->edges, id, (VALUE)new_shape);
|
rb_id_table_insert(shape->edges, id, (VALUE)new_shape);
|
||||||
res = new_shape;
|
res = new_shape;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
res = rb_shape_get_shape_by_id(OBJ_TOO_COMPLEX_SHAPE_ID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -496,6 +499,9 @@ get_next_shape_internal(rb_shape_t * shape, ID id, enum shape_type shape_type, b
|
|||||||
}
|
}
|
||||||
RB_VM_LOCK_LEAVE();
|
RB_VM_LOCK_LEAVE();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
res = rb_shape_get_shape_by_id(OBJ_TOO_COMPLEX_SHAPE_ID);
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,9 +617,6 @@ rb_shape_transition_shape_frozen(VALUE obj)
|
|||||||
bool dont_care;
|
bool dont_care;
|
||||||
next_shape = get_next_shape_internal(shape, (ID)id_frozen, SHAPE_FROZEN, &dont_care, true);
|
next_shape = get_next_shape_internal(shape, (ID)id_frozen, SHAPE_FROZEN, &dont_care, true);
|
||||||
|
|
||||||
if (!next_shape) {
|
|
||||||
next_shape = rb_shape_get_shape_by_id(OBJ_TOO_COMPLEX_SHAPE_ID);
|
|
||||||
}
|
|
||||||
RUBY_ASSERT(next_shape);
|
RUBY_ASSERT(next_shape);
|
||||||
return next_shape;
|
return next_shape;
|
||||||
}
|
}
|
||||||
@ -646,10 +649,6 @@ rb_shape_get_next(rb_shape_t* shape, VALUE obj, ID id)
|
|||||||
bool variation_created = false;
|
bool variation_created = false;
|
||||||
rb_shape_t * new_shape = get_next_shape_internal(shape, id, SHAPE_IVAR, &variation_created, allow_new_shape);
|
rb_shape_t * new_shape = get_next_shape_internal(shape, id, SHAPE_IVAR, &variation_created, allow_new_shape);
|
||||||
|
|
||||||
if (!new_shape) {
|
|
||||||
new_shape = rb_shape_get_shape_by_id(OBJ_TOO_COMPLEX_SHAPE_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we should update max_iv_count on the object's class
|
// Check if we should update max_iv_count on the object's class
|
||||||
if (BUILTIN_TYPE(obj) == T_OBJECT) {
|
if (BUILTIN_TYPE(obj) == T_OBJECT) {
|
||||||
VALUE klass = rb_obj_class(obj);
|
VALUE klass = rb_obj_class(obj);
|
||||||
@ -683,6 +682,7 @@ rb_shape_transition_shape_capa_create(rb_shape_t* shape, size_t new_capacity)
|
|||||||
ID edge_name = rb_make_temporary_id(new_capacity);
|
ID edge_name = rb_make_temporary_id(new_capacity);
|
||||||
bool dont_care;
|
bool dont_care;
|
||||||
rb_shape_t * new_shape = get_next_shape_internal(shape, edge_name, SHAPE_CAPACITY_CHANGE, &dont_care, true);
|
rb_shape_t * new_shape = get_next_shape_internal(shape, edge_name, SHAPE_CAPACITY_CHANGE, &dont_care, true);
|
||||||
|
RUBY_ASSERT(rb_shape_id(new_shape) != OBJ_TOO_COMPLEX_SHAPE_ID);
|
||||||
new_shape->capacity = (uint32_t)new_capacity;
|
new_shape->capacity = (uint32_t)new_capacity;
|
||||||
return new_shape;
|
return new_shape;
|
||||||
}
|
}
|
||||||
|
10
shape.h
10
shape.h
@ -178,7 +178,7 @@ ROBJECT_IV_CAPACITY(VALUE obj)
|
|||||||
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
||||||
// Asking for capacity doesn't make sense when the object is using
|
// Asking for capacity doesn't make sense when the object is using
|
||||||
// a hash table for storing instance variables
|
// a hash table for storing instance variables
|
||||||
RUBY_ASSERT(ROBJECT_SHAPE_ID(obj) != OBJ_TOO_COMPLEX_SHAPE_ID);
|
RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
|
||||||
return rb_shape_get_shape_by_id(ROBJECT_SHAPE_ID(obj))->capacity;
|
return rb_shape_get_shape_by_id(ROBJECT_SHAPE_ID(obj))->capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,7 +186,7 @@ static inline st_table *
|
|||||||
ROBJECT_IV_HASH(VALUE obj)
|
ROBJECT_IV_HASH(VALUE obj)
|
||||||
{
|
{
|
||||||
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
||||||
RUBY_ASSERT(ROBJECT_SHAPE_ID(obj) == OBJ_TOO_COMPLEX_SHAPE_ID);
|
RUBY_ASSERT(rb_shape_obj_too_complex(obj));
|
||||||
return (st_table *)ROBJECT(obj)->as.heap.ivptr;
|
return (st_table *)ROBJECT(obj)->as.heap.ivptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ static inline void
|
|||||||
ROBJECT_SET_IV_HASH(VALUE obj, const st_table *tbl)
|
ROBJECT_SET_IV_HASH(VALUE obj, const st_table *tbl)
|
||||||
{
|
{
|
||||||
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
||||||
RUBY_ASSERT(ROBJECT_SHAPE_ID(obj) == OBJ_TOO_COMPLEX_SHAPE_ID);
|
RUBY_ASSERT(rb_shape_obj_too_complex(obj));
|
||||||
ROBJECT(obj)->as.heap.ivptr = (VALUE *)tbl;
|
ROBJECT(obj)->as.heap.ivptr = (VALUE *)tbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,12 +203,12 @@ size_t rb_id_table_size(const struct rb_id_table *tbl);
|
|||||||
static inline uint32_t
|
static inline uint32_t
|
||||||
ROBJECT_IV_COUNT(VALUE obj)
|
ROBJECT_IV_COUNT(VALUE obj)
|
||||||
{
|
{
|
||||||
if (ROBJECT_SHAPE_ID(obj) == OBJ_TOO_COMPLEX_SHAPE_ID) {
|
if (rb_shape_obj_too_complex(obj)) {
|
||||||
return (uint32_t)rb_st_table_size(ROBJECT_IV_HASH(obj));
|
return (uint32_t)rb_st_table_size(ROBJECT_IV_HASH(obj));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
|
||||||
RUBY_ASSERT(ROBJECT_SHAPE_ID(obj) != OBJ_TOO_COMPLEX_SHAPE_ID);
|
RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
|
||||||
return rb_shape_get_shape_by_id(ROBJECT_SHAPE_ID(obj))->next_iv_index;
|
return rb_shape_get_shape_by_id(ROBJECT_SHAPE_ID(obj))->next_iv_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ static inline st_table *
|
|||||||
RCLASS_IV_HASH(VALUE obj)
|
RCLASS_IV_HASH(VALUE obj)
|
||||||
{
|
{
|
||||||
RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
|
RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
|
||||||
RUBY_ASSERT(RCLASS_SHAPE_ID(obj) == OBJ_TOO_COMPLEX_SHAPE_ID);
|
RUBY_ASSERT(rb_shape_obj_too_complex(obj));
|
||||||
return (st_table *)RCLASS_IVPTR(obj);
|
return (st_table *)RCLASS_IVPTR(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ static inline void
|
|||||||
RCLASS_SET_IV_HASH(VALUE obj, const st_table *tbl)
|
RCLASS_SET_IV_HASH(VALUE obj, const st_table *tbl)
|
||||||
{
|
{
|
||||||
RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
|
RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
|
||||||
RUBY_ASSERT(RCLASS_SHAPE_ID(obj) == OBJ_TOO_COMPLEX_SHAPE_ID);
|
RUBY_ASSERT(rb_shape_obj_too_complex(obj));
|
||||||
RCLASS_IVPTR(obj) = (VALUE *)tbl;
|
RCLASS_IVPTR(obj) = (VALUE *)tbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user