summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--bootstraptest/test_syntax.rb15
-rw-r--r--compile.c23
-rw-r--r--id.c2
-rw-r--r--id.h2
-rw-r--r--insnhelper.ci63
-rw-r--r--insns.def117
-rw-r--r--object.c6
-rw-r--r--vm.h2
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 <ko1@atdot.net>
+
+ * 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 <ko1@atdot.net>
* 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; i<n; i++) {
+ iobj->operands[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<Y.
@@ -1991,7 +1963,8 @@ opt_succ
BASIC_OP_UNREDEFINED_P(BOP_SUCC)) {
val = rb_time_succ(recv);
}
- else {
+ else
+ {
goto INSN_LABEL(normal_dispatch);
}
}
@@ -2004,6 +1977,30 @@ opt_succ
/**
@c optimize
+ @e optimized not
+ @j 最適化された recv.!()。
+ */
+DEFINE_INSN
+opt_not
+(IC ic)
+(VALUE recv)
+(VALUE val)
+{
+ extern VALUE rb_obj_not(VALUE obj);
+ NODE *mn = vm_method_search(idNot, CLASS_OF(recv), ic);
+
+ if (check_cfunc(mn, rb_obj_not)) {
+ val = RTEST(recv) ? Qfalse : Qtrue;
+ }
+ else {
+ PUSH(recv);
+ CALL_SIMPLE_METHOD(0, idNot, recv);
+ }
+}
+
+
+/**
+ @c optimize
@e optimized regexp match
@j 最適化された正規表現マッチ。
*/
diff --git a/object.c b/object.c
index c33123b2fc..4811c9a0ab 100644
--- a/object.c
+++ b/object.c
@@ -89,7 +89,7 @@ rb_eql(VALUE obj1, VALUE obj2)
* 1.eql? 1.0 #=> 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 */