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
|
#endif
|
||||||
|
|
||||||
VALUE
|
MJIT_FUNC_EXPORTED VALUE
|
||||||
rb_class_allocate_instance(VALUE klass)
|
rb_class_allocate_instance(VALUE klass)
|
||||||
{
|
{
|
||||||
return rb_class_instance_allocate_internal(klass, T_OBJECT | ROBJECT_EMBED, RGENGC_WB_PROTECTED_OBJECT);
|
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;
|
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:
|
* call-seq:
|
||||||
* iseq.disasm -> str
|
* 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);
|
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);
|
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);
|
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);
|
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)) {
|
if (!is_singleton && vm_scope_module_func_check(ec)) {
|
||||||
klass = rb_singleton_class(klass);
|
klass = rb_singleton_class(klass);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user