diff options
Diffstat (limited to 'shape.h')
-rw-r--r-- | shape.h | 73 |
1 files changed, 37 insertions, 36 deletions
@@ -4,41 +4,42 @@ #include "internal/gc.h" #if (SIZEOF_UINT64_T <= SIZEOF_VALUE) + #define SIZEOF_SHAPE_T 4 #define SHAPE_IN_BASIC_FLAGS 1 typedef uint32_t attr_index_t; +typedef uint32_t shape_id_t; +# define SHAPE_ID_NUM_BITS 32 + #else + #define SIZEOF_SHAPE_T 2 #define SHAPE_IN_BASIC_FLAGS 0 typedef uint16_t attr_index_t; -#endif - -#define MAX_IVARS (attr_index_t)(-1) - -#if SIZEOF_SHAPE_T == 4 -typedef uint32_t shape_id_t; -# define SHAPE_ID_NUM_BITS 32 -# define SHAPE_BUFFER_SIZE 0x80000 -#else typedef uint16_t shape_id_t; # define SHAPE_ID_NUM_BITS 16 -# define SHAPE_BUFFER_SIZE 0x8000 + #endif +typedef uint32_t redblack_id_t; + +#define MAX_IVARS (attr_index_t)(-1) + # define SHAPE_MASK (((uintptr_t)1 << SHAPE_ID_NUM_BITS) - 1) # define SHAPE_FLAG_MASK (((VALUE)-1) >> SHAPE_ID_NUM_BITS) # define SHAPE_FLAG_SHIFT ((SIZEOF_VALUE * 8) - SHAPE_ID_NUM_BITS) # define SHAPE_MAX_VARIATIONS 8 -# define SHAPE_MAX_NUM_IVS 80 -# define MAX_SHAPE_ID SHAPE_BUFFER_SIZE # define INVALID_SHAPE_ID SHAPE_MASK # define ROOT_SHAPE_ID 0x0 -# define SPECIAL_CONST_SHAPE_ID (SIZE_POOL_COUNT * 2) +# define SPECIAL_CONST_SHAPE_ID (ROOT_SHAPE_ID + 1) # define OBJ_TOO_COMPLEX_SHAPE_ID (SPECIAL_CONST_SHAPE_ID + 1) +# define FIRST_T_OBJECT_SHAPE_ID (OBJ_TOO_COMPLEX_SHAPE_ID + 1) + +typedef struct redblack_node redblack_node_t; struct rb_shape { struct rb_id_table * edges; // id_table from ID (ivar) to next shape @@ -48,16 +49,22 @@ struct rb_shape { uint8_t type; uint8_t size_pool_index; shape_id_t parent_id; + redblack_node_t * ancestor_index; }; typedef struct rb_shape rb_shape_t; +struct redblack_node { + ID key; + rb_shape_t * value; + redblack_id_t l; + redblack_id_t r; +}; + enum shape_type { SHAPE_ROOT, SHAPE_IVAR, SHAPE_FROZEN, - SHAPE_CAPACITY_CHANGE, - SHAPE_INITIAL_CAPACITY, SHAPE_T_OBJECT, SHAPE_OBJ_TOO_COMPLEX, }; @@ -67,6 +74,9 @@ typedef struct { rb_shape_t *shape_list; rb_shape_t *root_shape; shape_id_t next_shape_id; + + redblack_node_t *shape_cache; + unsigned int cache_size; } rb_shape_tree_t; RUBY_EXTERN rb_shape_tree_t *rb_shape_tree_ptr; @@ -141,18 +151,18 @@ int32_t rb_shape_id_offset(void); rb_shape_t * rb_shape_get_parent(rb_shape_t * shape); -rb_shape_t* rb_shape_get_shape_by_id(shape_id_t shape_id); -shape_id_t rb_shape_get_shape_id(VALUE obj); +RUBY_FUNC_EXPORTED rb_shape_t *rb_shape_get_shape_by_id(shape_id_t shape_id); +RUBY_FUNC_EXPORTED shape_id_t rb_shape_get_shape_id(VALUE obj); rb_shape_t * rb_shape_get_next_iv_shape(rb_shape_t * shape, ID id); bool rb_shape_get_iv_index(rb_shape_t * shape, ID id, attr_index_t * value); -bool rb_shape_obj_too_complex(VALUE obj); +bool rb_shape_get_iv_index_with_hint(shape_id_t shape_id, ID id, attr_index_t * value, shape_id_t *shape_id_hint); +RUBY_FUNC_EXPORTED bool rb_shape_obj_too_complex(VALUE obj); void rb_shape_set_shape(VALUE obj, rb_shape_t* shape); 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, VALUE * removed); -rb_shape_t * rb_shape_transition_shape_capa(rb_shape_t * shape, uint32_t new_capacity); +rb_shape_t* rb_shape_transition_shape_frozen(VALUE obj); +bool rb_shape_transition_shape_remove_ivar(VALUE obj, ID id, rb_shape_t *shape, VALUE * removed); rb_shape_t* rb_shape_get_next(rb_shape_t* shape, VALUE obj, ID id); rb_shape_t * rb_shape_rebuild_shape(rb_shape_t * initial_shape, rb_shape_t * dest_shape); @@ -163,7 +173,7 @@ ROBJECT_IV_CAPACITY(VALUE obj) RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT); // Asking for capacity doesn't make sense when the object is using // 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; } @@ -171,15 +181,15 @@ static inline st_table * ROBJECT_IV_HASH(VALUE obj) { 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; } static inline void -ROBJECT_SET_IV_HASH(VALUE obj, const struct rb_id_table *tbl) +ROBJECT_SET_IV_HASH(VALUE obj, const st_table *tbl) { 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; } @@ -188,12 +198,12 @@ size_t rb_id_table_size(const struct rb_id_table *tbl); static inline uint32_t 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)); } else { 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; } } @@ -204,20 +214,11 @@ RBASIC_IV_COUNT(VALUE obj) return rb_shape_get_shape_by_id(rb_shape_get_shape_id(obj))->next_iv_index; } -static inline uint32_t -RCLASS_IV_COUNT(VALUE obj) -{ - RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE)); - uint32_t ivc = rb_shape_get_shape_by_id(RCLASS_SHAPE_ID(obj))->next_iv_index; - return ivc; -} - rb_shape_t *rb_shape_traverse_from_new_root(rb_shape_t *initial_shape, rb_shape_t *orig_shape); bool rb_shape_set_shape_id(VALUE obj, shape_id_t shape_id); VALUE rb_obj_debug_shape(VALUE self, VALUE obj); -void rb_shape_set_too_complex(VALUE obj); // For ext/objspace RUBY_SYMBOL_EXPORT_BEGIN |