diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml
index 07c43a0c3b0788..67a350db1c887f 100644
--- a/.github/workflows/check_misc.yml
+++ b/.github/workflows/check_misc.yml
@@ -35,6 +35,18 @@ jobs:
if: ${{ github.repository == 'ruby/ruby' && github.ref == 'refs/heads/master' && github.event_name == 'push' }}
continue-on-error: true # The next auto-style should always run
+ # Sync git.ruby-lang.org before pushing new commits to avoid duplicated syncs
+ - name: Sync git.ruby-lang.org
+ env:
+ RUBY_GIT_SYNC_PRIVATE_KEY: ${{ secrets.RUBY_GIT_SYNC_PRIVATE_KEY }}
+ run: |
+ mkdir -p ~/.ssh
+ echo "$RUBY_GIT_SYNC_PRIVATE_KEY" > ~/.ssh/id_ed25519
+ chmod 600 ~/.ssh/id_ed25519
+ ssh-keyscan -t ed25519 git.ruby-lang.org >> ~/.ssh/known_hosts
+ ssh -i ~/.ssh/id_ed25519 git-sync@git.ruby-lang.org 'sudo -u git /home/git/git.ruby-lang.org/bin/update-ruby.sh master'
+ if: ${{ github.repository == 'ruby/ruby' && github.ref == 'refs/heads/master' && github.event_name == 'push' }}
+
- uses: ./.github/actions/setup/directories
with:
makeup: true
diff --git a/.github/workflows/zjit-macos.yml b/.github/workflows/zjit-macos.yml
index a638a3b1b353dd..0d2b564c41c802 100644
--- a/.github/workflows/zjit-macos.yml
+++ b/.github/workflows/zjit-macos.yml
@@ -101,9 +101,6 @@ jobs:
- name: Run configure
run: ../src/configure -C --disable-install-doc ${{ matrix.configure }}
- - run: make prepare-gems
- if: ${{ matrix.test_task == 'test-bundled-gems' }}
-
- run: make
- name: Verify that --zjit-dump-disasm works
diff --git a/.github/workflows/zjit-ubuntu.yml b/.github/workflows/zjit-ubuntu.yml
index 99d5dbfdedc390..a30ff1df88fdd9 100644
--- a/.github/workflows/zjit-ubuntu.yml
+++ b/.github/workflows/zjit-ubuntu.yml
@@ -72,6 +72,10 @@ jobs:
configure: '--enable-zjit=dev --with-gcc=clang-14'
libclang_path: '/usr/lib/llvm-14/lib/libclang.so.1'
+ - test_task: 'test-bundled-gems'
+ configure: '--enable-zjit=dev'
+ run_opts: '--zjit-call-threshold=1'
+
env:
GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
RUN_OPTS: ${{ matrix.run_opts }}
diff --git a/array.c b/array.c
index 2ba95bef186dae..378da150ee3e3e 100644
--- a/array.c
+++ b/array.c
@@ -4569,7 +4569,7 @@ take_items(VALUE obj, long n)
* [:c3, :b3, :a3]]
*
* For an *object* in *other_arrays* that is not actually an array,
- * forms the the "other array" as object.to_ary, if defined,
+ * forms the "other array" as object.to_ary, if defined,
* or as object.each.to_a otherwise.
*
* Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
diff --git a/doc/zjit.md b/doc/zjit.md
index c0378031b24bd2..d0d3e361913039 100644
--- a/doc/zjit.md
+++ b/doc/zjit.md
@@ -150,10 +150,10 @@ Through [Stackprof](https://github.com/tmm1/stackprof), detailed information abo
./miniruby --zjit-trace-exits script.rb
```
-A file called `zjit_exit_locations{timestamp}.dump` will be created in the same directory as `script.rb`. Viewing the side exited methods can be done with Stackprof:
+A file called `zjit_exits_{pid}.dump` will be created in the same directory as `script.rb`. Viewing the side exited methods can be done with Stackprof:
```bash
-stackprof path/to/zjit_exit_locations{timestamp}.dump
+stackprof path/to/zjit_exits_{pid}.dump
```
## Useful dev commands
diff --git a/gems/bundled_gems b/gems/bundled_gems
index d37d90bbf14eb2..4b95fa525004f7 100644
--- a/gems/bundled_gems
+++ b/gems/bundled_gems
@@ -41,7 +41,7 @@ benchmark 0.4.1 https://github.com/ruby/benchmark
logger 1.7.0 https://github.com/ruby/logger
rdoc 6.14.2 https://github.com/ruby/rdoc
win32ole 1.9.2 https://github.com/ruby/win32ole
-irb 1.15.2 https://github.com/ruby/irb 331c4e851296b115db766c291e8cf54a2492fb36
+irb 1.15.2 https://github.com/ruby/irb d43c3d764ae439706aa1b26a3ec299cc45eaed5b
reline 0.6.2 https://github.com/ruby/reline
readline 0.0.4 https://github.com/ruby/readline
fiddle 1.1.8 https://github.com/ruby/fiddle
diff --git a/thread_pthread.c b/thread_pthread.c
index 5150a6173e6e6b..323659b64945b8 100644
--- a/thread_pthread.c
+++ b/thread_pthread.c
@@ -90,9 +90,16 @@ static const void *const condattr_monotonic = NULL;
#endif
#endif
+#ifdef HAVE_SCHED_YIELD
+#define native_thread_yield() (void)sched_yield()
+#else
+#define native_thread_yield() ((void)0)
+#endif
+
// native thread wrappers
#define NATIVE_MUTEX_LOCK_DEBUG 0
+#define NATIVE_MUTEX_LOCK_DEBUG_YIELD 0
static void
mutex_debug(const char *msg, void *lock)
@@ -111,6 +118,9 @@ void
rb_native_mutex_lock(pthread_mutex_t *lock)
{
int r;
+#if NATIVE_MUTEX_LOCK_DEBUG_YIELD
+ native_thread_yield();
+#endif
mutex_debug("lock", lock);
if ((r = pthread_mutex_lock(lock)) != 0) {
rb_bug_errno("pthread_mutex_lock", r);
@@ -310,12 +320,6 @@ static rb_serial_t current_fork_gen = 1; /* We can't use GET_VM()->fork_gen */
static void threadptr_trap_interrupt(rb_thread_t *);
-#ifdef HAVE_SCHED_YIELD
-#define native_thread_yield() (void)sched_yield()
-#else
-#define native_thread_yield() ((void)0)
-#endif
-
static void native_thread_dedicated_inc(rb_vm_t *vm, rb_ractor_t *cr, struct rb_native_thread *nt);
static void native_thread_dedicated_dec(rb_vm_t *vm, rb_ractor_t *cr, struct rb_native_thread *nt);
static void native_thread_assign(struct rb_native_thread *nt, rb_thread_t *th);
diff --git a/tool/lib/core_assertions.rb b/tool/lib/core_assertions.rb
index 934ab080372d67..cc4eb327d41106 100644
--- a/tool/lib/core_assertions.rb
+++ b/tool/lib/core_assertions.rb
@@ -74,10 +74,7 @@ def message msg = nil, ending = nil, &default
module CoreAssertions
require_relative 'envutil'
require 'pp'
- begin
- require '-test-/asan'
- rescue LoadError
- end
+ require '-test-/asan'
nil.pretty_inspect
@@ -162,7 +159,7 @@ def assert_no_memory_leak(args, prepare, code, message=nil, limit: 2.0, rss: fal
pend 'assert_no_memory_leak may consider MJIT memory usage as leak' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
# ASAN has the same problem - its shadow memory greatly increases memory usage
# (plus asan has better ways to detect memory leaks than this assertion)
- pend 'assert_no_memory_leak may consider ASAN memory usage as leak' if defined?(Test::ASAN) && Test::ASAN.enabled?
+ pend 'assert_no_memory_leak may consider ASAN memory usage as leak' if Test::ASAN.enabled?
require_relative 'memory_status'
raise Test::Unit::PendedError, "unsupported platform" unless defined?(Memory::Status)
diff --git a/tool/test-bundled-gems.rb b/tool/test-bundled-gems.rb
index 86bb747d946320..006ebd981af913 100644
--- a/tool/test-bundled-gems.rb
+++ b/tool/test-bundled-gems.rb
@@ -1,6 +1,7 @@
require 'rbconfig'
require 'timeout'
require 'fileutils'
+require 'shellwords'
require_relative 'lib/colorize'
require_relative 'lib/gem_env'
@@ -25,6 +26,7 @@
rake = File.realpath("../../.bundle/bin/rake", __FILE__)
gem_dir = File.realpath('../../gems', __FILE__)
rubylib = [gem_dir+'/lib', ENV["RUBYLIB"]].compact.join(File::PATH_SEPARATOR)
+run_opts = ENV["RUN_OPTS"]&.shellsplit
exit_code = 0
ruby = ENV['RUBY'] || RbConfig.ruby
failed = []
@@ -33,7 +35,7 @@
next if bundled_gems&.none? {|pat| File.fnmatch?(pat, gem)}
next unless File.directory?("#{gem_dir}/src/#{gem}/test")
- test_command = [ruby, "-C", "#{gem_dir}/src/#{gem}", rake, "test"]
+ test_command = [ruby, *run_opts, "-C", "#{gem_dir}/src/#{gem}", rake, "test"]
first_timeout = 600 # 10min
toplib = gem
@@ -71,7 +73,7 @@
load_path = true
when "test-unit"
- test_command = [ruby, "-C", "#{gem_dir}/src/#{gem}", "test/run.rb"]
+ test_command = [ruby, *run_opts, "-C", "#{gem_dir}/src/#{gem}", "test/run.rb"]
when "csv"
first_timeout = 30
diff --git a/zjit.rb b/zjit.rb
index b44154ad9cef1c..75c57f9a35c195 100644
--- a/zjit.rb
+++ b/zjit.rb
@@ -35,18 +35,17 @@ def exit_locations
return unless trace_exit_locations_enabled?
results = Primitive.rb_zjit_get_exit_locations
- raw_samples = results[:raw].dup
- line_samples = results[:lines].dup
- frames = results[:frames].dup
+ raw_samples = results[:raw]
+ line_samples = results[:lines]
+ frames = results[:frames]
samples_count = 0
- # Loop through the instructions and set the frame hash with the data.
- # We use nonexistent.def for the file name, otherwise insns.def will be displayed
- # and that information isn't useful in this context.
+ # Use nonexistent.def as a dummy file name.
+ frame_template = { samples: 0, total_samples: 0, edges: {}, name: name, file: "nonexistent.def", line: nil, lines: {} }
+
+ # Loop through all possible instructions and setup the frame hash.
RubyVM::INSTRUCTION_NAMES.each_with_index do |name, frame_id|
- frame_hash = { samples: 0, total_samples: 0, edges: {}, name: name, file: "nonexistent.def", line: nil, lines: {} }
- results[:frames][frame_id] = frame_hash
- frames[frame_id] = frame_hash
+ frames[frame_id] = frame_template.dup.tap { |h| h[:name] = name }
end
# Loop through the raw_samples and build the hashes for StackProf.
@@ -100,10 +99,13 @@ def exit_locations
end
results[:samples] = samples_count
- # Set missed_samples and gc_samples to 0 as their values
- # don't matter to us in this context.
+
+ # These values are mandatory to include for stackprof, but we don't use them.
results[:missed_samples] = 0
results[:gc_samples] = 0
+
+ results[:frames].reject! { |k, v| v[:samples] == 0 }
+
results
end
@@ -277,7 +279,7 @@ def print_stats
def dump_locations # :nodoc:
return unless trace_exit_locations_enabled?
- filename = "zjit_exits_#{Time.now.to_i}.dump"
+ filename = "zjit_exits_#{Process.pid}.dump"
n_bytes = dump_exit_locations(filename)
$stderr.puts("#{n_bytes} bytes written to #{filename}.")