diff options
author | Aaron Patterson <[email protected]> | 2022-12-05 16:48:47 -0800 |
---|---|---|
committer | Aaron Patterson <[email protected]> | 2022-12-07 09:57:11 -0800 |
commit | edc7af48acd12666a2945f30901d16b62a39f474 (patch) | |
tree | 7497e93afe9d84f970228cb515a5dc9092db1fbb /shape.h | |
parent | f725bf358a38b2d5dccb016a962f560baaee55c2 (diff) |
Stop transitioning to UNDEF when undefining an instance variable
Cases like this:
```ruby
obj = Object.new
loop do
obj.instance_variable_set(:@foo, 1)
obj.remove_instance_variable(:@foo)
end
```
can cause us to use many more shapes than we want (and even run out).
This commit changes the code such that when an instance variable is
removed, we'll walk up the shape tree, find the shape, then rebuild any
child nodes that happened to be below the "targetted for removal" IV.
This also requires moving any instance variables so that indexes derived
from the shape tree will work correctly.
Co-Authored-By: Jemma Issroff <[email protected]>
Co-authored-by: John Hawthorn <[email protected]>
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/6866
Diffstat (limited to 'shape.h')
-rw-r--r-- | shape.h | 4 |
1 files changed, 2 insertions, 2 deletions
@@ -51,7 +51,6 @@ enum shape_type { SHAPE_IVAR, SHAPE_FROZEN, SHAPE_CAPACITY_CHANGE, - SHAPE_IVAR_UNDEF, SHAPE_INITIAL_CAPACITY, SHAPE_T_OBJECT, }; @@ -125,6 +124,7 @@ bool rb_shape_root_shape_p(rb_shape_t* shape); rb_shape_t * rb_shape_get_root_shape(void); uint8_t rb_shape_id_num_bits(void); int32_t rb_shape_id_offset(void); +unsigned int rb_shape_depth(rb_shape_t * shape); rb_shape_t* rb_shape_get_shape_by_id_without_assertion(shape_id_t shape_id); rb_shape_t * rb_shape_get_parent(rb_shape_t * shape); @@ -136,7 +136,7 @@ shape_id_t rb_shape_get_shape_id(VALUE obj); rb_shape_t* rb_shape_get_shape(VALUE obj); int rb_shape_frozen_shape_p(rb_shape_t* shape); void rb_shape_transition_shape_frozen(VALUE obj); -void rb_shape_transition_shape_remove_ivar(VALUE obj, ID id, rb_shape_t *shape); +void rb_shape_transition_shape_remove_ivar(VALUE obj, ID id, rb_shape_t *shape, VALUE * removed); rb_shape_t * rb_shape_transition_shape_capa(rb_shape_t * shape, uint32_t new_capacity); rb_shape_t * rb_shape_get_next_iv_shape(rb_shape_t * shape, ID id); rb_shape_t* rb_shape_get_next(rb_shape_t* shape, VALUE obj, ID id); |