summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authork0kubun <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-09-25 17:19:51 +0000
committerk0kubun <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-09-25 17:19:51 +0000
commit08c9f030f6b5d260d12cf02a9ca0f4a60f816365 (patch)
tree42e5f6136b38effe27dac1617ce5ddd44fac6323
parent3f4d174c22589ea275f971fab90136add6e456ac (diff)
Revert "Revert r64824 to fix build failure on AppVeyor"
This reverts commit r64829. I'll prepare another temporary fix, but I'll separately commit that to make it easier to revert that later. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64838 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--compile.c2
-rw-r--r--defs/id.def2
-rw-r--r--insns.def28
-rw-r--r--test/ruby/test_jit.rb8
-rw-r--r--test/ruby/test_optimization.rb10
-rw-r--r--tool/transform_mjit_header.rb2
-rw-r--r--vm.c2
-rw-r--r--vm_core.h2
-rw-r--r--vm_insnhelper.c24
9 files changed, 80 insertions, 0 deletions
diff --git a/compile.c b/compile.c
index 83d992a2e9..0a2e076b39 100644
--- a/compile.c
+++ b/compile.c
@@ -3245,6 +3245,8 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
case idGE: SP_INSN(ge); return COMPILE_OK;
case idLTLT: SP_INSN(ltlt); return COMPILE_OK;
case idAREF: SP_INSN(aref); return COMPILE_OK;
+ case idAnd: SP_INSN(and); return COMPILE_OK;
+ case idOr: SP_INSN(or); return COMPILE_OK;
}
break;
case 2:
diff --git a/defs/id.def b/defs/id.def
index e1a66f5030..fe61d254c9 100644
--- a/defs/id.def
+++ b/defs/id.def
@@ -97,6 +97,8 @@ token_ops = %[\
Eqq === EQQ
Neq != NEQ
Not !
+ And &
+ Or |
Backquote `
EqTilde =~ MATCH
NeqTilde !~ NMATCH
diff --git a/insns.def b/insns.def
index 742cd87960..cacc5b709f 100644
--- a/insns.def
+++ b/insns.def
@@ -1216,6 +1216,34 @@ opt_ltlt
}
}
+/* optimized X&Y. */
+DEFINE_INSN
+opt_and
+(CALL_INFO ci, CALL_CACHE cc)
+(VALUE recv, VALUE obj)
+(VALUE val)
+{
+ val = vm_opt_and(recv, obj);
+
+ if (val == Qundef) {
+ CALL_SIMPLE_METHOD();
+ }
+}
+
+/* optimized X|Y. */
+DEFINE_INSN
+opt_or
+(CALL_INFO ci, CALL_CACHE cc)
+(VALUE recv, VALUE obj)
+(VALUE val)
+{
+ val = vm_opt_or(recv, obj);
+
+ if (val == Qundef) {
+ CALL_SIMPLE_METHOD();
+ }
+}
+
/* [] */
DEFINE_INSN
opt_aref
diff --git a/test/ruby/test_jit.rb b/test/ruby/test_jit.rb
index 50f318c2a7..3770faf038 100644
--- a/test/ruby/test_jit.rb
+++ b/test/ruby/test_jit.rb
@@ -478,6 +478,14 @@ class TestJIT < Test::Unit::TestCase
assert_compile_once('[1] << 2', result_inspect: '[1, 2]', insns: %i[opt_ltlt])
end
+ def test_compile_insn_opt_and
+ assert_compile_once('1 & 3', result_inspect: '1', insns: %i[opt_and])
+ end
+
+ def test_compile_insn_opt_or
+ assert_compile_once('1 | 3', result_inspect: '3', insns: %i[opt_or])
+ end
+
def test_compile_insn_opt_aref
skip_on_mswin
# optimized call (optimized JIT) -> send call
diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb
index d4a1fdbcea..c425254661 100644
--- a/test/ruby/test_optimization.rb
+++ b/test/ruby/test_optimization.rb
@@ -187,6 +187,16 @@ class TestRubyOptimization < Test::Unit::TestCase
assert_redefine_method('String', '<<', 'assert_equal "b", "a" << "b"')
end
+ def test_fixnum_and
+ assert_equal 1, 1&3
+ assert_redefine_method('Integer', '&', 'assert_equal 3, 1&3')
+ end
+
+ def test_fixnum_or
+ assert_equal 3, 1|3
+ assert_redefine_method('Integer', '|', 'assert_equal 1, 3|1')
+ end
+
def test_array_plus
assert_equal [1,2], [1]+[2]
assert_redefine_method('Array', '+', 'assert_equal [2], [1]+[2]')
diff --git a/tool/transform_mjit_header.rb b/tool/transform_mjit_header.rb
index 936a0e1945..1000172352 100644
--- a/tool/transform_mjit_header.rb
+++ b/tool/transform_mjit_header.rb
@@ -52,6 +52,8 @@ module MJITHeader
'vm_opt_gt',
'vm_opt_ge',
'vm_opt_ltlt',
+ 'vm_opt_and',
+ 'vm_opt_or',
'vm_opt_aref',
'vm_opt_aset',
'vm_opt_aref_with',
diff --git a/vm.c b/vm.c
index da9afe2fc7..eb47a83d5f 100644
--- a/vm.c
+++ b/vm.c
@@ -1610,6 +1610,8 @@ vm_init_redefined_flag(void)
OP(Max, MAX), (C(Array));
OP(Min, MIN), (C(Array));
OP(Call, CALL), (C(Proc));
+ OP(And, AND), (C(Integer));
+ OP(Or, OR), (C(Integer));
#undef C
#undef OP
}
diff --git a/vm_core.h b/vm_core.h
index bb6409719b..1ab49b05de 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -531,6 +531,8 @@ enum ruby_basic_operators {
BOP_MAX,
BOP_MIN,
BOP_CALL,
+ BOP_AND,
+ BOP_OR,
BOP_LAST_
};
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 29b935803b..29e6545398 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -3653,6 +3653,30 @@ vm_opt_ltlt(VALUE recv, VALUE obj)
}
static VALUE
+vm_opt_and(VALUE recv, VALUE obj)
+{
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_AND, INTEGER_REDEFINED_OP_FLAG)) {
+ return LONG2NUM(FIX2LONG(recv) & FIX2LONG(obj));
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+vm_opt_or(VALUE recv, VALUE obj)
+{
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_OR, INTEGER_REDEFINED_OP_FLAG)) {
+ return LONG2NUM(FIX2LONG(recv) | FIX2LONG(obj));
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
vm_opt_aref(VALUE recv, VALUE obj)
{
if (SPECIAL_CONST_P(recv)) {