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
1
i = 0
2
while i<6_000_000 # while loop 2
3
  case :foo
4
  when :foo
5
    i += 1
6
  else
7
    raise
8
  end
9
end
compile.c
1492 1492
};
1493 1493

  
1494 1494
struct cdhash_set_label_struct {
1495
    VALUE hash;
1495
    st_table *cdh;
1496 1496
    int pos;
1497 1497
    int len;
1498 1498
};
1499 1499

  
1500 1500
static int
1501
cdhash_set_label_i(VALUE key, VALUE val, void *ptr)
1501
cdhash_set_label_i(VALUE key, long val, void *ptr)
1502 1502
{
1503
    struct cdhash_set_label_struct *data = (struct cdhash_set_label_struct *)ptr;
1503
    struct cdhash_set_label_struct *d = (struct cdhash_set_label_struct *)ptr;
1504 1504
    LABEL *lobj = (LABEL *)(val & ~1);
1505
    rb_hash_aset(data->hash, key, INT2FIX(lobj->position - (data->pos+data->len)));
1505
    st_insert(d->cdh, key, lobj->position - (d->pos + d->len));
1506 1506
    return ST_CONTINUE;
1507 1507
}
1508 1508

  
......
1630 1630
			}
1631 1631
		      case TS_CDHASH:
1632 1632
			{
1633
			    VALUE map = operands[j];
1634
			    struct cdhash_set_label_struct data;
1635
                            data.hash = map;
1636
                            data.pos = code_index;
1637
                            data.len = len;
1638
			    rb_hash_foreach(map, cdhash_set_label_i, (VALUE)&data);
1639

  
1640
			    freeze_hide_obj(map);
1641
			    generated_iseq[code_index + 1 + j] = map;
1633
			    st_table *cdh = (st_table *)operands[j];
1634
			    struct cdhash_set_label_struct d;
1635
			    d.cdh = cdh;
1636
			    d.pos = code_index;
1637
			    d.len = len;
1638

  
1639
			    st_foreach(cdh, cdhash_set_label_i, (st_data_t)&d);
1640
			    generated_iseq[code_index + 1 + j] = (VALUE)cdh;
1642 1641
			    break;
1643 1642
			}
1644 1643
		      case TS_LINDEX:
......
2932 2931
}
2933 2932

  
2934 2933
static int
2935
when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, int only_special_literals, VALUE literals)
2934
when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1,
2935
	  int only_special_literals, st_table *literals)
2936 2936
{
2937 2937
    while (vals) {
2938 2938
	NODE* val = vals->nd_head;
......
2942 2942
	    only_special_literals = 0;
2943 2943
	}
2944 2944
	else {
2945
	    if (rb_hash_lookup(literals, lit) != Qnil) {
2945
	    if (st_lookup(literals, lit, 0)) {
2946 2946
		rb_compile_warning(ruby_sourcefile, nd_line(val), "duplicated when clause is ignored");
2947 2947
	    }
2948 2948
	    else {
2949
		rb_hash_aset(literals, lit, (VALUE)(l1) | 1);
2949
		st_add_direct(literals, lit, (VALUE)(l1) | 1);
2950 2950
	    }
2951 2951
	}
2952 2952

  
......
3703 3703
	DECL_ANCHOR(body_seq);
3704 3704
	DECL_ANCHOR(cond_seq);
3705 3705
	int only_special_literals = 1;
3706
	VALUE literals = rb_hash_new();
3706
	st_table *literals = st_init_table(&cdhash_type);
3707 3707

  
3708 3708
	INIT_ANCHOR(head);
3709 3709
	INIT_ANCHOR(body_seq);
3710 3710
	INIT_ANCHOR(cond_seq);
3711 3711

  
3712
	rb_hash_tbl_raw(literals)->type = &cdhash_type;
3713

  
3714 3712
	if (node->nd_head == 0) {
3715 3713
	    COMPILE_(ret, "when", node->nd_body, poped);
3716 3714
	    break;
......
3789 3787
	}
3790 3788

  
3791 3789
	if (only_special_literals) {
3792
	    iseq_add_mark_object(iseq, literals);
3793

  
3794 3790
	    ADD_INSN(ret, nd_line(tempnode), dup);
3795 3791
	    ADD_INSN2(ret, nd_line(tempnode), opt_case_dispatch, literals, elselabel);
3796 3792
	    LABEL_REF(elselabel);
3797 3793
	}
3794
	else {
3795
	    st_free_table(literals);
3796
	}
3798 3797

  
3799 3798
	ADD_SEQ(ret, cond_seq);
3800 3799
	ADD_SEQ(ret, body_seq);
......
6403 6402
		      case TS_CDHASH:
6404 6403
			{
6405 6404
			    int i;
6406
			    VALUE map = rb_hash_new();
6405
			    st_table *literals = st_init_table(&cdhash_type);
6407 6406

  
6408
			    rb_hash_tbl_raw(map)->type = &cdhash_type;
6409 6407
			    op = rb_convert_type(op, T_ARRAY, "Array", "to_ary");
6410 6408
			    op = rb_ary_dup(op);
6411 6409
			    for (i=0; i<RARRAY_LEN(op); i+=2) {
......
6413 6411
				VALUE sym = RARRAY_AREF(op, i+1);
6414 6412
				LABEL *label =
6415 6413
				  register_label(iseq, labels_table, sym);
6416
				rb_hash_aset(map, key, (VALUE)label | 1);
6414

  
6415
				st_add_direct(literals, key, (VALUE)label | 1);
6417 6416
			    }
6418 6417
			    RB_GC_GUARD(op);
6419
			    argv[j] = map;
6420
			    rb_iseq_add_mark_object(iseq, map);
6418
			    argv[j] = (VALUE)literals;
6421 6419
			}
6422 6420
			break;
6423 6421
		      case TS_FUNCPTR:
insns.def
1253 1253
 */
1254 1254
DEFINE_INSN
1255 1255
opt_case_dispatch
1256
(CDHASH hash, OFFSET else_offset)
1256
(CDHASH cdh, OFFSET else_offset)
1257 1257
(..., VALUE key)
1258 1258
() // inc += -1;
1259 1259
{
......
1281 1281
				   FALSE_REDEFINED_OP_FLAG  |
1282 1282
				   STRING_REDEFINED_OP_FLAG)) {
1283 1283
	    st_data_t val;
1284
	    if (st_lookup(RHASH_TBL_RAW(hash), key, &val)) {
1285
		JUMP(FIX2INT((VALUE)val));
1284
	    if (st_lookup(cdh, key, &val)) {
1285
		JUMP(val);
1286 1286
	    }
1287 1287
	    else {
1288 1288
		JUMP(else_offset);
iseq.c
1754 1754
cdhash_each(VALUE key, VALUE value, VALUE ary)
1755 1755
{
1756 1756
    rb_ary_push(ary, obj_resurrect(key));
1757
    rb_ary_push(ary, value);
1757
    rb_ary_push(ary, INT2FIX(value));
1758 1758
    return ST_CONTINUE;
1759 1759
}
1760 1760

  
......
1961 1961
		break;
1962 1962
	      case TS_CDHASH:
1963 1963
		{
1964
		    VALUE hash = *seq;
1964
		    st_table *cdh = (st_table *)*seq;
1965 1965
		    VALUE val = rb_ary_new();
1966 1966
		    int i;
1967 1967

  
1968
		    rb_hash_foreach(hash, cdhash_each, val);
1968
		    st_foreach(cdh, cdhash_each, val);
1969 1969

  
1970 1970
		    for (i=0; i<RARRAY_LEN(val); i+=2) {
1971 1971
			VALUE pos = FIX2INT(rb_ary_entry(val, i+1));
vm_core.h
917 917

  
918 918
void rb_vm_change_state(void);
919 919

  
920
typedef VALUE CDHASH;
920
typedef st_table * CDHASH;
921 921

  
922 922
#ifndef FUNC_FASTCALL
923 923
#define FUNC_FASTCALL(x) x
924
-