Skip to content

Commit fa93a68

Browse files
committed
Implement gen_fields_tbl cache
When accessing an object ivars, it's not rare to access the same object's ivar quickly after. For instance from enumerator.c: ```c enumerator = rb_obj_alloc(rb_cEnumerator); rb_ivar_set(enumerator, id_sliceafter_enum, enumerable); rb_ivar_set(enumerator, id_sliceafter_pat, pat); rb_ivar_set(enumerator, id_sliceafter_pred, pred); ``` If we keep a cache of the last IMEMO/fields we interacted with, we can save having to lookup the `gen_fields_tbl`, synchronize the VM lock, etc.
1 parent fccd96c commit fa93a68

3 files changed

Lines changed: 44 additions & 8 deletions

File tree

variable.c

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,9 +1238,19 @@ rb_obj_fields(VALUE obj, ID field_name)
12381238
}
12391239
// fall through
12401240
default:
1241-
RB_VM_LOCKING() {
1242-
if (!st_lookup(generic_fields_tbl_, (st_data_t)obj, (st_data_t *)&fields_obj)) {
1243-
rb_bug("Object is missing entry in generic_fields_tbl");
1241+
{
1242+
rb_execution_context_t *ec = GET_EC();
1243+
if (ec->gen_fields_cache.obj == obj) {
1244+
fields_obj = ec->gen_fields_cache.fields_obj;
1245+
}
1246+
else {
1247+
RB_VM_LOCKING() {
1248+
if (!st_lookup(generic_fields_tbl_, (st_data_t)obj, (st_data_t *)&fields_obj)) {
1249+
rb_bug("Object is missing entry in generic_fields_tbl");
1250+
}
1251+
}
1252+
ec->gen_fields_cache.fields_obj = fields_obj;
1253+
ec->gen_fields_cache.obj = obj;
12441254
}
12451255
}
12461256
}
@@ -1261,8 +1271,15 @@ rb_free_generic_ivar(VALUE obj)
12611271
}
12621272
// fall through
12631273
default:
1264-
RB_VM_LOCKING() {
1265-
st_delete(generic_fields_tbl_no_ractor_check(), &key, &value);
1274+
{
1275+
rb_execution_context_t *ec = GET_EC();
1276+
if (ec->gen_fields_cache.obj == obj) {
1277+
ec->gen_fields_cache.obj = Qundef;
1278+
ec->gen_fields_cache.fields_obj = Qundef;
1279+
}
1280+
RB_VM_LOCKING() {
1281+
st_delete(generic_fields_tbl_no_ractor_check(), &key, &value);
1282+
}
12661283
}
12671284
}
12681285
RBASIC_SET_SHAPE_ID(obj, ROOT_SHAPE_ID);
@@ -1286,10 +1303,18 @@ rb_obj_set_fields(VALUE obj, VALUE fields_obj, ID field_name, VALUE original_fie
12861303
}
12871304
// fall through
12881305
default:
1289-
RB_VM_LOCKING() {
1290-
st_insert(generic_fields_tbl_, (st_data_t)obj, (st_data_t)fields_obj);
1306+
{
1307+
RB_VM_LOCKING() {
1308+
st_insert(generic_fields_tbl_, (st_data_t)obj, (st_data_t)fields_obj);
1309+
}
1310+
RB_OBJ_WRITTEN(obj, original_fields_obj, fields_obj);
1311+
1312+
rb_execution_context_t *ec = GET_EC();
1313+
if (ec->gen_fields_cache.fields_obj != fields_obj) {
1314+
ec->gen_fields_cache.obj = obj;
1315+
ec->gen_fields_cache.fields_obj = fields_obj;
1316+
}
12911317
}
1292-
RB_OBJ_WRITTEN(obj, original_fields_obj, fields_obj);
12931318
}
12941319

12951320
if (original_fields_obj) {

vm.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3441,6 +3441,9 @@ rb_execution_context_update(rb_execution_context_t *ec)
34413441
}
34423442

34433443
ec->storage = rb_gc_location(ec->storage);
3444+
3445+
ec->gen_fields_cache.obj = rb_gc_location(ec->gen_fields_cache.obj);
3446+
ec->gen_fields_cache.fields_obj = rb_gc_location(ec->gen_fields_cache.fields_obj);
34443447
}
34453448

34463449
static enum rb_id_table_iterator_result
@@ -3505,6 +3508,9 @@ rb_execution_context_mark(const rb_execution_context_t *ec)
35053508
rb_gc_mark(ec->private_const_reference);
35063509

35073510
rb_gc_mark_movable(ec->storage);
3511+
3512+
rb_gc_mark_weak((VALUE *)&ec->gen_fields_cache.obj);
3513+
rb_gc_mark_weak((VALUE *)&ec->gen_fields_cache.fields_obj);
35083514
}
35093515

35103516
void rb_fiber_mark_self(rb_fiber_t *fib);

vm_core.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,11 @@ struct rb_execution_context_struct {
10701070

10711071
VALUE private_const_reference;
10721072

1073+
struct {
1074+
VALUE obj;
1075+
VALUE fields_obj;
1076+
} gen_fields_cache;
1077+
10731078
/* for GC */
10741079
struct {
10751080
VALUE *stack_start;

0 commit comments

Comments
 (0)