Feature #11786 ยป 0001-micro-optimize-case-dispatch-even-harder.patch
benchmark/bm_vm2_case_small.rb | ||
---|---|---|
i = 0
|
||
while i<6_000_000 # while loop 2
|
||
case :foo
|
||
when :foo
|
||
i += 1
|
||
else
|
||
raise
|
||
end
|
||
end
|
compile.c | ||
---|---|---|
};
|
||
struct cdhash_set_label_struct {
|
||
VALUE hash;
|
||
st_table *cdh;
|
||
int pos;
|
||
int len;
|
||
};
|
||
static int
|
||
cdhash_set_label_i(VALUE key, VALUE val, void *ptr)
|
||
cdhash_set_label_i(VALUE key, long val, void *ptr)
|
||
{
|
||
struct cdhash_set_label_struct *data = (struct cdhash_set_label_struct *)ptr;
|
||
struct cdhash_set_label_struct *d = (struct cdhash_set_label_struct *)ptr;
|
||
LABEL *lobj = (LABEL *)(val & ~1);
|
||
rb_hash_aset(data->hash, key, INT2FIX(lobj->position - (data->pos+data->len)));
|
||
st_insert(d->cdh, key, lobj->position - (d->pos + d->len));
|
||
return ST_CONTINUE;
|
||
}
|
||
... | ... | |
}
|
||
case TS_CDHASH:
|
||
{
|
||
VALUE map = operands[j];
|
||
struct cdhash_set_label_struct data;
|
||
data.hash = map;
|
||
data.pos = code_index;
|
||
data.len = len;
|
||
rb_hash_foreach(map, cdhash_set_label_i, (VALUE)&data);
|
||
freeze_hide_obj(map);
|
||
generated_iseq[code_index + 1 + j] = map;
|
||
st_table *cdh = (st_table *)operands[j];
|
||
struct cdhash_set_label_struct d;
|
||
d.cdh = cdh;
|
||
d.pos = code_index;
|
||
d.len = len;
|
||
st_foreach(cdh, cdhash_set_label_i, (st_data_t)&d);
|
||
generated_iseq[code_index + 1 + j] = (VALUE)cdh;
|
||
break;
|
||
}
|
||
case TS_LINDEX:
|
||
... | ... | |
}
|
||
static int
|
||
when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, int only_special_literals, VALUE literals)
|
||
when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1,
|
||
int only_special_literals, st_table *literals)
|
||
{
|
||
while (vals) {
|
||
NODE* val = vals->nd_head;
|
||
... | ... | |
only_special_literals = 0;
|
||
}
|
||
else {
|
||
if (rb_hash_lookup(literals, lit) != Qnil) {
|
||
if (st_lookup(literals, lit, 0)) {
|
||
rb_compile_warning(ruby_sourcefile, nd_line(val), "duplicated when clause is ignored");
|
||
}
|
||
else {
|
||
rb_hash_aset(literals, lit, (VALUE)(l1) | 1);
|
||
st_add_direct(literals, lit, (VALUE)(l1) | 1);
|
||
}
|
||
}
|
||
... | ... | |
DECL_ANCHOR(body_seq);
|
||
DECL_ANCHOR(cond_seq);
|
||
int only_special_literals = 1;
|
||
VALUE literals = rb_hash_new();
|
||
st_table *literals = st_init_table(&cdhash_type);
|
||
INIT_ANCHOR(head);
|
||
INIT_ANCHOR(body_seq);
|
||
INIT_ANCHOR(cond_seq);
|
||
rb_hash_tbl_raw(literals)->type = &cdhash_type;
|
||
if (node->nd_head == 0) {
|
||
COMPILE_(ret, "when", node->nd_body, poped);
|
||
break;
|
||
... | ... | |
}
|
||
if (only_special_literals) {
|
||
iseq_add_mark_object(iseq, literals);
|
||
ADD_INSN(ret, nd_line(tempnode), dup);
|
||
ADD_INSN2(ret, nd_line(tempnode), opt_case_dispatch, literals, elselabel);
|
||
LABEL_REF(elselabel);
|
||
}
|
||
else {
|
||
st_free_table(literals);
|
||
}
|
||
ADD_SEQ(ret, cond_seq);
|
||
ADD_SEQ(ret, body_seq);
|
||
... | ... | |
case TS_CDHASH:
|
||
{
|
||
int i;
|
||
VALUE map = rb_hash_new();
|
||
st_table *literals = st_init_table(&cdhash_type);
|
||
rb_hash_tbl_raw(map)->type = &cdhash_type;
|
||
op = rb_convert_type(op, T_ARRAY, "Array", "to_ary");
|
||
op = rb_ary_dup(op);
|
||
for (i=0; i<RARRAY_LEN(op); i+=2) {
|
||
... | ... | |
VALUE sym = RARRAY_AREF(op, i+1);
|
||
LABEL *label =
|
||
register_label(iseq, labels_table, sym);
|
||
rb_hash_aset(map, key, (VALUE)label | 1);
|
||
st_add_direct(literals, key, (VALUE)label | 1);
|
||
}
|
||
RB_GC_GUARD(op);
|
||
argv[j] = map;
|
||
rb_iseq_add_mark_object(iseq, map);
|
||
argv[j] = (VALUE)literals;
|
||
}
|
||
break;
|
||
case TS_FUNCPTR:
|
insns.def | ||
---|---|---|
*/
|
||
DEFINE_INSN
|
||
opt_case_dispatch
|
||
(CDHASH hash, OFFSET else_offset)
|
||
(CDHASH cdh, OFFSET else_offset)
|
||
(..., VALUE key)
|
||
() // inc += -1;
|
||
{
|
||
... | ... | |
FALSE_REDEFINED_OP_FLAG |
|
||
STRING_REDEFINED_OP_FLAG)) {
|
||
st_data_t val;
|
||
if (st_lookup(RHASH_TBL_RAW(hash), key, &val)) {
|
||
JUMP(FIX2INT((VALUE)val));
|
||
if (st_lookup(cdh, key, &val)) {
|
||
JUMP(val);
|
||
}
|
||
else {
|
||
JUMP(else_offset);
|
iseq.c | ||
---|---|---|
cdhash_each(VALUE key, VALUE value, VALUE ary)
|
||
{
|
||
rb_ary_push(ary, obj_resurrect(key));
|
||
rb_ary_push(ary, value);
|
||
rb_ary_push(ary, INT2FIX(value));
|
||
return ST_CONTINUE;
|
||
}
|
||
... | ... | |
break;
|
||
case TS_CDHASH:
|
||
{
|
||
VALUE hash = *seq;
|
||
st_table *cdh = (st_table *)*seq;
|
||
VALUE val = rb_ary_new();
|
||
int i;
|
||
rb_hash_foreach(hash, cdhash_each, val);
|
||
st_foreach(cdh, cdhash_each, val);
|
||
for (i=0; i<RARRAY_LEN(val); i+=2) {
|
||
VALUE pos = FIX2INT(rb_ary_entry(val, i+1));
|
vm_core.h | ||
---|---|---|
void rb_vm_change_state(void);
|
||
typedef VALUE CDHASH;
|
||
typedef st_table * CDHASH;
|
||
#ifndef FUNC_FASTCALL
|
||
#define FUNC_FASTCALL(x) x
|
||
-
|