Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 82c0cb9

Browse files
committed
Add a specialized instruction for .nil? calls
This commit adds a specialized instruction for called to `.nil?`. It is about 27% faster than master. Here is a benchmark: ``` [aaron@TC ~/g/ruby (specialized-nilp)]$ cat compil.rb require "benchmark/ips" not_nil = Object.new xnil = nil Benchmark.ips do |x| x.report("nil?") { xnil.nil? } x.report("not nil") { not_nil.nil? } end ``` On Ruby master: ``` [aaron@TC ~/g/ruby (master)]$ ./ruby compil.rb Warming up -------------------------------------- nil? 450.695k i/100ms not nil 443.863k i/100ms Calculating ------------------------------------- nil? 20.829M (± 7.6%) i/s - 103.660M in 5.015627s not nil 20.700M (± 7.9%) i/s - 102.976M in 5.015786s [aaron@TC ~/g/ruby (master)]$ ./ruby compil.rb Warming up -------------------------------------- nil? 412.899k i/100ms not nil 420.359k i/100ms Calculating ------------------------------------- nil? 17.882M (±15.1%) i/s - 87.122M in 5.010014s not nil 18.445M (± 7.6%) i/s - 91.638M in 5.006561s [aaron@TC ~/g/ruby (master)]$ ./ruby compil.rb Warming up -------------------------------------- nil? 423.562k i/100ms not nil 446.841k i/100ms Calculating ------------------------------------- nil? 20.547M (± 7.8%) i/s - 102.078M in 5.009083s not nil 20.050M (±12.8%) i/s - 98.305M in 5.007470s ``` On this branch: ``` [aaron@TC ~/g/ruby (specialized-nilp)]$ ./ruby compil.rb Warming up -------------------------------------- nil? 475.495k i/100ms not nil 406.826k i/100ms Calculating ------------------------------------- nil? 27.379M (±12.1%) i/s - 134.565M in 5.009041s not nil 26.911M (± 8.0%) i/s - 133.439M in 5.001739s [aaron@TC ~/g/ruby (specialized-nilp)]$ ./ruby compil.rb Warming up -------------------------------------- nil? 448.738k i/100ms not nil 443.743k i/100ms Calculating ------------------------------------- nil? 27.265M (±12.4%) i/s - 133.724M in 5.004383s not nil 27.125M (± 5.8%) i/s - 135.342M in 5.012178s [aaron@TC ~/g/ruby (specialized-nilp)]$ ./ruby compil.rb Warming up -------------------------------------- nil? 461.641k i/100ms not nil 465.173k i/100ms Calculating ------------------------------------- nil? 27.170M (±12.3%) i/s - 133.414M in 5.008517s not nil 26.930M (± 8.6%) i/s - 133.505M in 5.006783s ```
1 parent c9b74f9 commit 82c0cb9

File tree

7 files changed

+39
-1
lines changed

7 files changed

+39
-1
lines changed

compile.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3251,6 +3251,7 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
32513251
case idLength: SP_INSN(length); return COMPILE_OK;
32523252
case idSize: SP_INSN(size); return COMPILE_OK;
32533253
case idEmptyP: SP_INSN(empty_p);return COMPILE_OK;
3254+
case idNilP: SP_INSN(nil_p);return COMPILE_OK;
32543255
case idSucc: SP_INSN(succ); return COMPILE_OK;
32553256
case idNot: SP_INSN(not); return COMPILE_OK;
32563257
}

defs/id.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ firstline, predefined = __LINE__+1, %[\
33
max
44
min
55
freeze
6+
nil?
67
inspect
78
intern
89
object_id

insns.def

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,20 @@ opt_str_freeze
808808
}
809809
}
810810

811+
/* optimized empty? */
812+
DEFINE_INSN
813+
opt_nil_p
814+
(CALL_INFO ci, CALL_CACHE cc)
815+
(VALUE recv)
816+
(VALUE val)
817+
{
818+
val = vm_opt_nil_p(ci, cc, recv);
819+
820+
if (val == Qundef) {
821+
CALL_SIMPLE_METHOD();
822+
}
823+
}
824+
811825
DEFINE_INSN
812826
opt_str_uminus
813827
(VALUE str, CALL_INFO ci, CALL_CACHE cc)

object.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1664,7 +1664,7 @@ rb_true(VALUE obj)
16641664
*/
16651665

16661666

1667-
static VALUE
1667+
VALUE
16681668
rb_false(VALUE obj)
16691669
{
16701670
return Qfalse;

vm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,6 +1657,7 @@ vm_init_redefined_flag(void)
16571657
OP(Call, CALL), (C(Proc));
16581658
OP(And, AND), (C(Integer));
16591659
OP(Or, OR), (C(Integer));
1660+
OP(NilP, NIL_P), (C(NilClass));
16601661
#undef C
16611662
#undef OP
16621663
}

vm_core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ enum ruby_basic_operators {
547547
BOP_LENGTH,
548548
BOP_SIZE,
549549
BOP_EMPTY_P,
550+
BOP_NIL_P,
550551
BOP_SUCC,
551552
BOP_GT,
552553
BOP_GE,

vm_insnhelper.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4239,6 +4239,26 @@ vm_opt_empty_p(VALUE recv)
42394239
}
42404240
}
42414241

4242+
VALUE rb_false(VALUE obj);
4243+
4244+
static VALUE
4245+
vm_opt_nil_p(CALL_INFO ci, CALL_CACHE cc, VALUE recv)
4246+
{
4247+
if (recv == Qnil) {
4248+
if (BASIC_OP_UNREDEFINED_P(BOP_NIL_P, NIL_REDEFINED_OP_FLAG)) {
4249+
return Qtrue;
4250+
} else {
4251+
return Qundef;
4252+
}
4253+
} else {
4254+
if (vm_method_cfunc_is(ci, cc, recv, rb_false)) {
4255+
return Qfalse;
4256+
} else {
4257+
return Qundef;
4258+
}
4259+
}
4260+
}
4261+
42424262
static VALUE
42434263
fix_succ(VALUE x)
42444264
{

0 commit comments

Comments
 (0)