From bbd5a5a81d8bf3c7368d308c10f5752be25af6d1 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Wed, 28 May 2025 09:34:37 +0200 Subject: [PATCH] vm_getivar: normalize shape_id to ignore frozen state Freezing an object changes its `shape_id` This is necessary so that `setivar` routines can use the `shape_id` as a cache key and save on checking the frozen status every time. However for `getivar` routines, this causes needless cache misses. By clearing that bit we increase hit rate in codepaths that see both frozen and mutable objects. --- shape.h | 9 +++++++++ vm_insnhelper.c | 3 +-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/shape.h b/shape.h index 4508646de2..ea736c385c 100644 --- a/shape.h +++ b/shape.h @@ -14,6 +14,7 @@ STATIC_ASSERT(shape_id_num_bits, SHAPE_ID_NUM_BITS == sizeof(shape_id_t) * CHAR_ #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_READ_ONLY_MASK (~SHAPE_ID_FL_FROZEN) typedef uint32_t redblack_id_t; @@ -110,6 +111,14 @@ RBASIC_SHAPE_ID(VALUE obj) #endif } +// Same as RBASIC_SHAPE_ID but with flags that have no impact +// on reads removed. e.g. Remove FL_FROZEN. +static inline shape_id_t +RBASIC_SHAPE_ID_FOR_READ(VALUE obj) +{ + return RBASIC_SHAPE_ID(obj) & SHAPE_ID_READ_ONLY_MASK; +} + static inline void RBASIC_SET_SHAPE_ID(VALUE obj, shape_id_t shape_id) { diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 78d845405a..ebc2345dbf 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1215,14 +1215,13 @@ vm_getivar(VALUE obj, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_call { #if OPT_IC_FOR_IVAR VALUE val = Qundef; - shape_id_t shape_id; VALUE * ivar_list; if (SPECIAL_CONST_P(obj)) { return default_value; } - shape_id = RBASIC_SHAPE_ID(obj); + shape_id_t shape_id = RBASIC_SHAPE_ID_FOR_READ(obj); switch (BUILTIN_TYPE(obj)) { case T_OBJECT: