1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

_mjit_compile_send.erb: inline attr_reader call

_mjit_compile_send_guard.erb: carve out the shared logic to invalidate
inlined method call

common.mk: update dependency for this change

test_jit.rb: add test for attr_reader optimization

* Benchmark

```
require 'benchmark_driver'

Benchmark.driver do |x|
  x.prelude %{
    class C
      attr_reader :a
      def initialize
        @a = 1
      end
    end

    o = C.new

    def l o
      i = 0
      while i < 1000000
        o.a
        i += 1
      end
    end
  }
  x.report 'aread', %{ l o }
  x.loop_count 1000

  x.rbenv 'before', 'before,--jit', 'after,--jit'
  x.verbose
end
```

```
before: ruby 2.6.0dev (2018-04-20 trunk 63211) [x86_64-linux]
before,--jit: ruby 2.6.0dev (2018-04-20 trunk 63211) +JIT [x86_64-linux]
after,--jit: ruby 2.6.0dev (2018-04-20 trunk 63211) +JIT [x86_64-linux]
last_commit=_mjit_compile_send.erb: inline attr_reader call
Calculating -------------------------------------
                         before  before,--jit  after,--jit
               aread     54.597       122.894      218.574 i/s -      1.000k times in 18.316102s 8.137089s 4.575106s

Comparison:
                            aread
         after,--jit:       218.6 i/s
        before,--jit:       122.9 i/s - 1.78x  slower
              before:        54.6 i/s - 4.00x  slower

```

* Optcarrot

A little made faster?

fps: 71.35 -> 72.11

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63212 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
k0kubun 2018-04-20 13:42:08 +00:00
parent 1658fb3f83
commit e72a86fc93
4 changed files with 67 additions and 7 deletions

View file

@ -924,6 +924,7 @@ $(srcs_vpath)vmtc.inc: $(srcdir)/tool/ruby_vm/views/vmtc.inc.erb
$(srcs_vpath)vm.inc: $(srcdir)/tool/ruby_vm/views/vm.inc.erb
$(srcs_vpath)mjit_compile.inc: $(srcdir)/tool/ruby_vm/views/mjit_compile.inc.erb \
$(srcdir)/tool/ruby_vm/views/_mjit_compile_insn.erb $(srcdir)/tool/ruby_vm/views/_mjit_compile_send.erb \
$(srcdir)/tool/ruby_vm/views/_mjit_compile_send_guard.erb \
$(srcdir)/tool/ruby_vm/views/_mjit_compile_insn_body.erb $(srcdir)/tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb
common-srcs: $(srcs_vpath)parse.c $(srcs_vpath)lex.c $(srcs_vpath)enc/trans/newline.c $(srcs_vpath)id.c \

View file

@ -529,6 +529,41 @@ class TestJIT < Test::Unit::TestCase
end;
end
def test_attr_reader
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "4nil\nnil\n6", success_count: 2, min_calls: 2)
begin;
class A
attr_reader :a, :b
def initialize
@a = 2
end
def test
a
end
def undefined
b
end
end
a = A.new
print(a.test * a.test)
p(a.undefined)
p(a.undefined)
# redefinition
class A
def test
3
end
end
print(2 * a.test)
end;
end
private
# The shortest way to test one proc

View file

@ -29,16 +29,12 @@
fprintf(f, " MAYBE_UNUSED(unsigned int) stack_size = %u;\n", b->stack_size);
}
% # JIT: Invalidate call cache if it requires vm_search_method. This allows to inline some of following things.
<%= render 'mjit_compile_send_guard' -%>
% # JIT: move sp and pc if necessary
<%= render 'mjit_compile_pc_and_sp', locals: { insn: insn } -%>
% # JIT: Invalidate call cache if it requires vm_search_method. This allows to inline some of following things.
fprintf(f, " if (UNLIKELY(GET_GLOBAL_METHOD_STATE() != %"PRI_SERIALT_PREFIX"u ||\n", cc->method_state);
fprintf(f, " RCLASS_SERIAL(CLASS_OF(stack[%d])) != %"PRI_SERIALT_PREFIX"u)) {\n", b->stack_size - 1 - argc, cc->class_serial);
fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos);
fprintf(f, " goto cancel;\n");
fprintf(f, " }\n");
% # JIT: Print insn body in insns.def
fprintf(f, " {\n");
fprintf(f, " struct rb_calling_info calling;\n");
@ -88,5 +84,19 @@
fprintf(f, "}\n");
break;
}
% if insn.name == 'opt_send_without_block'
else if (cc->me->def->type == VM_METHOD_TYPE_IVAR) {
% # JIT: Invalidate call cache if it requires vm_search_method. This allows to inline some of following things.
<%= render 'mjit_compile_send_guard' -%>
% # JIT: vm_call_ivar without sp motion
fprintf(f, " stack[%d] = vm_getivar(stack[%d], (ID)0x%"PRIxVALUE", NULL, (CALL_CACHE)0x%"PRIxVALUE", 1);\n",
b->stack_size - argc - 1, b->stack_size - argc - 1, cc->me->def->body.attr.id, (VALUE)cc);
% # compiler: Move JIT compiler's internal stack pointer
b->stack_size += <%= insn.call_attribute('sp_inc') %>;
break;
}
% end
}
}

View file

@ -0,0 +1,14 @@
% # Copyright (c) 2018 Takashi Kokubun. All rights reserved.
% #
% # This file is a part of the programming language Ruby. Permission is hereby
% # granted, to either redistribute and/or modify this file, provided that the
% # conditions mentioned in the file COPYING are met. Consult the file for
% # details.
%
% # JIT: Invalidate call cache if it requires vm_search_method. This allows to inline some of following things.
fprintf(f, " if (UNLIKELY(GET_GLOBAL_METHOD_STATE() != %"PRI_SERIALT_PREFIX"u ||\n", cc->method_state);
fprintf(f, " RCLASS_SERIAL(CLASS_OF(stack[%d])) != %"PRI_SERIALT_PREFIX"u)) {\n", b->stack_size - 1 - argc, cc->class_serial);
fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos);
fprintf(f, " reg_cfp->sp = (VALUE *)reg_cfp->bp + %d;\n", b->stack_size + 1);
fprintf(f, " goto cancel;\n");
fprintf(f, " }\n");