summaryrefslogtreecommitdiff
path: root/shape.h
diff options
context:
space:
mode:
authorJean Boussier <jean.boussier@gmail.com>2025-06-24 16:09:52 +0200
committerJean Boussier <jean.boussier@gmail.com>2025-06-24 16:19:16 +0100
commitb2849876512c0df4759b589e3f8c2d6065bff2f7 (patch)
tree53134ae2a3b0b00d98d5dac80d93476c6f65bcf7 /shape.h
parent5bcc639b341291fe0584d11c6bdd1add29f40087 (diff)
Cleanup and document `shape_id_t` layout
Diffstat (limited to 'shape.h')
-rw-r--r--shape.h45
1 files changed, 36 insertions, 9 deletions
diff --git a/shape.h b/shape.h
index d7c80be9bc..69654cbc63 100644
--- a/shape.h
+++ b/shape.h
@@ -12,16 +12,39 @@ STATIC_ASSERT(shape_id_num_bits, SHAPE_ID_NUM_BITS == sizeof(shape_id_t) * CHAR_
#define SHAPE_BUFFER_SIZE (1 << SHAPE_ID_OFFSET_NUM_BITS)
#define SHAPE_ID_OFFSET_MASK (SHAPE_BUFFER_SIZE - 1)
-#define SHAPE_ID_FLAGS_MASK (shape_id_t)(((1 << (SHAPE_ID_NUM_BITS - SHAPE_ID_OFFSET_NUM_BITS)) - 1) << SHAPE_ID_OFFSET_NUM_BITS)
-#define SHAPE_ID_FL_FROZEN (SHAPE_FL_FROZEN << SHAPE_ID_OFFSET_NUM_BITS)
-#define SHAPE_ID_FL_HAS_OBJECT_ID (SHAPE_FL_HAS_OBJECT_ID << SHAPE_ID_OFFSET_NUM_BITS)
-#define SHAPE_ID_FL_TOO_COMPLEX (SHAPE_FL_TOO_COMPLEX << SHAPE_ID_OFFSET_NUM_BITS)
-#define SHAPE_ID_FL_NON_CANONICAL_MASK (SHAPE_FL_NON_CANONICAL_MASK << SHAPE_ID_OFFSET_NUM_BITS)
#define SHAPE_ID_HEAP_INDEX_BITS 3
-#define SHAPE_ID_HEAP_INDEX_OFFSET (SHAPE_ID_NUM_BITS - SHAPE_ID_HEAP_INDEX_BITS)
#define SHAPE_ID_HEAP_INDEX_MAX ((1 << SHAPE_ID_HEAP_INDEX_BITS) - 1)
-#define SHAPE_ID_HEAP_INDEX_MASK (SHAPE_ID_HEAP_INDEX_MAX << SHAPE_ID_HEAP_INDEX_OFFSET)
+
+#define SHAPE_ID_FL_USHIFT (SHAPE_ID_OFFSET_NUM_BITS + SHAPE_ID_HEAP_INDEX_BITS)
+#define SHAPE_ID_HEAP_INDEX_OFFSET SHAPE_ID_FL_USHIFT
+
+// shape_id_t bits:
+// 0-18 SHAPE_ID_OFFSET_MASK
+// index in rb_shape_tree.shape_list. Allow to access `rb_shape_t *`.
+// 19-21 SHAPE_ID_HEAP_INDEX_MASK
+// index in rb_shape_tree.capacities. Allow to access slot size.
+// 22 SHAPE_ID_FL_FROZEN
+// Whether the object is frozen or not.
+// 23 SHAPE_ID_FL_HAS_OBJECT_ID
+// Whether the object has an `SHAPE_OBJ_ID` transition.
+// 24 SHAPE_ID_FL_TOO_COMPLEX
+// The object is backed by a `st_table`.
+
+enum shape_id_fl_type {
+#define RBIMPL_SHAPE_ID_FL(n) (1<<(SHAPE_ID_FL_USHIFT+n))
+
+ SHAPE_ID_HEAP_INDEX_MASK = RBIMPL_SHAPE_ID_FL(0) | RBIMPL_SHAPE_ID_FL(1) | RBIMPL_SHAPE_ID_FL(2),
+
+ SHAPE_ID_FL_FROZEN = RBIMPL_SHAPE_ID_FL(3),
+ SHAPE_ID_FL_HAS_OBJECT_ID = RBIMPL_SHAPE_ID_FL(4),
+ SHAPE_ID_FL_TOO_COMPLEX = RBIMPL_SHAPE_ID_FL(5),
+
+ SHAPE_ID_FL_NON_CANONICAL_MASK = SHAPE_ID_FL_FROZEN | SHAPE_ID_FL_HAS_OBJECT_ID,
+ SHAPE_ID_FLAGS_MASK = SHAPE_ID_HEAP_INDEX_MASK | SHAPE_ID_FL_NON_CANONICAL_MASK | SHAPE_ID_FL_TOO_COMPLEX,
+
+#undef RBIMPL_SHAPE_ID_FL
+};
// This masks allows to check if a shape_id contains any ivar.
// It rely on ROOT_SHAPE_WITH_OBJ_ID==1.
@@ -229,9 +252,13 @@ rb_shape_heap_index(shape_id_t shape_id)
static inline shape_id_t
rb_shape_root(size_t heap_id)
{
- shape_id_t heap_index = (shape_id_t)heap_id;
+ shape_id_t heap_index = (shape_id_t)(heap_id + 1);
+ shape_id_t heap_flags = heap_index << SHAPE_ID_HEAP_INDEX_OFFSET;
+
+ RUBY_ASSERT((heap_flags & SHAPE_ID_HEAP_INDEX_MASK) == heap_flags);
+ RUBY_ASSERT(rb_shape_heap_index(heap_flags) == heap_index);
- return ROOT_SHAPE_ID | ((heap_index + 1) << SHAPE_ID_HEAP_INDEX_OFFSET);
+ return ROOT_SHAPE_ID | heap_flags;
}
static inline shape_id_t