Project

General

Profile

Feature #11786 ยป 0001-micro-optimize-case-dispatch-even-harder.patch

normalperson (Eric Wong), 12/08/2015 03:36 AM

View differences:

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
-
    (1-1/1)