summaryrefslogtreecommitdiff
path: root/shape.h
diff options
context:
space:
mode:
Diffstat (limited to 'shape.h')
-rw-r--r--shape.h73
1 files changed, 37 insertions, 36 deletions
diff --git a/shape.h b/shape.h
index 025dfb4dd8..07eb2c979f 100644
--- a/shape.h
+++ b/shape.h
@@ -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