@@ -12,16 +12,39 @@ STATIC_ASSERT(shape_id_num_bits, SHAPE_ID_NUM_BITS == sizeof(shape_id_t) * CHAR_
1212
1313#define SHAPE_BUFFER_SIZE (1 << SHAPE_ID_OFFSET_NUM_BITS)
1414#define SHAPE_ID_OFFSET_MASK (SHAPE_BUFFER_SIZE - 1)
15- #define SHAPE_ID_FLAGS_MASK (shape_id_t)(((1 << (SHAPE_ID_NUM_BITS - SHAPE_ID_OFFSET_NUM_BITS)) - 1) << SHAPE_ID_OFFSET_NUM_BITS)
16- #define SHAPE_ID_FL_FROZEN (SHAPE_FL_FROZEN << SHAPE_ID_OFFSET_NUM_BITS)
17- #define SHAPE_ID_FL_HAS_OBJECT_ID (SHAPE_FL_HAS_OBJECT_ID << SHAPE_ID_OFFSET_NUM_BITS)
18- #define SHAPE_ID_FL_TOO_COMPLEX (SHAPE_FL_TOO_COMPLEX << SHAPE_ID_OFFSET_NUM_BITS)
19- #define SHAPE_ID_FL_NON_CANONICAL_MASK (SHAPE_FL_NON_CANONICAL_MASK << SHAPE_ID_OFFSET_NUM_BITS)
2015
2116#define SHAPE_ID_HEAP_INDEX_BITS 3
22- #define SHAPE_ID_HEAP_INDEX_OFFSET (SHAPE_ID_NUM_BITS - SHAPE_ID_HEAP_INDEX_BITS)
2317#define SHAPE_ID_HEAP_INDEX_MAX ((1 << SHAPE_ID_HEAP_INDEX_BITS) - 1)
24- #define SHAPE_ID_HEAP_INDEX_MASK (SHAPE_ID_HEAP_INDEX_MAX << SHAPE_ID_HEAP_INDEX_OFFSET)
18+
19+ #define SHAPE_ID_FL_USHIFT (SHAPE_ID_OFFSET_NUM_BITS + SHAPE_ID_HEAP_INDEX_BITS)
20+ #define SHAPE_ID_HEAP_INDEX_OFFSET SHAPE_ID_FL_USHIFT
21+
22+ // shape_id_t bits:
23+ // 0-18 SHAPE_ID_OFFSET_MASK
24+ // index in rb_shape_tree.shape_list. Allow to access `rb_shape_t *`.
25+ // 19-21 SHAPE_ID_HEAP_INDEX_MASK
26+ // index in rb_shape_tree.capacities. Allow to access slot size.
27+ // 22 SHAPE_ID_FL_FROZEN
28+ // Whether the object is frozen or not.
29+ // 23 SHAPE_ID_FL_HAS_OBJECT_ID
30+ // Whether the object has an `SHAPE_OBJ_ID` transition.
31+ // 24 SHAPE_ID_FL_TOO_COMPLEX
32+ // The object is backed by a `st_table`.
33+
34+ enum shape_id_fl_type {
35+ #define RBIMPL_SHAPE_ID_FL(n) (1<<(SHAPE_ID_FL_USHIFT+n))
36+
37+ SHAPE_ID_HEAP_INDEX_MASK = RBIMPL_SHAPE_ID_FL (0 ) | RBIMPL_SHAPE_ID_FL (1 ) | RBIMPL_SHAPE_ID_FL (2 ),
38+
39+ SHAPE_ID_FL_FROZEN = RBIMPL_SHAPE_ID_FL (3 ),
40+ SHAPE_ID_FL_HAS_OBJECT_ID = RBIMPL_SHAPE_ID_FL (4 ),
41+ SHAPE_ID_FL_TOO_COMPLEX = RBIMPL_SHAPE_ID_FL (5 ),
42+
43+ SHAPE_ID_FL_NON_CANONICAL_MASK = SHAPE_ID_FL_FROZEN | SHAPE_ID_FL_HAS_OBJECT_ID ,
44+ SHAPE_ID_FLAGS_MASK = SHAPE_ID_HEAP_INDEX_MASK | SHAPE_ID_FL_NON_CANONICAL_MASK | SHAPE_ID_FL_TOO_COMPLEX ,
45+
46+ #undef RBIMPL_SHAPE_ID_FL
47+ };
2548
2649// This masks allows to check if a shape_id contains any ivar.
2750// It rely on ROOT_SHAPE_WITH_OBJ_ID==1.
@@ -229,9 +252,13 @@ rb_shape_heap_index(shape_id_t shape_id)
229252static inline shape_id_t
230253rb_shape_root (size_t heap_id )
231254{
232- shape_id_t heap_index = (shape_id_t )heap_id ;
255+ shape_id_t heap_index = (shape_id_t )(heap_id + 1 );
256+ shape_id_t heap_flags = heap_index << SHAPE_ID_HEAP_INDEX_OFFSET ;
257+
258+ RUBY_ASSERT ((heap_flags & SHAPE_ID_HEAP_INDEX_MASK ) == heap_flags );
259+ RUBY_ASSERT (rb_shape_heap_index (heap_flags ) == heap_index );
233260
234- return ROOT_SHAPE_ID | (( heap_index + 1 ) << SHAPE_ID_HEAP_INDEX_OFFSET ) ;
261+ return ROOT_SHAPE_ID | heap_flags ;
235262}
236263
237264static inline shape_id_t
0 commit comments