* insns.def: add definemethod and definesmethod (singleton method)
instructions. Old YARV contains these instructions, but it is moved
to methods of FrozenCore class because remove number of instructions
can improve performance for some techniques (static stack caching
and so on). However, we don't employ these technique and it is hard
to optimize/analysis definition sequence. So I decide to introduce
them (and remove definition methods). `putiseq` insn is also removed.
* vm_method.c (rb_scope_visibility_get): renamed to
`vm_scope_visibility_get()` and make it accept `ec`.
Same for `vm_scope_module_func_check()`.
These fixes are result of refactoring `vm_define_method`.
* vm_insnhelper.c (rb_vm_get_cref): renamed to `vm_get_cref`
because of consistency with other functions.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67442 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
related: r66982
Sadly opt_regexpmatch2 was not a leaf insn either.
http://ci.rvm.jp/results/trunk-vm-asserts@silicon-docker/1751213
CHECK_INTERRUPT_IN_MATCH_AT is just like RUBY_VM_CHECK_INTS, and it may
call arbitrary Ruby method, for example a GC finalizer from postponed
job in this case.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67091 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Given `str`, if `str_coderange(str)` is `ENC_CODERANGE_BROKEN`,
it calls `rb_raise`. And it calls `rb_funcallv` from `rb_exc_new3`.
http://ci.rvm.jp/results/trunk-vm-asserts@silicon-docker/1673244
Maybe we can have a function to directly call `exc_initialize` for this
purpose, but it may not be worth having such a function for keeping the
instruction leaf. We may even want to delete the insn
https://github.com/ruby/ruby/pull/1959.
I'm not sure whether compile.c could generate opt_regexpmatch2 for
invalid coderange string. Let's monitor that for a while.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66982 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
These instructions were missed before. The stack canary mechanism
(see r64677) can not detect rb_raise() because exceptions jump over
the canary liveness check.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66980 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
They are considered Array and Hash creation events, so
allow dtrace (and systemtap) to track those creations.
Co-Authored-By: Eric Wong <e@80x24.org>
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66767 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
- FIXNUM_2_P: moved to vm_insnhelper.c because that is the only
place this macro is used.
- FLONUM_2_P: ditto.
- FLOAT_HEAP_P: not used anywhere.
- FLOAT_INSTANCE_P: ditto.
- GET_TOS: ditto.
- USE_IC_FOR_SPECIALIZED_METHOD: ditto.
- rb_obj_hidden_p: ditto.
- REG_A: ditto.
- REG_B: ditto.
- GET_CONST_INLINE_CACHE: ditto.
- vm_regan_regtype: moved inside of VM_COLLECT_USAGE_DETAILS
because that os the only place this enum is used.
- vm_regan_acttype: ditto.
- GET_GLOBAL: used only once. Removed with replacing that usage.
- SET_GLOBAL: ditto.
- rb_method_definition_create: declaration moved to
vm_insnhelper.c because that is the only place this declaration
makes sense.
- rb_method_definition_set: ditto.
- rb_method_definition_eq: ditto.
- rb_make_no_method_exception: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66597 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Just add more room for comments. This is a pure refactoring that does
not change anything but readability.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66564 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
The instructions are just for optimization. To clarity the intention,
this change adds the prefix "opt_", like "opt_case_dispatch".
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65600 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
In these expressions `1` is of type `signed int` (cf: ISO/IEC
9899:1990 section 6.1.3.2). The variable (e.g. `num`) is of type
`rb_num_t`, which is in fact `unsigned long`. These two expressions
then exercises the "usual arithmetic conversions" (cf: ISO/IEC
9899:1990 section 6.2.1.5) and both eventually become `unsigned long`.
The two unsigned expressions are then subtracted to generate another
unsigned integer expression (cf: ISO/IEC 9899:1990 section 6.3.6).
This is where integer overflows can occur. OTOH the left hand side of
the assignments are `rb_snum_t` which is `signed long`. The
assignments exercise the "implicit conversion" of "an unsigned integer
is converted to its corresponding signed integer" case (cf: ISO/IEC
9899:1990 section 6.2.1.2), which is "implementation-defined" (read:
not portable).
Casts are the proper way to avoid this problem. Because all
expressions are converted to some integer types before any binary
operations are performed, the assignments now have fully defined
behaviour. These values can never exceed LONG_MAX so the casts must
not lose any information.
See also: https://travis-ci.org/ruby/ruby/jobs/451726874#L4357
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65595 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* transient_heap.c, transient_heap.h: implement TransientHeap (theap).
theap is designed for Ruby's object system. theap is like Eden heap
on generational GC terminology. theap allocation is very fast because
it only needs to bump up pointer and deallocation is also fast because
we don't do anything. However we need to evacuate (Copy GC terminology)
if theap memory is long-lived. Evacuation logic is needed for each type.
See [Bug #14858] for details.
* array.c: Now, theap for T_ARRAY is supported.
ary_heap_alloc() tries to allocate memory area from theap. If this trial
sccesses, this array has theap ptr and RARRAY_TRANSIENT_FLAG is turned on.
We don't need to free theap ptr.
* ruby.h: RARRAY_CONST_PTR() returns malloc'ed memory area. It menas that
if ary is allocated at theap, force evacuation to malloc'ed memory.
It makes programs slow, but very compatible with current code because
theap memory can be evacuated (theap memory will be recycled).
If you want to get transient heap ptr, use RARRAY_CONST_PTR_TRANSIENT()
instead of RARRAY_CONST_PTR(). If you can't understand when evacuation
will occur, use RARRAY_CONST_PTR().
(re-commit of r65444)
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65449 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* transient_heap.c, transient_heap.h: implement TransientHeap (theap).
theap is designed for Ruby's object system. theap is like Eden heap
on generational GC terminology. theap allocation is very fast because
it only needs to bump up pointer and deallocation is also fast because
we don't do anything. However we need to evacuate (Copy GC terminology)
if theap memory is long-lived. Evacuation logic is needed for each type.
See [Bug #14858] for details.
* array.c: Now, theap for T_ARRAY is supported.
ary_heap_alloc() tries to allocate memory area from theap. If this trial
sccesses, this array has theap ptr and RARRAY_TRANSIENT_FLAG is turned on.
We don't need to free theap ptr.
* ruby.h: RARRAY_CONST_PTR() returns malloc'ed memory area. It menas that
if ary is allocated at theap, force evacuation to malloc'ed memory.
It makes programs slow, but very compatible with current code because
theap memory can be evacuated (theap memory will be recycled).
If you want to get transient heap ptr, use RARRAY_CONST_PTR_TRANSIENT()
instead of RARRAY_CONST_PTR(). If you can't understand when evacuation
will occur, use RARRAY_CONST_PTR().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65444 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
The idea behind this commit is that handles_sp and leaf are two
concepts that are not mutually independent. By making one explicitly
depend another, we can reduces the number of lines of codes written,
thus making things concise.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65426 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (newhashfromarray): `rb_hash_bulk_insert()` can call
Ruby methods like #hash so that it should not be a leaf insn.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65345 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
The instructions were used only for branch coverage.
Instead, it now uses a trace framework [Feature #14104].
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65225 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* insns.def (opt_send_without_block): reorder insn position because
`opt_str_freeze` insn refer this insn (function) when
OPT_CALL_THREADED_CODE is true.
* vm_opts.h (OPT_THREADED_CODE): introduce new macro to select
threaded code implementation with a compile option (-D...).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64854 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
because r64849 seems to fix issues which we were confused about.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64850 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
as a workaround to fix the build pipeline broken by r64824,
because optimizing Ruby should be prioritized higher than supporting unused jokes.
In the current build system, exceeding 200 insns somehow crashes C
extension build on some of MinGW environments like "mingw32-make[1]:
*** No rule to make target 'note'. Stop."
https://ci.appveyor.com/project/ruby/ruby/build/9725/job/co4nu9jugm8qwdrp
and on some of Linux environments like "cannot load such file -- stringio (LoadError)"
```
build_install /home/ko1/ruby/src/trunk_gcc5/lib/rubygems/specification.rb:18:in `require': cannot load such file -- stringio (LoadError)
from /home/ko1/ruby/src/trunk_gcc5/lib/rubygems/specification.rb:18:in `<top (required)>'
from /home/ko1/ruby/src/trunk_gcc5/lib/rubygems.rb:1365:in `require'
from /home/ko1/ruby/src/trunk_gcc5/lib/rubygems.rb:1365:in `<module:Gem>'
from /home/ko1/ruby/src/trunk_gcc5/lib/rubygems.rb:116:in `<top (required)>'
from /home/ko1/ruby/src/trunk_gcc5/tool/rbinstall.rb:24:in `require'
from /home/ko1/ruby/src/trunk_gcc5/tool/rbinstall.rb:24:in `<main>'
make: *** [do-install-nodoc] Error 1
```
http://ci.rvm.jp/results/trunk_gcc5@silicon-docker/1353447
This commit removes "bitblt" and "trace_bitblt" insns, which reduces the
number of insns from 202 to 200 and fixes at least the latter build
failure. I hope this fixes the MinGW build failure as well. Let me
confirm the situation on AppVeyor CI.
Note that this is hard to fix because some MinGW environments (MSP-Greg's
MinGW CI on AppVeyor) don't reproduce this and some Linux environments
(including my local machine) don't reproduce it either. Make sure you
have the reproductive environment and confirm it's fixed when reverting
this commit.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64839 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
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
not optimizing Array#& and Array#| because vm_insnhelper.c can't easily
inline it (large amount of array.c code would be needed in vm_insnhelper.c)
and the method body is a little complicated compared to Integer's ones.
So I thought only Integer#& and Integer#| have a significant impact,
and eliminating unnecessary branches would contribute to JIT's performance.
vm_insnhelper.c: ditto
tool/transform_mjit_header.rb: make sure these instructions are inlined
on JIT.
compile.c: compile vm_opt_and and vm_opt_or.
id.def: define id for them to be used in compile.c and vm*.c
vm.c: track redefinition of Integer#& and Integer#|
vm_core.h: allow detecting redefinition of & and |
test/ruby/test_jit.rb: test new insns
test/ruby/test_optimization.rb: ditto
* Optcarrot benchmark
This is a kind of experimental thing but I'm committing this since the
performance impact is significant especially on Optcarrot with JIT.
$ benchmark-driver benchmark.yml --rbenv 'before::before --disable-gems;before+JIT::before --disable-gems --jit;after::after --disable-gems;after+JIT::after --disable-gems --jit' -v --repeat-count 24
before: ruby 2.6.0dev (2018-09-24 trunk 64821) [x86_64-linux]
before+JIT: ruby 2.6.0dev (2018-09-24 trunk 64821) +JIT [x86_64-linux]
after: ruby 2.6.0dev (2018-09-24 opt_and 64821) [x86_64-linux]
last_commit=opt_or
after+JIT: ruby 2.6.0dev (2018-09-24 opt_and 64821) +JIT [x86_64-linux]
last_commit=opt_or
Calculating -------------------------------------
before before+JIT after after+JIT
Optcarrot Lan_Master.nes 51.460 66.315 53.023 71.173 fps
Comparison:
Optcarrot Lan_Master.nes
after+JIT: 71.2 fps
before+JIT: 66.3 fps - 1.07x slower
after: 53.0 fps - 1.34x slower
before: 51.5 fps - 1.38x slower
[close https://github.com/ruby/ruby/pull/1963]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64824 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Now that we can say for sure if an instruction calls a method or
not internally, it is now possible to reroute the bugs that
forced us to revert the "move PC around" optimization.
First try: r62051
Reverted: r63763
See also: r63999
----
trunk: ruby 2.6.0dev (2018-09-13 trunk 64736) [x86_64-darwin15]
ours: ruby 2.6.0dev (2018-09-13 trunk 64736) [x86_64-darwin15]
last_commit=move ADD_PC around (take 2)
Calculating -------------------------------------
trunk ours
so_ackermann 1.884 2.278 i/s - 1.000 times in 0.530926s 0.438935s
so_array 1.178 1.157 i/s - 1.000 times in 0.848786s 0.864467s
so_binary_trees 0.176 0.177 i/s - 1.000 times in 5.683895s 5.657707s
so_concatenate 0.220 0.221 i/s - 1.000 times in 4.546896s 4.518949s
so_count_words 6.729 6.470 i/s - 1.000 times in 0.148602s 0.154561s
so_exception 3.324 3.688 i/s - 1.000 times in 0.300872s 0.271147s
so_fannkuch 0.546 0.968 i/s - 1.000 times in 1.831328s 1.033376s
so_fasta 0.541 0.547 i/s - 1.000 times in 1.849923s 1.827091s
so_k_nucleotide 0.800 0.777 i/s - 1.000 times in 1.250635s 1.286295s
so_lists 2.101 1.848 i/s - 1.000 times in 0.475954s 0.541095s
so_mandelbrot 0.435 0.408 i/s - 1.000 times in 2.299328s 2.450535s
so_matrix 1.946 1.912 i/s - 1.000 times in 0.513872s 0.523076s
so_meteor_contest 0.311 0.317 i/s - 1.000 times in 3.219297s 3.152052s
so_nbody 0.746 0.703 i/s - 1.000 times in 1.339815s 1.423441s
so_nested_loop 0.899 0.901 i/s - 1.000 times in 1.111767s 1.109555s
so_nsieve 0.559 0.579 i/s - 1.000 times in 1.787763s 1.726552s
so_nsieve_bits 0.435 0.428 i/s - 1.000 times in 2.296282s 2.333852s
so_object 1.368 1.442 i/s - 1.000 times in 0.731237s 0.693684s
so_partial_sums 0.616 0.546 i/s - 1.000 times in 1.623592s 1.833097s
so_pidigits 0.831 0.832 i/s - 1.000 times in 1.203117s 1.202334s
so_random 2.934 2.724 i/s - 1.000 times in 0.340791s 0.367150s
so_reverse_complement 0.583 0.866 i/s - 1.000 times in 1.714144s 1.154615s
so_sieve 1.829 2.081 i/s - 1.000 times in 0.546607s 0.480562s
so_spectralnorm 0.524 0.558 i/s - 1.000 times in 1.908716s 1.792382s
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64737 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
String#freeze can be redefined to be destructive. While such
redefinition is definitely weird, it should be possible. Resurrect
the string to prepare for that sort of things.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64691 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Simply use DISPATCH_ORIGINAL_INSN instead of rb_funcall. This is,
when possible, overall performant because method dispatch results are
cached inside of CALL_CACHE. Should also be good for JIT.
----
trunk: ruby 2.6.0dev (2018-09-12 trunk 64689) [x86_64-darwin15]
ours: ruby 2.6.0dev (2018-09-12 leaf-insn 64688) [x86_64-darwin15]
last_commit=make opt_str_freeze leaf
Calculating -------------------------------------
trunk ours
vm2_freezestring 5.440M 31.411M i/s - 6.000M times in 1.102968s 0.191017s
Comparison:
vm2_freezestring
ours: 31410864.5 i/s
trunk: 5439865.4 i/s - 5.77x slower
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64690 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This instruction can be written without rb_funcall. It not only boosts
performance of case statements, but also makes room of future JIT
improvements. Because opt_case_dispatch is about optimization this
should not be a bad thing to have.
----
trunk: ruby 2.6.0dev (2018-09-05 trunk 64634) [x86_64-darwin15]
ours: ruby 2.6.0dev (2018-09-12 leaf-insn 64688) [x86_64-darwin15]
last_commit=make opt_case_dispatch leaf
Calculating -------------------------------------
trunk ours
vm2_case_lit 1.366 2.012 i/s - 1.000 times in 0.731839s 0.497008s
Comparison:
vm2_case_lit
ours: 2.0 i/s
trunk: 1.4 i/s - 1.47x slower
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64689 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
An instruction is leaf if it has no rb_funcall inside. In order to
check this property, we introduce stack canary which is a random
number collected at runtime. Stack top is always filled with this
number and checked for stack smashing operations, when VM_CHECK_MODE.
[GH-1947]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64677 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
_mjit_compile_send.erb: simplify code using the change
insns.def: adapt to the interface change
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64281 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This is just a refactoring.
The receiver of "invokesuper" was a boolean to represent if it is ZSUPER
or not. This was used in vm_search_super_method to prohibit ZSUPER call
in define_method. (It is currently prohibited because of the limitation
of the implementation.)
This change removes the hack by introducing an explicit flag,
VM_CALL_SUPER, to signal the information. Now, the implementation of
"invokesuper" is consistent with "send" instruction.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64268 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
because it's more suitable to describe the current behavior now.
tool/ruby_vm/models/bare_instructions.rb: ditto.
tool/ruby_vm/views/_insn_entry.erb: ditto.
tool/ruby_vm/views/_mjit_compile_insn_body.erb: ditto.
tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64053 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
By the way, the original patch of r63988 was provided by wanabe:
https://github.com/wanabe/ruby/tree/local-stack
but I forgot to add his credit in the previous commit message.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63990 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This optimization was reverted on r63863, but this commit resurrects the
optimization to skip some sp motions on JIT execution.
tool/ruby_vm/views/_mjit_compile_insn_body.erb: ditto
tool/ruby_vm/views/_mjit_compile_insn.erb: ditto
insns.def: resurrect handles_frame as handles_stack, which was deleted
on r63763.
tool/ruby_vm/models/bare_instructions.rb: ditto
vm_insnhelper.c: prevent moving sp outside insns.def to allow modifying
it by JIT.
* Optcarrot benchmark
$ benchmark-driver benchmark.yml --rbenv 'before --jit;after --jit' --repeat-count 12 -v
before --jit: ruby 2.6.0dev (2018-07-17 trunk 63987) +JIT [x86_64-linux]
after --jit: ruby 2.6.0dev (2018-07-17 local-stack 63987) +JIT [x86_64-linux]
last_commit=mjit_compile.c: resurrect local variable stack
Calculating -------------------------------------
before --jit after --jit
Optcarrot Lan_Master.nes 70.518 72.144 fps
Comparison:
Optcarrot Lan_Master.nes
after --jit: 72.1 fps
before --jit: 70.5 fps - 1.02x slower
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63988 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
r63655 was tightly coupled to handle_frames and some assumptions seems
to have been broken by r63763.
To partially resolve Bug#14892, this reverts the optimization for now. I
want to make MJIT CI happy first and then I'll probably retry r63655 by
partially reverting r63763 for sp changes.
The skipped test is not fixed yet.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63863 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
I introduced this mechanism in r62051 to speed things up. Later it
was reported that the change causes problems. I searched for
workarounds but nothing seemed appropriate. I hereby officially
give it up. The idea to move ADD_PC around was a mistake.
Fixes [Bug #14809] and [Bug #14834].
Signed-off-by: Urabe, Shyouhei <shyouhei@ruby-lang.org>
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63763 b2dd03c8-39d4-4d8f-98ff-823fe69b080e