* iseq.c: before this patch, RubyVM::InstructionSequence.of(src) (ISeq in
short) returns different ISeq (wrapper) objects point to one ISeq internal
object. This patch changes this behavior to cache created ISeq (wrapper)
objects and return same ISeq object for an internal ISeq object.
* iseq.h (ISEQ_EXECUTABLE_P): introduced to check executable ISeq objects.
* iseq.h (ISEQ_COMPILE_DATA_ALLOC): reordr setting flag line to avoid
ISEQ_USE_COMPILE_DATA but compiled_data == NULL case.
* vm_core.h (rb_iseq_t): introduce `rb_iseq_t::wrapper` and
`rb_iseq_t::aux::exec`. Move `rb_iseq_t::local_hooks` to
`rb_iseq_t::aux::exec::local_hooks`.
* test/ruby/test_iseq.rb: add ISeq.of() tests.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66246 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
postponed_job is safe to use in signal handlers, but is not
thread-safe for MJIT. Implement a workqueue for MJIT
thread-safety.
[Bug #15316]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66100 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* vm_trace.c: `TracePoint#enable(target_line:)` is supported.
This option enables a hook only at specified target_line.
target_line should be combination with target and :line event.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66008 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* vm_trace.c (rb_tracepoint_enable_for_target): support targetting
TracePoint. [Feature #15289]
Tragetting TracePoint is only enabled on specified method, proc
and so on, example: `tp.enable(target: code)`.
`code` should be consisted of InstructionSeuqnece (iseq)
(RubyVM::InstructionSeuqnece.of(code) should not return nil)
If code is a tree of iseq, TracePoint is enabled on all of
iseqs in a tree.
Enabled tragetting TracePoints can not enabled again with
and without target.
* vm_core.h (rb_iseq_t): introduce `rb_iseq_t::local_hooks`
to store local hooks.
`rb_iseq_t::aux::trace_events` is renamed to
`global_trace_events` to contrast with `local_hooks`.
* vm_core.h (rb_hook_list_t): add `rb_hook_list_t::running`
to represent how many Threads/Fibers are used this list.
If this field is 0, nobody using this hooks and we can
delete it.
This is why we can remove code from cont.c.
* vm_core.h (rb_vm_t): because of above change, we can eliminate
`rb_vm_t::trace_running` field.
Also renamed from `rb_vm_t::event_hooks` to `global_hooks`.
* vm_core.h, vm.c (ruby_vm_event_enabled_global_flags): renamed
from `ruby_vm_event_enabled_flags.
* vm_core.h, vm.c (ruby_vm_event_local_num): added to count
enabled targetting TracePoints.
* vm_core.h, vm_trace.c (rb_exec_event_hooks): accepts
hook list.
* vm_core.h (rb_vm_global_hooks): added for convinience.
* method.h (rb_method_bmethod_t): added to maintain Proc
and `rb_hook_list_t` for bmethod (defined by define_method).
* prelude.rb (TracePoint#enable): extracet a keyword parameter
(because it is easy than writing in C).
It calls `TracePoint#__enable` internal method written in C.
* vm_insnhelper.c (vm_trace): check also iseq->local_hooks.
* vm.c (invoke_bmethod): check def->body.bmethod.hooks.
* vm.c (hook_before_rewind): check iseq->local_hooks
and def->body.bmethod.hooks before rewind by exception.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66003 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
We already use "static inline" heavily and there should be no
penalty for modern compilers; this adds type-checking, too.
This will make future changes easier-to-review.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65775 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* vm_core.h: remove `rb_execution_context_t::passed_bmethod_me`
and fix functions to pass the `me` directly.
`passed_bmethod_me` was used to make bmethod (methods defined by
`defined_method`). `rb_vm_invoke_bmethod` invoke `Proc` with `me`
information as method frame (`lambda` frame, actually).
If the proc call is not bmethod call, `passed_bmethod_me` should
be NULL. However, there is a bug which passes wrong `me` for
normal block call.
http://ci.rvm.jp/results/trunk-asserts@silicon-docker/1449470
This is because wrong `me` was remained in `passed_bmethod_me`
(and used incorrectly it after collected by GC).
We need to clear `passed_bmethod_me` just after bmethod call,
but clearing is not enough.
To solve this issue, I removed `passed_bmethod_me` and pass `me`
information as a function parameter of `rb_vm_invoke_bmethod`,
`invoke_block_from_c_proc` and `invoke_iseq_block_from_c` in vm.c.
* vm.c (invoke_iseq_block_from_c): the number of parameters is too
long so that I try to specify `ALWAYS_INLINE`.
* vm.c (invoke_block_from_c_proc): ditto.
* vm_insnhelper.c (vm_yield_with_cfunc): now there are no pathes
to use bmethod here.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65636 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* vm_core.h (rb_thread_struct): introduce new fields `invoke_type`
and `invoke_arg`.
There are two types threads: invoking proc (normal Ruby thread
created by `Thread.new do ... end`) and invoking func, created
by C-API. `invoke_type` shows the types.
* thread.c (thread_do_start): copy `invoke_arg.proc.args` contents
from Array to ALLOCA stack memory if args length is enough small (<8).
We don't need to keep Array and don't need to cancel using transient heap.
* vm.c (thread_mark): For func invoking threads, they can pass (void *)
parameter (rb_thread_t::invoke_arg::func::arg). However, a rubyspec test
(thread_spec.c) passes an Array object and it expect to mark it.
Clealy it is out of scope (misuse of `rb_thread_create` C-API). However,
I'm not sure someone else has such kind of misunderstanding.
So now we mark conservatively this (void *) arg with rb_gc_mark_maybe.
This misuse is found by this error log.
http://ci.rvm.jp/results/trunk-theap-asserts@silicon-docker/1448164
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65622 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
because it's not supported by this file. Also, shared `def_iseq_ptr`
instead of copying the main definition of it.
vm_core.h: moved `def_iseq_ptr` to this place. added `inline` to avoid
compiler warnings since it's not used in some files including vm_core.h.
vm_insnhelper.c: moved `def_iseq_ptr` to vm_core.h.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65440 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This reverts commit 5a1dfb04bc (r63451)
And mark the functions as async-signal-safe while we're at it to
prevent future developers from making the same mistake as I did :x
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65316 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
The comment didn't make sense. As it's allocated with
`ZALLOC_N(struct rb_call_cache, body->ci_size + body->ci_kw_size)`,
it's very likely to be forgotten to press shift key on US keyboard.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65277 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
We have several options to ensure there's no race condition between main
thread and MJIT thead about IC reference:
1) Give up caching ivar for multiple classes (or multiple versions of the
same class) in the same getinstancevariable (This commit's approach)
2) Allocate new inline cache every time
Other ideas we could think of couldn't eliminate possibilities of race
condition.
In 2, it's memory allocation would be slow and it may trigger JIT
cancellation frequently. So 1 would be fast for both VM and JIT
situations.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65213 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* configure.ac: introduce new configure option `--enable-mjit` and
`--disable-mjit`. Default is "enable".
`--disable-mjit` disables all of MJIT features so that `ruby --jit`
can't enable MJIT.
This option affect a macro `USE_MJIT`.
This change remove `--enable/disable-install-mjit-header` option.
* Makefile.in: introduce the `ENABLE_MJIT` variable.
* common.mk: use `ENABLE_MJIT` option.
* internal.h: respect `USE_MJIT`. Same as other *.c, *.h.
* test/ruby/test_jit.rb: check `ENABLE_MJIT` key of rbconfg.rb.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65204 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This patch introduces "oneshot_lines" mode for `Coverage.start`, which
checks "whether each line was executed at least once or not", instead of
"how many times each line was executed". A hook for each line is fired
at most once, and after it is fired, the hook flag was removed; it runs
with zero overhead.
See [Feature #15022] in detail.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65195 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Surprisingly, this constant (been there since around 1983) has
never been a part of any standards until now. We have to find
out the appropriate value.
NSIG_MAX is expected to become a part of forthcoming POSIX.
See: http://austingroupbugs.net/view.php?id=741
_SIG_MAXSIG is here because that is greater than NSIG. See
Python's relevant discussion: https://bugs.python.org/issue20584
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65161 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
like "error: static declaration of 'xxx' follows non-static declaration".
r64940 is successfully built on mswin but not built on almost all other environments.
internal.h: ditto
include/ruby/intern.h: MJIT_STATIC is moved to this file since this file
also needs to use this.
mjit.h: MJIT_STATIC is moved from this.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64941 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
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
This enhances rb_vm_insn_addr2insn which retrieves a decoded insn number
from encoded insn.
The insn data table include not only decoded insn number, but also its
len, trace and non-trace version of encoded insn.
This table can be used to simplify trace instrumentation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64518 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Spurious interrupts from SIGCHLD cause Mutex#sleep (via
ConditionVariable#wait) to return early and breaks some use
cases. Since these are outside the programs's control with
MJIT, we will only consider pending interrupts (e.g. those
from Thread#run) and signals which cause a Ruby-level Signal.trap
handler to fire as "spurious" wakeups.
[ruby-core:88537] [Feature #15002]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64444 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
On a 64-bit system, this reduces rb_thread_t from 536 to 520 bytes.
Depending on the allocation, this can reduce cacheline access
for checking the abort_on_exception, report_on_exception and
pending_interrupt_queue_checked flags.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64376 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This reverts commit 194a6a2c68 (r64203).
Race conditions which caused the original reversion will be fixed
in the subsequent commit.
[ruby-core:88360] [Misc #14937]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64352 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
By this commit's changes in other files, now MJIT started to work on VC++.
Unfortunately some features are still broken and they'll be fixed later.
This also suppresses cl.exe's default output to stdout because there
seems to be no option to do it. Tweaking some log messages as well.
vm_core.h: declare `__declspec(dllimport)` to export them correctly on mswin.
vm_insnhelper.h: ditto
mjit.h: ditto
test_jit.rb: skipped some pending tests.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64221 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
To reduce resource use and reduce CI failure; remove
timer-thread. Single-threaded Ruby processes (including forked
children) will never see extra thread overhead. This prevents
glibc and jemalloc from going into multi-threaded mode and
initializing locks or causing fragmentation via arena explosion.
The GVL is implements its own wait-queue as a ccan/list to
permit controlling wakeup order. Timeslice under contention is
handled by a designated timer thread (similar to choosing a
"patrol_thread" for current deadlock checking).
There is only one self-pipe, now, as wakeups for timeslice are
done independently using condition variables. This reduces FD
pressure slightly.
Signal handling is handled directly by a Ruby Thread (instead
of timer-thread) by exposing signal self-pipe to callers of
rb_thread_fd_select, native_sleep, rb_wait_for_single_fd, etc...
Acquiring, using, and releasing the self-pipe is exposed via 4
new internal functions:
1) rb_sigwait_fd_get - exclusively acquire timer_thread_pipe.normal[0]
2) rb_sigwait_fd_sleep - sleep and wait for signal (and no other FDs)
3) rb_sigwait_fd_put - release acquired result from rb_sigwait_fd_get
4) rb_sigwait_fd_migrate - migrate signal handling to another thread
after calling rb_sigwait_fd_put.
rb_sigwait_fd_migrate is necessary for waitpid callers because
only one thread can wait on self-pipe at a time, otherwise a
deadlock will occur if threads fight over the self-pipe.
TRAP_INTERRUPT_MASK is now set for the main thread directly in
signal handler via rb_thread_wakeup_timer_thread.
Originally, I wanted to use POSIX timers
(timer_create/timer_settime) for this. Unfortunately, this
proved unfeasible as Mutex#sleep resumes on spurious wakeups and
test/thread/test_cv.rb::test_condvar_timed_wait failed. Using
pthread_sigmask to mask out SIGVTALRM fixed that test, but
test/fiddle/test_function.rb::test_nogvl_poll proved there'd be
some unavoidable (and frequent) incompatibilities from that
approach.
Finally, this allows us to drop thread_destruct_lock and
interrupt current ec directly.
We don't need to rely on vm->thread_destruct_lock or a coherent
vm->running_thread on any platform. Separate timer-thread for
time slice and signal handling is relegated to thread_win32.c,
now.
[ruby-core:88088] [Misc #14937]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64107 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Otherwise, an altstack may live past ObjectSpace destruction
and xfree-ing the altstack will segfault.
[ruby-core:85621] [Feature #14487]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64102 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Repack rb_thread_struct, rb_execution_context_struct, args_info and
iseq_compile_data to save 1 word per struct.
re_pattern_buffer remains unpacked due to the possible binary
compatibility.
[Fix GH-1907]
Based on the patch
From: Lourens Naudé <lourens@bearmetal.eu>
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64096 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Revert r63968 and cast at caller side to prevent unintentional casting.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63972 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* variable.c (rb_const_search): call #const_missing method on
private constants, as well as uninitialized constants.
[Feature #14328]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63871 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Reading win32/win32.c waitpid implementation, maybe waitpid(-1, ...)
on that platform will never conflict with mjit use of waitpid.
In any case, I've added WAITPID_USE_SIGCHLD macro to vm_core.h
so it can be easy for Linux/BSD users to test (hopefully!)
win32-compatible code.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63855 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
The change is unstable on Windows. Please re-commit it when it correctly
supports Windows.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63852 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Some systems lack SIGCHLD or have incomplete SIGCHLD
implementations. So enable polling mode for them.
[ruby-core:87705] [Bug #14867]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63795 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Use a global SIGCHLD handler to guard all callers of rb_waitpid.
To work safely with multi-threaded programs, we introduce a
VM-wide waitpid_lock to be acquired BEFORE fork/vfork spawns the
process. This is to be combined with the new ruby_waitpid_locked
function used by mjit.c in a non-Ruby thread.
Ruby-level SIGCHLD handlers registered with Signal.trap(:CHLD)
continues to work as before and there should be no regressions
in any existing use cases.
Splitting the wait queues for PID > 0 and groups (PID <= 0)
ensures we favor PID > 0 callers.
The disabling of SIGCHLD in rb_f_system is longer necessary,
as we use deferred signal handling and no longer make ANY
blocking waitpid syscalls in other threads which could "beat"
the waitpid call made by rb_f_system.
We prevent SIGCHLD from firing in normal Ruby Threads and only
enable it in the timer-thread, to prevent spurious wakeups
from in test/-ext-/gvl/test_last_thread.rb with MJIT enabled.
I've tried to guard as much of the code for RUBY_SIGCHLD==0
using C "if" statements rather than CPP "#if" so to reduce
the likelyhood of portability problems as the compiler will
see more code.
We also work to suppress false-positives from
Process.wait(-1, Process::WNOHANG) to quiets warnings from
spec/ruby/core/process/wait2_spec.rb with MJIT enabled.
Lastly, we must implement rb_grantpt for ext/pty. We need a
MJIT-compatible way of supporting grantpt(3) which may spawn
the `pt_chown' binary and call waitpid(2) on it.
[ruby-core:87605] [Ruby trunk Bug#14867]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63758 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
vm->sleeper is never modified in signal handlers or without GVL,
so there's no need for volatile hocus-pocus.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63713 b2dd03c8-39d4-4d8f-98ff-823fe69b080e