After 5e86b005c0, I now think ANYARGS is
dangerous and should be extinct. This commit deletes ANYARGS from
struct vm_ifunc, but in doing so we also have to decouple the usage
of this struct in compile.c, which (I think) is an abuse of ANYARGS.
This was an intentional bug added in 1.9.
The approach taken here is to add a second operand to the
getconstant instruction for whether nil should be allowed and
treated as current scope.
Fixes [Bug #11718]
Methods on duplicated class/module refer same constant inline
cache (IC). Constant access lookup should be done for cloned
class/modules but inline cache doesn't check it.
To check it, this patch introduce new RCLASS_CLONED flag which
are set when if class/module is cloned (both orig and dst).
[Bug #15877]
only when its receiver and the argument are both Integers.
Since 6bedbf4625, Integer#[] has supported a range extraction.
This means that Integer#[] now accepts multiple arguments, which made
the method very slow unfortunately.
This change fixes the performance issue by adding a special handling for
its traditional use case: `num[idx]` where both `num` and `idx` are
Integers.
* internal.h (UNALIGNED_MEMBER_ACCESS, UNALIGNED_MEMBER_PTR):
moved from eval_intern.h.
* compile.c iseq.c, vm.c: use UNALIGNED_MEMBER_PTR for `entries`
in `struct iseq_catch_table`.
* vm_eval.c, vm_insnhelper.c: use UNALIGNED_MEMBER_PTR for `body`
in `rb_method_definition_t`.
ec->cfp->iseq might not exist at the very beginning of a thread.
=================================================================
==82954==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7fc86f334810 at pc 0x55ceaf013125 bp 0x7ffe2eddbbf0 sp 0x7ffe2eddbbe8
READ of size 8 at 0x7fc86f334810 thread T0
#0 0x55ceaf013124 in vm_check_canary vm_insnhelper.c:217:24
#1 0x55ceaefb4796 in vm_push_frame vm_insnhelper.c:276:5
#2 0x55ceaf0124bd in th_init vm.c:2661:5
#3 0x55ceaf00d5eb in ruby_thread_init vm.c:2690:5
#4 0x55ceaf00d4b1 in rb_thread_alloc vm.c:2703:5
#5 0x55ceaef0038b in thread_s_new thread.c:872:20
#6 0x55ceaf04d8c1 in call_cfunc_m1 vm_insnhelper.c:2041:12
#7 0x55ceaf03118d in vm_call_cfunc_with_frame vm_insnhelper.c:2207:11
#8 0x55ceaf017985 in vm_call_cfunc vm_insnhelper.c:2225:12
#9 0x55ceaf01548b in vm_call_method_each_type vm_insnhelper.c:2560:9
#10 0x55ceaf014c96 in vm_call_method vm_insnhelper.c:2686:13
#11 0x55ceaefb5de4 in vm_call_general vm_insnhelper.c:2730:12
#12 0x55ceaf03c868 in vm_sendish vm_insnhelper.c:3623:11
#13 0x55ceaefc95bb in vm_exec_core insns.def:771:11
#14 0x55ceaf006700 in rb_vm_exec vm.c:1892:22
#15 0x55ceaf00acbf in rb_iseq_eval_main vm.c:2151:11
#16 0x55ceaea250ca in ruby_exec_internal eval.c:262:2
#17 0x55ceaea2498b in ruby_exec_node eval.c:326:12
#18 0x55ceaea247d0 in ruby_run_node eval.c:318:25
#19 0x55ceae88c486 in main main.c:42:9
#20 0x7fc874330b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
#21 0x55ceae7e5289 in _start (miniruby+0x15f289)
0x7fc86f334810 is located 16 bytes to the right of 1048576-byte region [0x7fc86f234800,0x7fc86f334800)
allocated by thread T0 here:
#0 0x55ceae85d56d in malloc (miniruby+0x1d756d)
#1 0x55ceaea71d12 in objspace_xmalloc0 gc.c:9416:5
#2 0x55ceaea71cd2 in ruby_xmalloc2_body gc.c:9623:12
#3 0x55ceaea7d09c in ruby_xmalloc2 gc.c:11479:12
#4 0x55ceaf00c3b7 in rb_thread_recycle_stack vm.c:2462:12
#5 0x55ceaf012256 in th_init vm.c:2656:29
#6 0x55ceaf00d5eb in ruby_thread_init vm.c:2690:5
#7 0x55ceaf00d4b1 in rb_thread_alloc vm.c:2703:5
#8 0x55ceaef0038b in thread_s_new thread.c:872:20
#9 0x55ceaf04d8c1 in call_cfunc_m1 vm_insnhelper.c:2041:12
#10 0x55ceaf03118d in vm_call_cfunc_with_frame vm_insnhelper.c:2207:11
#11 0x55ceaf017985 in vm_call_cfunc vm_insnhelper.c:2225:12
#12 0x55ceaf01548b in vm_call_method_each_type vm_insnhelper.c:2560:9
#13 0x55ceaf014c96 in vm_call_method vm_insnhelper.c:2686:13
#14 0x55ceaefb5de4 in vm_call_general vm_insnhelper.c:2730:12
#15 0x55ceaf03c868 in vm_sendish vm_insnhelper.c:3623:11
#16 0x55ceaefc95bb in vm_exec_core insns.def:771:11
#17 0x55ceaf006700 in rb_vm_exec vm.c:1892:22
#18 0x55ceaf00acbf in rb_iseq_eval_main vm.c:2151:11
#19 0x55ceaea250ca in ruby_exec_internal eval.c:262:2
#20 0x55ceaea2498b in ruby_exec_node eval.c:326:12
#21 0x55ceaea247d0 in ruby_run_node eval.c:318:25
#22 0x55ceae88c486 in main main.c:42:9
#23 0x7fc874330b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
SUMMARY: AddressSanitizer: heap-buffer-overflow vm_insnhelper.c:217:24 in vm_check_canary
Shadow bytes around the buggy address:
0x0ff98de5e8b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ff98de5e8c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ff98de5e8d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ff98de5e8e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0ff98de5e8f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0ff98de5e900: fa fa[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0ff98de5e910: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0ff98de5e920: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0ff98de5e930: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0ff98de5e940: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0ff98de5e950: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==82954==ABORTING
When reviewing r66565, I overlooked that `GET_ISEQ()` and `GET_EP()` are
NOT `ec->cfp->iseq` and `ec->cfp->ep` but `reg_cfp->iseq` and
`reg_cfp->ep`.
`vm_push_frame` updates `ec->cfp` and in this case we want to check the
callee's cfp and so `ec->cfp` should be checked instead.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67522 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* 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
cfp->bp was (re-)introduced by Kokubun san, but VM doesn't use it
because I (ko1) want to remove it in a future. But using it make
leave instruction fast because of sp consisntency check.
So now VM uses cfp->bp.
To use cfp->bp, I checked the value and I found that it is not a
"initial value of sp" but a "initial value of ep". Fix this problem
and fix all bp references (this is why bp is renamed to bp_).
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67342 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Add counters to count ccf (call cache fastpath) usage.
These counters will help which kind of method dispatch
is important to optimize.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67336 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
similar idea to r67315, provide the following optimization
for method dispatch with lead and kw parameters.
(1) add a special branch to check passing kw arguments to
a method which has lead and kw parameters.
ex) def foo(x, k:1); end; foo(0, k:1)
(2) add a special branch to check passing no-kw arguments to
a method which has lead and kw parameters.
ex) def foo(x, k:1); end; foo(0)
For (1) and (2) cases, provide special dispatchers. For (2) case,
this patch only use the special dispatcher if all default
kw parameters are literal values (nil, 1, and so on. In other case,
kw->default_values does not contains Qundef) (and no required kw
parameters becaseu they don't pass any keyword parameters).
Passing keyword arguments with a hash object is not a scope of
this patch.
Without this patch, (1) and (2) cases use `setup_parameters_complex()`.
Especially, (2) seems frequent case for methods which extend a normal
usecase with keyword parameters (like: `exception: true`).
We can measure the performance with benchmark-driver:
With methods: def kw k1:1, k2:2; end
def m; end
With the following binaries:
clean-miniruby: unmodified trunk.
opt_miniruby1: use special branches for lead/kw parameters.
opt_miniruby2: use special dispatchers for lead/kw parameters.
opt_cc_miniruby: apply step (2).
Result with benchmark-driver:
m
opt_miniruby2: 75222278.0 i/s
clean-miniruby: 73177896.5 i/s - 1.03x slower
opt_miniruby1: 62466783.3 i/s - 1.20x slower
kw
opt_miniruby2: 52044504.4 i/s
opt_miniruby1: 29142025.7 i/s - 1.79x slower
clean-miniruby: 20515235.4 i/s - 2.54x slower
kw k1: 10
opt_miniruby2: 26492219.5 i/s
opt_miniruby1: 25409484.9 i/s - 1.04x slower
clean-miniruby: 20235113.7 i/s - 1.31x slower
kw k1: 10, k2: 20
opt_miniruby1: 24159534.0 i/s
opt_miniruby2: 23470527.5 i/s - 1.03x slower
clean-miniruby: 17822621.5 i/s - 1.36x slower
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67333 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
because it's not used outside vm*.c, and also having non-static function
without MJIT_STATIC is harmful for mswin JIT system.
I hope this fix mswin test failure starting from r67315.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67328 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
There is a special optimization for "only lead parameters"
method dispatch using specialized dispatcher functions
`vm_call_iseq_setup_normal_0start...`.
Other cases (opt, rest, post, ...) we don't use specialized
dispatcher and call with `setup_parameters_complex` to
satisfy Ruby's complex parameter specification.
This commit introduce a specialize dispatcher for
methods which use only lead and optional parameters.
Two step improvements:
(1) prepare "lead/opt" only check pass.
It is to skip the `setup_parameters_complex` function.
(2) introduce specialized dispatcher for only "lead/opt"
parameters methods (vm_call_iseq_setup_normal_opt_start).
With these improvements, we achieved good micro-benchmark
results:
With a method: `def opt2 a, b=nil; end`
With the following binaries:
clean-miniruby: unmodified trunk.
opt_miniruby: apply step (1).
opt_cc_miniruby: apply step (2).
Result with benchmark-driver:
opt2(1)
opt_cc_miniruby: 42269409.1 i/s
opt_miniruby: 36304428.3 i/s - 1.16x slower
clean-miniruby: 25897409.5 i/s - 1.63x slower
opt2(1, 2)
opt_cc_miniruby: 45935145.7 i/s
opt_miniruby: 40513196.9 i/s - 1.13x slower
clean-miniruby: 29976057.6 i/s - 1.53x slower
This improvement may be trivial (difficult to improve practical
cases). However, this is enough small patch so I decide to
introduce it.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67315 b2dd03c8-39d4-4d8f-98ff-823fe69b080e