Increment max_iv_count on class based on number of set_iv in initialize (#6788)
We can loosely predict the number of ivar sets on a class based on the number of iv set instructions in the initialize method. This should give us a more accurate estimate to use for initial size pool allocation, which should in turn give us more cache hits.
This commit is contained in:
parent
20b9d7b9fd
commit
9c5e3671eb
Notes:
git
2022-11-22 20:28:39 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>
2
gc.c
2
gc.c
@ -3089,7 +3089,7 @@ rb_imemo_new_debug(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0,
|
||||
}
|
||||
#endif
|
||||
|
||||
VALUE
|
||||
MJIT_FUNC_EXPORTED VALUE
|
||||
rb_class_allocate_instance(VALUE klass)
|
||||
{
|
||||
return rb_class_instance_allocate_internal(klass, T_OBJECT | ROBJECT_EMBED, RGENGC_WB_PROTECTED_OBJECT);
|
||||
|
39
iseq.c
39
iseq.c
@ -2490,6 +2490,45 @@ rb_iseq_disasm(const rb_iseq_t *iseq)
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Estimates the number of instance variables that will be set on
|
||||
* a given `class` with the initialize method defined in
|
||||
* `initialize_iseq`
|
||||
*/
|
||||
attr_index_t
|
||||
rb_estimate_iv_count(VALUE klass, const rb_iseq_t * initialize_iseq)
|
||||
{
|
||||
bool calls_super = false;
|
||||
|
||||
struct rb_id_table * iv_names = rb_id_table_create(0);
|
||||
|
||||
VALUE * code = ISEQ_BODY(initialize_iseq)->iseq_encoded;
|
||||
|
||||
for (unsigned int i = 0; i < ISEQ_BODY(initialize_iseq)->iseq_size; ) {
|
||||
VALUE insn = code[i];
|
||||
int original_insn = rb_vm_insn_addr2insn((const void *)insn);
|
||||
|
||||
if (BIN(setinstancevariable) == original_insn) {
|
||||
ID name = (ID)code[i + 1];
|
||||
rb_id_table_insert(iv_names, name, Qtrue);
|
||||
}
|
||||
else if (BIN(invokesuper) == original_insn) {
|
||||
calls_super = true;
|
||||
}
|
||||
|
||||
i += insn_len(original_insn);
|
||||
}
|
||||
|
||||
attr_index_t count = (attr_index_t)rb_id_table_size(iv_names);
|
||||
|
||||
if (calls_super) {
|
||||
VALUE superclass = rb_class_superclass(klass);
|
||||
count += RCLASS_EXT(superclass)->max_iv_count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* iseq.disasm -> str
|
||||
|
@ -1158,6 +1158,7 @@ rb_iseq_t *rb_iseq_new_with_callback(const struct rb_iseq_new_with_callback_call
|
||||
|
||||
VALUE rb_iseq_disasm(const rb_iseq_t *iseq);
|
||||
int rb_iseq_disasm_insn(VALUE str, const VALUE *iseqval, size_t pos, const rb_iseq_t *iseq, VALUE child);
|
||||
attr_index_t rb_estimate_iv_count(VALUE klass, const rb_iseq_t * initialize_iseq);
|
||||
|
||||
VALUE rb_iseq_coverage(const rb_iseq_t *iseq);
|
||||
|
||||
|
@ -4946,6 +4946,11 @@ vm_define_method(const rb_execution_context_t *ec, VALUE obj, ID id, VALUE iseqv
|
||||
}
|
||||
|
||||
rb_add_method_iseq(klass, id, (const rb_iseq_t *)iseqval, cref, visi);
|
||||
// Set max_iv_count on klasses based on number of ivar sets that are in the initialize method
|
||||
if (id == rb_intern("initialize") && klass != rb_cObject && RB_TYPE_P(klass, T_CLASS) && (rb_get_alloc_func(klass) == rb_class_allocate_instance)) {
|
||||
|
||||
RCLASS_EXT(klass)->max_iv_count = rb_estimate_iv_count(klass, (const rb_iseq_t *)iseqval);
|
||||
}
|
||||
|
||||
if (!is_singleton && vm_scope_module_func_check(ec)) {
|
||||
klass = rb_singleton_class(klass);
|
||||
|
Loading…
x
Reference in New Issue
Block a user