Skip to content

Commit cac5f1f

Browse files
committed
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.
1 parent a483cdd commit cac5f1f

4 files changed

Lines changed: 16 additions & 3 deletions

File tree

id_table.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ managed_id_table_dup_i(ID id, VALUE val, void *data)
381381
VALUE
382382
rb_managed_id_table_dup(VALUE old_table)
383383
{
384+
RUBY_ASSERT(RB_TYPE_P(old_table, T_DATA));
384385
RUBY_ASSERT(rb_typeddata_inherited_p(RTYPEDDATA_TYPE(old_table), &managed_id_table_type));
385386

386387
struct rb_id_table *new_tbl;
@@ -394,6 +395,7 @@ rb_managed_id_table_dup(VALUE old_table)
394395
int
395396
rb_managed_id_table_lookup(VALUE table, ID id, VALUE *valp)
396397
{
398+
RUBY_ASSERT(RB_TYPE_P(table, T_DATA));
397399
RUBY_ASSERT(rb_typeddata_inherited_p(RTYPEDDATA_TYPE(table), &managed_id_table_type));
398400

399401
return rb_id_table_lookup(RTYPEDDATA_GET_DATA(table), id, valp);
@@ -402,6 +404,7 @@ rb_managed_id_table_lookup(VALUE table, ID id, VALUE *valp)
402404
int
403405
rb_managed_id_table_insert(VALUE table, ID id, VALUE val)
404406
{
407+
RUBY_ASSERT(RB_TYPE_P(table, T_DATA));
405408
RUBY_ASSERT(rb_typeddata_inherited_p(RTYPEDDATA_TYPE(table), &managed_id_table_type));
406409

407410
return rb_id_table_insert(RTYPEDDATA_GET_DATA(table), id, val);
@@ -410,6 +413,7 @@ rb_managed_id_table_insert(VALUE table, ID id, VALUE val)
410413
size_t
411414
rb_managed_id_table_size(VALUE table)
412415
{
416+
RUBY_ASSERT(RB_TYPE_P(table, T_DATA));
413417
RUBY_ASSERT(rb_typeddata_inherited_p(RTYPEDDATA_TYPE(table), &managed_id_table_type));
414418

415419
return rb_id_table_size(RTYPEDDATA_GET_DATA(table));
@@ -418,6 +422,7 @@ rb_managed_id_table_size(VALUE table)
418422
void
419423
rb_managed_id_table_foreach(VALUE table, rb_id_table_foreach_func_t *func, void *data)
420424
{
425+
RUBY_ASSERT(RB_TYPE_P(table, T_DATA));
421426
RUBY_ASSERT(rb_typeddata_inherited_p(RTYPEDDATA_TYPE(table), &managed_id_table_type));
422427

423428
rb_id_table_foreach(RTYPEDDATA_GET_DATA(table), func, data);

shape.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ static void
303303
shape_tree_mark(void *data)
304304
{
305305
rb_shape_t *cursor = rb_shape_get_root_shape();
306-
rb_shape_t *end = RSHAPE(GET_SHAPE_TREE()->next_shape_id);
306+
rb_shape_t *end = cursor + (GET_SHAPE_TREE()->next_shape_id - 1);
307307
while (cursor < end) {
308308
if (cursor->edges && !SINGLE_CHILD_P(cursor->edges)) {
309309
// FIXME: GC compaction may call `rb_shape_traverse_from_new_root`

shape.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ STATIC_ASSERT(shape_id_num_bits, SHAPE_ID_NUM_BITS == sizeof(shape_id_t) * CHAR_
1414
#define SHAPE_ID_OFFSET_MASK (SHAPE_BUFFER_SIZE - 1)
1515
#define SHAPE_ID_FLAGS_MASK (shape_id_t)(((1 << (SHAPE_ID_NUM_BITS - SHAPE_ID_OFFSET_NUM_BITS)) - 1) << SHAPE_ID_OFFSET_NUM_BITS)
1616
#define SHAPE_ID_FL_FROZEN (SHAPE_FL_FROZEN << SHAPE_ID_OFFSET_NUM_BITS)
17+
#define SHAPE_ID_READ_ONLY_MASK (~SHAPE_ID_FL_FROZEN)
1718

1819
typedef uint32_t redblack_id_t;
1920

@@ -110,6 +111,14 @@ RBASIC_SHAPE_ID(VALUE obj)
110111
#endif
111112
}
112113

114+
// Same as RBASIC_SHAPE_ID but with flags that have no impact
115+
// on reads removed. e.g. Remove FL_FROZEN.
116+
static inline shape_id_t
117+
RBASIC_SHAPE_ID_FOR_READ(VALUE obj)
118+
{
119+
return RBASIC_SHAPE_ID(obj) & SHAPE_ID_READ_ONLY_MASK;
120+
}
121+
113122
static inline void
114123
RBASIC_SET_SHAPE_ID(VALUE obj, shape_id_t shape_id)
115124
{

vm_insnhelper.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,14 +1215,13 @@ vm_getivar(VALUE obj, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_call
12151215
{
12161216
#if OPT_IC_FOR_IVAR
12171217
VALUE val = Qundef;
1218-
shape_id_t shape_id;
12191218
VALUE * ivar_list;
12201219

12211220
if (SPECIAL_CONST_P(obj)) {
12221221
return default_value;
12231222
}
12241223

1225-
shape_id = RBASIC_SHAPE_ID(obj);
1224+
shape_id_t shape_id = RBASIC_SHAPE_ID_FOR_READ(obj);
12261225

12271226
switch (BUILTIN_TYPE(obj)) {
12281227
case T_OBJECT:

0 commit comments

Comments
 (0)