From cd843108646b999e13cfbf04e51eca30b68850b3 Mon Sep 17 00:00:00 2001 From: ko1 Date: Tue, 18 Dec 2007 12:07:51 +0000 Subject: * compile.c, insnhelper.ci, insns.def, object.c, vm.c, vm.h: optimize !@, != method invocation. * id.c, id.h: ditto. * bootstraptest/test_syntax.rb: add tests for above. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@14299 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 9 ++++ bootstraptest/test_syntax.rb | 15 ++++++ compile.c | 23 ++++++++- id.c | 2 + id.h | 2 + insnhelper.ci | 63 +++++++++++++++++++++++ insns.def | 117 +++++++++++++++++++++---------------------- object.c | 6 +-- vm.h | 2 + 9 files changed, 175 insertions(+), 64 deletions(-) diff --git a/ChangeLog b/ChangeLog index ac059f6d57..495934ac8b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Tue Dec 18 20:58:35 2007 Koichi Sasada + + * compile.c, insnhelper.ci, insns.def, object.c, vm.c, vm.h: + optimize !@, != method invocation. + + * id.c, id.h: ditto. + + * bootstraptest/test_syntax.rb: add tests for above. + Tue Dec 18 18:10:05 2007 Koichi Sasada * bootstraptest/test_knownbug.rb: add issues. diff --git a/bootstraptest/test_syntax.rb b/bootstraptest/test_syntax.rb index 3e4c79bece..0ba8f658f2 100644 --- a/bootstraptest/test_syntax.rb +++ b/bootstraptest/test_syntax.rb @@ -628,3 +628,18 @@ assert_match /illegal multibyte char/, %q{ STDERR.reopen(STDOUT) eval("\"\xf0".force_encoding("utf-8")) }, '[ruby-dev:32429]' + +# method ! and != +assert_equal 'true', %q{!false} +assert_equal 'true', %q{1 == 1} +assert_equal 'true', %q{1 != 2} +assert_equal 'true', %q{ + class C; def !=(obj); true; end; end + C.new != 1 +} +assert_equal 'true', %q{ + class C; def !@; true; end; end + !C.new +} + + diff --git a/compile.c b/compile.c index 538e811582..f77851f777 100644 --- a/compile.c +++ b/compile.c @@ -1416,6 +1416,21 @@ insn_set_specialized_instruction(INSN *iobj, int insn_id) return COMPILE_OK; } +static int +insn_set_specialized_instruction_with_ic(INSN *iobj, int insn_id, int n) +{ + int i; + iobj->insn_id = insn_id; + iobj->operand_size = n; + + /* max of n is 4 */ + for (i=0; ioperands[i] = Qnil; + } + + return COMPILE_OK; +} + static int iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj) @@ -1435,6 +1450,9 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj) else if (mid == idSucc) { insn_set_specialized_instruction(iobj, BIN(opt_succ)); } + else if (mid == idNot) { + insn_set_specialized_instruction_with_ic(iobj, BIN(opt_not), 1); + } } else if (argc == 1) { if (0) { @@ -1455,7 +1473,10 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj) insn_set_specialized_instruction(iobj, BIN(opt_mod)); } else if (mid == idEq) { - insn_set_specialized_instruction(iobj, BIN(opt_eq)); + insn_set_specialized_instruction_with_ic(iobj, BIN(opt_eq), 1); + } + else if (mid == idNeq) { + insn_set_specialized_instruction_with_ic(iobj, BIN(opt_neq), 2); } else if (mid == idLT) { insn_set_specialized_instruction(iobj, BIN(opt_lt)); diff --git a/id.c b/id.c index 6fa00a66b3..84499ace34 100644 --- a/id.c +++ b/id.c @@ -38,6 +38,8 @@ Init_id(void) idEqq = rb_intern("==="); idBackquote = rb_intern("`"); idEqTilde = rb_intern("=~"); + idNot = rb_intern("!"); + idNeq = rb_intern("!="); idAREF = rb_intern("[]"); idASET = rb_intern("[]="); diff --git a/id.h b/id.h index fa22d8c788..5869ebcc4e 100644 --- a/id.h +++ b/id.h @@ -25,6 +25,8 @@ extern ID idGT; extern ID idGE; extern ID idEq; extern ID idEqq; +extern ID idNeq; +extern ID idNot; extern ID idBackquote; extern ID idEqTilde; extern ID idThrowState; diff --git a/insnhelper.ci b/insnhelper.ci index f7a3a0c3d2..4197f3b06b 100644 --- a/insnhelper.ci +++ b/insnhelper.ci @@ -1404,3 +1404,66 @@ call_end_proc(VALUE data) { rb_proc_call(data, rb_ary_new2(0)); } + +static inline int +check_cfunc(NODE *mn, void *func) +{ + if (mn && nd_type(mn->nd_body) == NODE_CFUNC && + mn->nd_body->nd_cfnc == func) { + return 1; + } + else { + return 0; + } +} + +static VALUE +opt_eq_func(VALUE recv, VALUE obj, IC ic) +{ + VALUE val = Qundef; + + if (FIXNUM_2_P(recv, obj) && + BASIC_OP_UNREDEFINED_P(BOP_EQ)) { + long a = FIX2LONG(recv), b = FIX2LONG(obj); + + if (a == b) { + val = Qtrue; + } + else { + val = Qfalse; + } + } + else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { + if (HEAP_CLASS_OF(recv) == rb_cFloat && + HEAP_CLASS_OF(obj) == rb_cFloat && + BASIC_OP_UNREDEFINED_P(BOP_EQ)) { + double a = RFLOAT_VALUE(recv); + double b = RFLOAT_VALUE(obj); + + if (isnan(a) || isnan(b)) { + val = Qfalse; + } + else if (a == b) { + val = Qtrue; + } + else { + val = Qfalse; + } + } + else if (HEAP_CLASS_OF(recv) == rb_cString && + HEAP_CLASS_OF(obj) == rb_cString && + BASIC_OP_UNREDEFINED_P(BOP_EQ)) { + val = rb_str_equal(recv, obj); + } + else { + NODE *mn = vm_method_search(idEq, CLASS_OF(recv), ic); + extern VALUE rb_obj_equal(VALUE obj1, VALUE obj2); + + if (check_cfunc(mn, rb_obj_equal)) { + return recv == obj ? Qtrue : Qfalse; + } + } + } + + return val; +} diff --git a/insns.def b/insns.def index 623f2ac42a..7cfa15a13f 100644 --- a/insns.def +++ b/insns.def @@ -581,26 +581,6 @@ newrange val = rb_range_new(low, high, flag); } -/** - @c put - @e put !val. - @j !val の結果をスタックにプッシュする。 - */ -DEFINE_INSN -putnot -() -(VALUE obj) -(VALUE val) -{ - if (RTEST(obj)) { - val = Qfalse; - } - else { - val = Qtrue; - } -} - - /**********************************************************/ /* deal with stack operation */ /**********************************************************/ @@ -1655,59 +1635,51 @@ opt_mod */ DEFINE_INSN opt_eq -() +(IC ic) (VALUE recv, VALUE obj) (VALUE val) { - if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_EQ)) { - long a = FIX2LONG(recv), b = FIX2LONG(obj); + val = opt_eq_func(recv, obj, ic); - if (a == b) { - val = Qtrue; - } - else { - val = Qfalse; - } + if (val == Qundef) { + /* other */ + PUSH(recv); + PUSH(obj); + CALL_SIMPLE_METHOD(1, idEq, recv); } - else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { - if (0) { - } - else if (HEAP_CLASS_OF(recv) == rb_cFloat && - HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_EQ)) { - double a = RFLOAT_VALUE(recv); - double b = RFLOAT_VALUE(obj); +} - if (isnan(a) || isnan(b)) { - val = Qfalse; - } - else if (a == b) { - val = Qtrue; - } - else { - val = Qfalse; - } - } - else if (HEAP_CLASS_OF(recv) == rb_cString && - HEAP_CLASS_OF(obj) == rb_cString && - BASIC_OP_UNREDEFINED_P(BOP_EQ)) { - val = rb_str_equal(recv, obj); - } - else { - goto INSN_LABEL(normal_dispatch); +/** + @c optimize + @e optimized X!=Y. + @j 最適化された X!=Y。 + */ +DEFINE_INSN +opt_neq +(IC ic1, IC ic2) +(VALUE recv, VALUE obj) +(VALUE val) +{ + extern VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2); + NODE *mn = vm_method_search(idNeq, CLASS_OF(recv), ic1); + val = Qundef; + + if (check_cfunc(mn, rb_obj_not_equal)) { + val = opt_eq_func(recv, obj, ic2); + + if (val != Qundef) { + val = RTEST(val) ? Qfalse : Qtrue; } } - else { - INSN_LABEL(normal_dispatch): + + if (val == Qundef) { /* other */ PUSH(recv); PUSH(obj); - CALL_SIMPLE_METHOD(1, idEq, recv); + CALL_SIMPLE_METHOD(1, idNeq, recv); } } - /** @c optimize @e optimized X false */ -static VALUE +VALUE rb_obj_equal(VALUE obj1, VALUE obj2) { if (obj1 == obj2) return Qtrue; @@ -103,7 +103,7 @@ rb_obj_equal(VALUE obj1, VALUE obj2) * Boolean negate. */ -static VALUE +VALUE rb_obj_not(VALUE obj) { return RTEST(obj) ? Qfalse : Qtrue; @@ -116,7 +116,7 @@ rb_obj_not(VALUE obj) * Returns true if two objects are not-equal, otherwise false. */ -static VALUE +VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2) { VALUE result = rb_funcall(obj1, id_eq, 1, obj2); diff --git a/vm.h b/vm.h index 360996e3f0..f7cffc1caa 100644 --- a/vm.h +++ b/vm.h @@ -279,5 +279,7 @@ default: \ #define BOP_SUCC 0x1000 #define BOP_GT 0x2000 #define BOP_GE 0x4000 +#define BOP_NOT 0x8000 +#define BOP_NEQ 0x10000 #endif /* RUBY_VM_H */ -- cgit v1.2.3