From 0e22108d60fbd0e338fb6e110ddd81a93b45b592 Mon Sep 17 00:00:00 2001 From: Sam Westerman Date: Tue, 2 Dec 2025 07:00:22 +0000 Subject: [PATCH 1/3] [ruby/optparse] Remove `const_set` and instead use explicit assignments https://github.com/ruby/optparse/commit/6e2709a5fd --- lib/optparse.rb | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index e0b0ff011b5455..aae73c86b32787 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -2314,42 +2314,42 @@ def message # Raises when ambiguously completable string is encountered. # class AmbiguousOption < ParseError - const_set(:Reason, 'ambiguous option') + Reason = 'ambiguous option' # :nodoc: end # # Raises when there is an argument for a switch which takes no argument. # class NeedlessArgument < ParseError - const_set(:Reason, 'needless argument') + Reason = 'needless argument' # :nodoc: end # # Raises when a switch with mandatory argument has no argument. # class MissingArgument < ParseError - const_set(:Reason, 'missing argument') + Reason = 'missing argument' # :nodoc: end # # Raises when switch is undefined. # class InvalidOption < ParseError - const_set(:Reason, 'invalid option') + Reason = 'invalid option' # :nodoc: end # # Raises when the given argument does not match required format. # class InvalidArgument < ParseError - const_set(:Reason, 'invalid argument') + Reason = 'invalid argument' # :nodoc: end # # Raises when the given argument word can't be completed uniquely. # class AmbiguousArgument < InvalidArgument - const_set(:Reason, 'ambiguous argument') + Reason = 'ambiguous argument' # :nodoc: end # @@ -2448,9 +2448,11 @@ def initialize(*args) # :nodoc: # and DecimalNumeric. See Acceptable argument classes (in source code). # module Acceptables - const_set(:DecimalInteger, OptionParser::DecimalInteger) - const_set(:OctalInteger, OptionParser::OctalInteger) - const_set(:DecimalNumeric, OptionParser::DecimalNumeric) + # :stopdoc: + DecimalInteger = OptionParser::DecimalInteger + OctalInteger = OptionParser::OctalInteger + DecimalNumeric = OptionParser::DecimalNumeric + # :startdoc: end end From 456ba321a84d34e76c8837ac96f47a11457480cb Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Sun, 30 Nov 2025 19:16:52 -0800 Subject: [PATCH 2/3] [ruby/rubygems] Make BUNDLE_LOCKFILE environment variable have precedence over lockfile method in Gemfile It would be simpler to do `options[:lockfile] ||= ENV["BUNDLE_LOCKFILE"]`, but that doesn't work as `options` is frozen. Fixes https://github.com/ruby/rubygems/pull/9117 https://github.com/ruby/rubygems/commit/6e3603a0e9 --- lib/bundler/cli.rb | 6 ++++-- lib/bundler/man/gemfile.5 | 4 ++-- lib/bundler/man/gemfile.5.ronn | 2 +- spec/bundler/commands/install_spec.rb | 14 ++++++++++++++ 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 9c29751a7c31fb..36ce04eb2a5d05 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -69,7 +69,7 @@ def initialize(*args) # lock --lockfile works differently than install --lockfile unless current_cmd == "lock" - custom_lockfile = options[:lockfile] || Bundler.settings[:lockfile] + custom_lockfile = options[:lockfile] || ENV["BUNDLE_LOCKFILE"] || Bundler.settings[:lockfile] if custom_lockfile && !custom_lockfile.empty? Bundler::SharedHelpers.set_env "BUNDLE_LOCKFILE", File.expand_path(custom_lockfile) reset_settings = true @@ -282,8 +282,10 @@ def install end require_relative "cli/install" + options = self.options.dup + options["lockfile"] ||= ENV["BUNDLE_LOCKFILE"] Bundler.settings.temporary(no_install: false) do - Install.new(options.dup).run + Install.new(options).run end end diff --git a/lib/bundler/man/gemfile.5 b/lib/bundler/man/gemfile.5 index fce7d8e178439b..a8c055a0c1a456 100644 --- a/lib/bundler/man/gemfile.5 +++ b/lib/bundler/man/gemfile.5 @@ -494,9 +494,9 @@ The \fBbundle install\fR \fB\-\-no\-lock\fR option (which disables lockfile crea .IP "2." 4 The \fBbundle install\fR \fB\-\-lockfile\fR option\. .IP "3." 4 -The \fBlockfile\fR method in the Gemfile\. -.IP "4." 4 The \fBBUNDLE_LOCKFILE\fR environment variable\. +.IP "4." 4 +The \fBlockfile\fR method in the Gemfile\. .IP "5." 4 The default behavior of adding \fB\.lock\fR to the end of the Gemfile name\. .IP "" 0 diff --git a/lib/bundler/man/gemfile.5.ronn b/lib/bundler/man/gemfile.5.ronn index e4bc91359e3cc5..18d7bb826e4439 100644 --- a/lib/bundler/man/gemfile.5.ronn +++ b/lib/bundler/man/gemfile.5.ronn @@ -581,6 +581,6 @@ following precedence is used: 1. The `bundle install` `--no-lock` option (which disables lockfile creation). 1. The `bundle install` `--lockfile` option. -1. The `lockfile` method in the Gemfile. 1. The `BUNDLE_LOCKFILE` environment variable. +1. The `lockfile` method in the Gemfile. 1. The default behavior of adding `.lock` to the end of the Gemfile name. diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb index bacd8d64f2d6c3..3dc8aa0dc01757 100644 --- a/spec/bundler/commands/install_spec.rb +++ b/spec/bundler/commands/install_spec.rb @@ -41,6 +41,20 @@ expect(bundled_app("OmgFile.lock")).to exist end + it "creates lockfile using BUNDLE_LOCKFILE instead of lockfile method" do + ENV["BUNDLE_LOCKFILE"] = "ReallyOmgFile.lock" + install_gemfile <<-G + lockfile "OmgFile.lock" + source "https://gem.repo1" + gem "myrack", "1.0" + G + + expect(bundled_app("ReallyOmgFile.lock")).to exist + expect(bundled_app("OmgFile.lock")).not_to exist + ensure + ENV.delete("BUNDLE_LOCKFILE") + end + it "creates lockfile based on --lockfile option is given" do gemfile bundled_app("OmgFile"), <<-G source "https://gem.repo1" From e515fa7ab1981df439a3a6b3635a0389f4216cce Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 26 Nov 2025 13:28:44 +0100 Subject: [PATCH 3/3] ZJIT: Improve documentation and make it easy to generate the types graph --- doc/jit/zjit.md | 49 ++++++++++++++++++++++++++----- zjit/src/hir_type/gen_hir_type.rb | 18 +++++++----- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/doc/jit/zjit.md b/doc/jit/zjit.md index f3b36b1fd5aaa5..7434d44b9d7d60 100644 --- a/doc/jit/zjit.md +++ b/doc/jit/zjit.md @@ -16,6 +16,35 @@ To build ZJIT on macOS: make -j miniruby ``` +To build ZJIT on Linux: + +```bash +./autogen.sh + +./configure \ + --enable-zjit=dev \ + --prefix="$HOME"/.rubies/ruby-zjit \ + --disable-install-doc + +make -j miniruby +``` + +Note that `--enable-zjit=dev` does a lot of IR validation, which will help to catch errors early but mean compilation and warmup are significantly slower. + +The valid values for `--enable-zjit` are, from fastest to slowest: +* `--enable-zjit`: enable ZJIT in release mode for maximum performance +* `--enable-zjit=stats`: enable ZJIT in extended-stats mode +* `--enable-zjit=dev_nodebug`: enable ZJIT in development mode but without slow runtime checks +* `--enable-zjit=dev`: enable ZJIT in debug mode for development, also enables `RUBY_DEBUG` + +### Regenerate bindings + +When modifying `zjit/bindgen/src/main.rs` you need to regenerate bindings in `zjit/src/cruby_bindings.inc.rs` with: + +```bash +make zjit-bindgen +``` + ## Documentation You can generate and open the source level documentation in your browser using: @@ -24,6 +53,16 @@ You can generate and open the source level documentation in your browser using: cargo doc --document-private-items -p zjit --open ``` +### Graph of the Type System + +You can generate a graph of the ZJIT type hierarchy using: + +```bash +ruby zjit/src/hir_type/gen_hir_type.rb > zjit/src/hir_type/hir_type.inc.rs +dot -O -Tpdf zjit_types.dot +open zjit_types.dot.pdf +``` + ## Testing Note that tests link against CRuby, so directly calling `cargo test`, or `cargo nextest` should not build. All tests are instead accessed through `make`. @@ -139,14 +178,8 @@ end ### Performance Ratio -The `ratio_in_zjit` stat shows the percentage of Ruby instructions executed in JIT code vs interpreter. This metric only appears when ZJIT is built with `--enable-zjit=stats` (which enables `rb_vm_insn_count` tracking) and represents a key performance indicator for ZJIT effectiveness. - -To build with stats support: - -```bash -./configure --enable-zjit=stats -make -j -``` +The `ratio_in_zjit` stat shows the percentage of Ruby instructions executed in JIT code vs interpreter. +This metric only appears when ZJIT is built with `--enable-zjit=stats` [or more](#build-instructions) (which enables `rb_vm_insn_count` tracking) and represents a key performance indicator for ZJIT effectiveness. ### Tracing side exits diff --git a/zjit/src/hir_type/gen_hir_type.rb b/zjit/src/hir_type/gen_hir_type.rb index 4e0ecc718f8f82..e51d0c04e1a324 100644 --- a/zjit/src/hir_type/gen_hir_type.rb +++ b/zjit/src/hir_type/gen_hir_type.rb @@ -25,20 +25,20 @@ def subtype name end # Helper to generate graphviz. -def to_graphviz_rec type +def to_graphviz_rec type, f type.subtypes.each {|subtype| - puts type.name + "->" + subtype.name + ";" + f.puts type.name + "->" + subtype.name + ";" } type.subtypes.each {|subtype| - to_graphviz_rec subtype + to_graphviz_rec subtype, f } end # Generate graphviz. -def to_graphviz type - puts "digraph G {" - to_graphviz_rec type - puts "}" +def to_graphviz type, f + f.puts "digraph G {" + to_graphviz_rec type, f + f.puts "}" end # ===== Start generating the type DAG ===== @@ -218,3 +218,7 @@ def add_union name, type_names } puts " ];" puts "}" + +File.open("zjit_types.dot", "w") do |f| + to_graphviz(any, f) +end