From 9c5e3671ebd9c07c178ca5dac08ad15ad1eae411 Mon Sep 17 00:00:00 2001 From: Jemma Issroff Date: Tue, 22 Nov 2022 15:28:14 -0500 Subject: 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. --- iseq.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'iseq.c') diff --git a/iseq.c b/iseq.c index a2e79cd55b..b366f03823 100644 --- a/iseq.c +++ b/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 -- cgit v1.2.3