From 8104c833ef47429ded66edf328fc7f9b57874cb4 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 15 Oct 2025 12:23:40 +0900 Subject: [PATCH 01/10] [rubygems/rubygems] Fixed wrong option message https://github.com/rubygems/rubygems/commit/15be905c44 --- lib/bundler/cli.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 9c7c1217fbf8bd..b8a8be82c18530 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -438,7 +438,7 @@ def cache map aliases_for("cache") desc "exec [OPTIONS]", "Run the command in context of the bundle" - method_option :keep_file_descriptors, type: :boolean, default: true, banner: "Passes all file descriptors to the new processes. Default is true, and setting it to false is deprecated" + method_option :keep_file_descriptors, type: :boolean, default: true, banner: "Passes all file descriptors to the new processes. Default is true, and setting it to false is not permitted (removed)." method_option :gemfile, type: :string, required: false, banner: "Use the specified gemfile instead of Gemfile" long_desc <<-D Exec runs a command, providing it access to the gems in the bundle. While using From fdc37df3d3bd8cb2c4b2fdbafa9e3a6d93d51ab4 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 15 Oct 2025 13:09:58 +0900 Subject: [PATCH 02/10] [rubygems/rubygems] Removed deprecated settings methods https://github.com/rubygems/rubygems/commit/89bcdfc941 --- lib/bundler/feature_flag.rb | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/lib/bundler/feature_flag.rb b/lib/bundler/feature_flag.rb index 8ec62fc1c9e638..dea8abedba393c 100644 --- a/lib/bundler/feature_flag.rb +++ b/lib/bundler/feature_flag.rb @@ -2,29 +2,6 @@ module Bundler class FeatureFlag - def self.settings_flag(flag, &default) - unless Bundler::Settings::BOOL_KEYS.include?(flag.to_s) - raise "Cannot use `#{flag}` as a settings feature flag since it isn't a bool key" - end - - settings_method("#{flag}?", flag, &default) - end - private_class_method :settings_flag - - def self.settings_option(key, &default) - settings_method(key, key, &default) - end - private_class_method :settings_option - - def self.settings_method(name, key, &default) - define_method(name) do - value = Bundler.settings[key] - value = instance_eval(&default) if value.nil? - value - end - end - private_class_method :settings_method - (1..10).each {|v| define_method("bundler_#{v}_mode?") { @major_version >= v } } def removed_major?(target_major_version) From d99a4295a8e2727023292ac78c058bdfc922c2a6 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 15 Oct 2025 13:22:30 +0900 Subject: [PATCH 03/10] [rubygems/rubygems] Restore an accidentally changes of cache_spec.rb https://github.com/rubygems/rubygems/commit/06508374aa --- spec/bundler/commands/cache_spec.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/spec/bundler/commands/cache_spec.rb b/spec/bundler/commands/cache_spec.rb index 283719bedf53b7..1e90f01ce7f8c9 100644 --- a/spec/bundler/commands/cache_spec.rb +++ b/spec/bundler/commands/cache_spec.rb @@ -207,6 +207,17 @@ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist end + it "prints an error when using legacy windows rubies" do + gemfile <<-D + source "https://gem.repo1" + gem 'myrack', :platforms => [:ruby_20, :x64_mingw_20] + D + + bundle "cache --all-platforms", raise_on_error: false + expect(err).to include("removed") + expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).not_to exist + end + it "does not attempt to install gems in without groups" do build_repo4 do build_gem "uninstallable", "2.0" do |s| From 92cbd7ec3354e652d8fcc52ad772bc4699475469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= <2887858+deivid-rodriguez@users.noreply.github.com> Date: Tue, 9 Sep 2025 19:22:06 +0200 Subject: [PATCH 04/10] [rubygems/rubygems] Test current clean after bundle update behavior https://github.com/rubygems/rubygems/commit/c43e35c3ea --- spec/bundler/commands/clean_spec.rb | 43 ++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/spec/bundler/commands/clean_spec.rb b/spec/bundler/commands/clean_spec.rb index f2cd8868935d7b..6b678d0aa5451b 100644 --- a/spec/bundler/commands/clean_spec.rb +++ b/spec/bundler/commands/clean_spec.rb @@ -220,7 +220,7 @@ def should_not_have_gems(*gems) expect(bundled_app("symlink-path/#{Bundler.ruby_scope}/bundler/gems/foo-#{revision[0..11]}")).to exist end - it "removes old git gems" do + it "removes old git gems on bundle update" do build_git "foo-bar", path: lib_path("foo-bar") revision = revision_for(lib_path("foo-bar")) @@ -383,7 +383,7 @@ def should_not_have_gems(*gems) expect(out).to include("myrack (1.0.0)").and include("thin (1.0)") end - it "automatically cleans when path has not been set", bundler: "5" do + it "does not clean on bundle update when path has not been set" do build_repo2 install_gemfile <<-G @@ -398,8 +398,43 @@ def should_not_have_gems(*gems) bundle "update", all: true - files = Pathname.glob(bundled_app(".bundle", Bundler.ruby_scope, "*", "*")) - files.map! {|f| f.to_s.sub(bundled_app(".bundle", Bundler.ruby_scope).to_s, "") } + files = Pathname.glob(default_bundle_path("*", "*")) + files.map! {|f| f.to_s.sub(default_bundle_path.to_s, "") } + expected_files = %W[ + /bin/bundle + /bin/bundler + /cache/bundler-#{Bundler::VERSION}.gem + /cache/foo-1.0.1.gem + /cache/foo-1.0.gem + /gems/bundler-#{Bundler::VERSION} + /gems/foo-1.0 + /gems/foo-1.0.1 + /specifications/bundler-#{Bundler::VERSION}.gemspec + /specifications/foo-1.0.1.gemspec + /specifications/foo-1.0.gemspec + ] + expected_files += ["/bin/bundle.bat", "/bin/bundler.bat"] if Gem.win_platform? + + expect(files.sort).to eq(expected_files.sort) + end + + it "will automatically clean on bundle update when path has not been set", bundler: "5" do + build_repo2 + + install_gemfile <<-G + source "https://gem.repo2" + + gem "foo" + G + + update_repo2 do + build_gem "foo", "1.0.1" + end + + bundle "update", all: true + + files = Pathname.glob(local_gem_path("*", "*")) + files.map! {|f| f.to_s.sub(local_gem_path.to_s, "") } expect(files.sort).to eq %w[ /cache/foo-1.0.1.gem /gems/foo-1.0.1 From a60b56c33d0eb40d8ad9731fe8611f401923a11a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= <2887858+deivid-rodriguez@users.noreply.github.com> Date: Tue, 9 Sep 2025 19:22:13 +0200 Subject: [PATCH 05/10] [rubygems/rubygems] Use `default_cache_path` helper for brevity https://github.com/rubygems/rubygems/commit/29a12c3d46 --- spec/bundler/install/gemfile/git_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/bundler/install/gemfile/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb index 216548cf27ccee..faf938383269ac 100644 --- a/spec/bundler/install/gemfile/git_spec.rb +++ b/spec/bundler/install/gemfile/git_spec.rb @@ -70,7 +70,7 @@ it "caches the git repo" do install_base_gemfile - expect(Dir["#{default_bundle_path}/cache/bundler/git/foo-1.0-*"]).to have_attributes size: 1 + expect(Dir["#{default_cache_path}/git/foo-1.0-*"]).to have_attributes size: 1 end it "does not write to cache on bundler/setup" do From c3e6e65591e881fd8816de79d00d4be73a4edf3f Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 15 Oct 2025 13:39:32 +0900 Subject: [PATCH 06/10] [rubygems/rubygems] Removed duplicated examples with bundle install https://github.com/rubygems/rubygems/commit/59b909fa74 --- spec/bundler/commands/install_spec.rb | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb index 65903b3e780024..8506005746a25b 100644 --- a/spec/bundler/commands/install_spec.rb +++ b/spec/bundler/commands/install_spec.rb @@ -327,21 +327,6 @@ end end - describe "doing bundle install foo" do - before do - gemfile <<-G - source "https://gem.repo1" - gem "myrack" - G - end - - it "works" do - bundle "config set --local path vendor" - bundle "install" - expect(the_bundle).to include_gems "myrack 1.0" - end - end - it "gives useful errors if no global sources are set, and gems not installed locally, with and without a lockfile" do install_gemfile <<-G, raise_on_error: false gem "myrack" From 6c9acb533f747682df2f681070596c7bbaccde18 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 15 Oct 2025 13:43:29 +0900 Subject: [PATCH 07/10] [rubygems/rubygems] Added example for global path with Gemfile https://github.com/rubygems/rubygems/commit/cd1493eec4 --- spec/bundler/other/major_deprecation_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/spec/bundler/other/major_deprecation_spec.rb b/spec/bundler/other/major_deprecation_spec.rb index d701c4008dbf4c..1b04af76325795 100644 --- a/spec/bundler/other/major_deprecation_spec.rb +++ b/spec/bundler/other/major_deprecation_spec.rb @@ -605,6 +605,21 @@ end end + context "with a global path source" do + before do + build_lib "foo" + + install_gemfile <<-G, raise_on_error: false + path "#{lib_path("foo-1.0")}" + gem 'foo' + G + end + + it "shows an error" do + expect(err).to include("You can no longer specify a path source by itself") + end + end + context "when Bundler.setup is run in a ruby script" do before do create_file "gems.rb", "source 'https://gem.repo1'" From 51b2c5a4cd8d1a26f25767366e95391b9de203b5 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 15 Oct 2025 14:11:06 +0900 Subject: [PATCH 08/10] [rubygems/rubygems] Removed obsoleted option from bundle-exec manpages https://github.com/rubygems/rubygems/commit/6a3342541a --- lib/bundler/man/bundle-exec.1 | 5 +---- lib/bundler/man/bundle-exec.1.ronn | 6 +----- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/lib/bundler/man/bundle-exec.1 b/lib/bundler/man/bundle-exec.1 index 93788a850f463d..24c84889b5bf39 100644 --- a/lib/bundler/man/bundle-exec.1 +++ b/lib/bundler/man/bundle-exec.1 @@ -4,7 +4,7 @@ .SH "NAME" \fBbundle\-exec\fR \- Execute a command in the context of the bundle .SH "SYNOPSIS" -\fBbundle exec\fR [\-\-keep\-file\-descriptors] [\-\-gemfile=GEMFILE] \fIcommand\fR +\fBbundle exec\fR [\-\-gemfile=GEMFILE] \fIcommand\fR .SH "DESCRIPTION" This command executes the command, making all gems specified in the [\fBGemfile(5)\fR][Gemfile(5)] available to \fBrequire\fR in Ruby programs\. .P @@ -13,9 +13,6 @@ Essentially, if you would normally have run something like \fBrspec spec/my_spec Note that \fBbundle exec\fR does not require that an executable is available on your shell's \fB$PATH\fR\. .SH "OPTIONS" .TP -\fB\-\-keep\-file\-descriptors\fR -Passes all file descriptors to the new processes\. Default is true from bundler version 2\.2\.26\. Setting it to false is now deprecated\. -.TP \fB\-\-gemfile=GEMFILE\fR Use the specified gemfile instead of [\fBGemfile(5)\fR][Gemfile(5)]\. .SH "BUNDLE INSTALL \-\-BINSTUBS" diff --git a/lib/bundler/man/bundle-exec.1.ronn b/lib/bundler/man/bundle-exec.1.ronn index 3d3f0eed7b89da..e51a66a0840c54 100644 --- a/lib/bundler/man/bundle-exec.1.ronn +++ b/lib/bundler/man/bundle-exec.1.ronn @@ -3,7 +3,7 @@ bundle-exec(1) -- Execute a command in the context of the bundle ## SYNOPSIS -`bundle exec` [--keep-file-descriptors] [--gemfile=GEMFILE] +`bundle exec` [--gemfile=GEMFILE] ## DESCRIPTION @@ -20,10 +20,6 @@ available on your shell's `$PATH`. ## OPTIONS -* `--keep-file-descriptors`: - Passes all file descriptors to the new processes. Default is true from - bundler version 2.2.26. Setting it to false is now deprecated. - * `--gemfile=GEMFILE`: Use the specified gemfile instead of [`Gemfile(5)`][Gemfile(5)]. From dce202d6d653dfc1b2c64822fe53066c3c558a78 Mon Sep 17 00:00:00 2001 From: Edouard CHIN Date: Thu, 9 Oct 2025 17:23:43 +0200 Subject: [PATCH 09/10] [rubygems/rubygems] Add checksum of gems hosted on private servers: - ### Problem Running `bundle lock --add-checksums` doesn't add the checksum of gems hosted on server that don't implement the compact index API. This result in a lockfile which is unusable in production as some checksums will be missing and Bundler raising an error. Users can work around this problem by running: `BUNDLE_LOCKFILE_CHECKSUMS=true bundle install --force` But this means redownloading and installing all gems which isn't great and slow on large apps. ### Context Bundler uses the Compact Index API to get the checksum of gems, but most private gem servers don't implement the compact index API (such as cloudsmith or packagecloud). This results in a soft failure on bundler side, and bundler leaving out blank checksum for those gems. ### Solution For gems that are hosted on private servers that don't send back the checksum of the gem, I'd like to fallback to the `bundle install` mechanism, which don't rely on an external API but instead compute the checksum of the package installed on disk. This patch goes through the spec that didn't return a checksum, and compute one if the package exists on disk. This solution makes the `bundle lock --add-checksums` command actually usable in real world scenarios while keeping the `bundle lock` command fast enough. https://github.com/rubygems/rubygems/commit/8e9abb5472 --- lib/bundler/definition.rb | 13 ++++- spec/bundler/commands/lock_spec.rb | 91 ++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 6cae8964d8145a..3c8c13b1303171 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -540,7 +540,18 @@ def add_checksums setup_domain!(add_checksums: true) - specs # force materialization to real specifications, so that checksums are fetched + # force materialization to real specifications, so that checksums are fetched + specs.each do |spec| + next unless spec.source.is_a?(Bundler::Source::Rubygems) + # Checksum was fetched from the compact index API. + next if !spec.source.checksum_store.missing?(spec) && !spec.source.checksum_store.empty?(spec) + # The gem isn't installed, can't compute the checksum. + next unless spec.loaded_from + + package = Gem::Package.new(spec.source.cached_built_in_gem(spec)) + checksum = Checksum.from_gem_package(package) + spec.source.checksum_store.register(spec, checksum) + end end private diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb index a7460ed695a456..36493e108a2cf4 100644 --- a/spec/bundler/commands/lock_spec.rb +++ b/spec/bundler/commands/lock_spec.rb @@ -2174,6 +2174,97 @@ L end + it "add checksums for gems installed on disk" do + build_repo4 do + build_gem "warning", "18.0.0" + end + + bundle "config lockfile_checksums false" + + simulate_platform "x86_64-linux" do + install_gemfile(<<-G, artifice: "endpoint") + source "https://gem.repo4" + + gem "warning" + G + + bundle "config --delete lockfile_checksums" + bundle("lock --add-checksums", artifice: "endpoint") + end + + checksums = checksums_section do |c| + c.checksum gem_repo4, "warning", "18.0.0" + end + + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo4/ + specs: + warning (18.0.0) + + PLATFORMS + ruby + x86_64-linux + + DEPENDENCIES + warning + #{checksums} + BUNDLED WITH + #{Bundler::VERSION} + L + end + + it "doesn't add checksum for gems not installed on disk" do + lockfile(<<~L) + GEM + remote: https://gem.repo4/ + specs: + warning (18.0.0) + + PLATFORMS + #{local_platform} + + DEPENDENCIES + warning + + BUNDLED WITH + #{Bundler::VERSION} + L + + gemfile(<<~G) + source "https://gem.repo4" + + gem "warning" + G + + build_repo4 do + build_gem "warning", "18.0.0" + end + + FileUtils.rm_rf("#{gem_repo4}/gems") + + bundle("lock --add-checksums", artifice: "endpoint") + + expect(lockfile).to eq <<~L + GEM + remote: https://gem.repo4/ + specs: + warning (18.0.0) + + PLATFORMS + #{local_platform} + + DEPENDENCIES + warning + + CHECKSUMS + warning (18.0.0) + + BUNDLED WITH + #{Bundler::VERSION} + L + end + context "when re-resolving to include prereleases" do before do build_repo4 do From bb4526b9b1c25f2e6435802321137d0d33216b76 Mon Sep 17 00:00:00 2001 From: Aiden Fox Ivey Date: Wed, 15 Oct 2025 05:56:31 -0400 Subject: [PATCH 10/10] ZJIT: Add trace exit counter (#14831) --- zjit/src/backend/lir.rs | 22 ++++++++++++++++++---- zjit/src/options.rs | 32 +++++++++++++++++++++++--------- zjit/src/state.rs | 6 +++--- zjit/src/stats.rs | 25 ++++++++++++++++++++----- 4 files changed, 64 insertions(+), 21 deletions(-) diff --git a/zjit/src/backend/lir.rs b/zjit/src/backend/lir.rs index aad5600f569767..6efb3e1259e4e6 100644 --- a/zjit/src/backend/lir.rs +++ b/zjit/src/backend/lir.rs @@ -4,9 +4,9 @@ use std::mem::take; use crate::codegen::local_size_and_idx_to_ep_offset; use crate::cruby::{Qundef, RUBY_OFFSET_CFP_PC, RUBY_OFFSET_CFP_SP, SIZEOF_VALUE_I32, vm_stack_canary}; use crate::hir::SideExitReason; -use crate::options::{debug, get_option}; +use crate::options::{debug, get_option, TraceExits}; use crate::cruby::VALUE; -use crate::stats::{exit_counter_ptr, exit_counter_ptr_for_opcode, CompileError}; +use crate::stats::{exit_counter_ptr, exit_counter_ptr_for_opcode, side_exit_counter, CompileError}; use crate::virtualmem::CodePtr; use crate::asm::{CodeBlock, Label}; use crate::state::rb_zjit_record_exit_stack; @@ -1644,8 +1644,22 @@ impl Assembler } } - if get_option!(trace_side_exits) { - asm_ccall!(self, rb_zjit_record_exit_stack, Opnd::const_ptr(pc as *const u8)); + if get_option!(trace_side_exits).is_some() { + // Get the corresponding `Counter` for the current `SideExitReason`. + let side_exit_counter = side_exit_counter(reason); + + // Only record the exit if `trace_side_exits` is defined and the counter is either the one specified + let should_record_exit = get_option!(trace_side_exits) + .map(|trace| match trace { + TraceExits::All => true, + TraceExits::Counter(counter) if counter == side_exit_counter => true, + _ => false, + }) + .unwrap_or(false); + + if should_record_exit { + asm_ccall!(self, rb_zjit_record_exit_stack, Opnd::const_ptr(pc as *const u8)); + } } asm_comment!(self, "exit to the interpreter"); diff --git a/zjit/src/options.rs b/zjit/src/options.rs index 4ef998acede36c..b7b20e63c4484d 100644 --- a/zjit/src/options.rs +++ b/zjit/src/options.rs @@ -3,6 +3,7 @@ use std::{ffi::{CStr, CString}, ptr::null}; use std::os::raw::{c_char, c_int, c_uint}; use crate::cruby::*; +use crate::stats::Counter; use std::collections::HashSet; /// Default --zjit-num-profiles @@ -72,7 +73,7 @@ pub struct Options { pub dump_disasm: bool, /// Trace and write side exit source maps to /tmp for stackprof. - pub trace_side_exits: bool, + pub trace_side_exits: Option, /// Frequency of tracing side exits. pub trace_side_exits_sample_interval: usize, @@ -102,7 +103,7 @@ impl Default for Options { dump_hir_graphviz: None, dump_lir: false, dump_disasm: false, - trace_side_exits: false, + trace_side_exits: None, trace_side_exits_sample_interval: 0, perf: false, allowed_iseqs: None, @@ -125,12 +126,20 @@ pub const ZJIT_OPTIONS: &[(&str, &str)] = &[ ("--zjit-perf", "Dump ISEQ symbols into /tmp/perf-{}.map for Linux perf."), ("--zjit-log-compiled-iseqs=path", "Log compiled ISEQs to the file. The file will be truncated."), - ("--zjit-trace-exits", - "Record Ruby source location when side-exiting."), - ("--zjit-trace-exits-sample-rate", + ("--zjit-trace-exits[=counter]", + "Record source on side-exit. `Counter` picks specific counter."), + ("--zjit-trace-exits-sample-rate=num", "Frequency at which to record side exits. Must be `usize`.") ]; +#[derive(Copy, Clone, Debug)] +pub enum TraceExits { + // Trace all exits + All, + // Trace exits for a specific `Counter` + Counter(Counter), +} + #[derive(Clone, Copy, Debug)] pub enum DumpHIR { // Dump High-level IR without Snapshot @@ -249,13 +258,18 @@ fn parse_option(str_ptr: *const std::os::raw::c_char) -> Option<()> { options.print_stats = false; } - ("trace-exits", "") => { - options.trace_side_exits = true; + ("trace-exits", exits) => { + options.trace_side_exits = match exits { + "" => Some(TraceExits::All), + name => Counter::get(name).map(TraceExits::Counter), + } } ("trace-exits-sample-rate", sample_interval) => { - // Even if `trace_side_exits` is already set, set it. - options.trace_side_exits = true; + // If not already set, then set it to `TraceExits::All` by default. + if options.trace_side_exits.is_none() { + options.trace_side_exits = Some(TraceExits::All); + } // `sample_interval ` must provide a string that can be validly parsed to a `usize`. options.trace_side_exits_sample_interval = sample_interval.parse::().ok()?; } diff --git a/zjit/src/state.rs b/zjit/src/state.rs index 1b766d5bc4b5aa..c0e9e0b77ca909 100644 --- a/zjit/src/state.rs +++ b/zjit/src/state.rs @@ -82,7 +82,7 @@ impl ZJITState { let exit_trampoline = gen_exit_trampoline(&mut cb).unwrap(); let function_stub_hit_trampoline = gen_function_stub_hit_trampoline(&mut cb).unwrap(); - let exit_locations = if get_option!(trace_side_exits) { + let exit_locations = if get_option!(trace_side_exits).is_some() { Some(SideExitLocations::default()) } else { None @@ -369,7 +369,7 @@ fn try_increment_existing_stack( /// Record a backtrace with ZJIT side exits #[unsafe(no_mangle)] pub extern "C" fn rb_zjit_record_exit_stack(exit_pc: *const VALUE) { - if !zjit_enabled_p() || !get_option!(trace_side_exits) { + if !zjit_enabled_p() || get_option!(trace_side_exits).is_none() { return; } @@ -425,7 +425,7 @@ pub extern "C" fn rb_zjit_record_exit_stack(exit_pc: *const VALUE) { /// Mark `raw_samples` so they can be used by rb_zjit_add_frame. pub fn gc_mark_raw_samples() { // Return if ZJIT is not enabled - if !zjit_enabled_p() || !get_option!(trace_side_exits) { + if !zjit_enabled_p() || get_option!(trace_side_exits).is_none() { return; } diff --git a/zjit/src/stats.rs b/zjit/src/stats.rs index d902c69b795c4b..6faa328a1ca736 100644 --- a/zjit/src/stats.rs +++ b/zjit/src/stats.rs @@ -57,6 +57,17 @@ macro_rules! make_counters { $( Counter::$counter_name => stringify!($counter_name), )+ } } + + pub fn get(name: &str) -> Option { + match name { + $( stringify!($default_counter_name) => Some(Counter::$default_counter_name), )+ + $( stringify!($exit_counter_name) => Some(Counter::$exit_counter_name), )+ + $( stringify!($dynamic_send_counter_name) => Some(Counter::$dynamic_send_counter_name), )+ + $( stringify!($optimized_send_counter_name) => Some(Counter::$optimized_send_counter_name), )+ + $( stringify!($counter_name) => Some(Counter::$counter_name), )+ + _ => None, + } + } } /// Map a counter to a pointer @@ -298,11 +309,11 @@ pub fn exit_counter_for_compile_error(compile_error: &CompileError) -> Counter { } } -pub fn exit_counter_ptr(reason: crate::hir::SideExitReason) -> *mut u64 { +pub fn side_exit_counter(reason: crate::hir::SideExitReason) -> Counter { use crate::hir::SideExitReason::*; use crate::hir::CallType::*; use crate::stats::Counter::*; - let counter = match reason { + match reason { UnknownNewarraySend(_) => exit_unknown_newarray_send, UnhandledCallType(Tailcall) => exit_unhandled_tailcall, UnhandledCallType(Splat) => exit_unhandled_splat, @@ -324,7 +335,11 @@ pub fn exit_counter_ptr(reason: crate::hir::SideExitReason) -> *mut u64 { StackOverflow => exit_stackoverflow, BlockParamProxyModified => exit_block_param_proxy_modified, BlockParamProxyNotIseqOrIfunc => exit_block_param_proxy_not_iseq_or_ifunc, - }; + } +} + +pub fn exit_counter_ptr(reason: crate::hir::SideExitReason) -> *mut u64 { + let counter = side_exit_counter(reason); counter_ptr(counter) } @@ -563,7 +578,7 @@ pub struct SideExitLocations { #[unsafe(no_mangle)] pub extern "C" fn rb_zjit_trace_exit_locations_enabled_p(_ec: EcPtr, _ruby_self: VALUE) -> VALUE { // Builtin zjit.rb calls this even if ZJIT is disabled, so OPTIONS may not be set. - if unsafe { OPTIONS.as_ref() }.is_some_and(|opts| opts.trace_side_exits) { + if unsafe { OPTIONS.as_ref() }.is_some_and(|opts| opts.trace_side_exits.is_some()) { Qtrue } else { Qfalse @@ -574,7 +589,7 @@ pub extern "C" fn rb_zjit_trace_exit_locations_enabled_p(_ec: EcPtr, _ruby_self: /// into raw, lines, and frames hash for RubyVM::YJIT.exit_locations. #[unsafe(no_mangle)] pub extern "C" fn rb_zjit_get_exit_locations(_ec: EcPtr, _ruby_self: VALUE) -> VALUE { - if !zjit_enabled_p() || !get_option!(trace_side_exits) { + if !zjit_enabled_p() || get_option!(trace_side_exits).is_none() { return Qnil; }