summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gdbinit2
-rw-r--r--.github/dependabot.yml4
-rw-r--r--.github/workflows/check_dependencies.yml6
-rw-r--r--.github/workflows/dependabot_automerge.yml2
-rw-r--r--.github/workflows/ubuntu.yml5
-rw-r--r--.github/workflows/windows.yml4
-rw-r--r--.gitignore1
-rw-r--r--bootstraptest/test_ractor.rb27
-rw-r--r--common.mk92
-rw-r--r--configure.ac9
-rw-r--r--defs/gmake.mk3
-rw-r--r--depend200
-rw-r--r--ext/json/generator/generator.c4
-rw-r--r--ext/json/lib/json.rb2
-rw-r--r--ext/json/lib/json/add/string.rb8
-rw-r--r--ext/json/lib/json/common.rb2
-rw-r--r--ext/json/parser/parser.c2
-rw-r--r--ext/openssl/ossl_x509store.c3
-rw-r--r--ext/socket/raddrinfo.c12
-rw-r--r--gc.c25
-rw-r--r--hash.c43
-rw-r--r--internal/re.h5
-rw-r--r--iseq.c15
-rw-r--r--lib/bundler/checksum.rb6
-rw-r--r--lib/bundler/cli.rb45
-rw-r--r--lib/bundler/cli/list.rb35
-rw-r--r--lib/bundler/cli/show.rb8
-rw-r--r--lib/bundler/definition.rb54
-rw-r--r--lib/bundler/man/bundle-add.12
-rw-r--r--lib/bundler/man/bundle-binstubs.12
-rw-r--r--lib/bundler/man/bundle-cache.12
-rw-r--r--lib/bundler/man/bundle-check.12
-rw-r--r--lib/bundler/man/bundle-clean.12
-rw-r--r--lib/bundler/man/bundle-config.145
-rw-r--r--lib/bundler/man/bundle-config.1.ronn69
-rw-r--r--lib/bundler/man/bundle-console.12
-rw-r--r--lib/bundler/man/bundle-doctor.18
-rw-r--r--lib/bundler/man/bundle-doctor.1.ronn8
-rw-r--r--lib/bundler/man/bundle-env.12
-rw-r--r--lib/bundler/man/bundle-exec.12
-rw-r--r--lib/bundler/man/bundle-fund.12
-rw-r--r--lib/bundler/man/bundle-gem.12
-rw-r--r--lib/bundler/man/bundle-help.12
-rw-r--r--lib/bundler/man/bundle-info.12
-rw-r--r--lib/bundler/man/bundle-init.12
-rw-r--r--lib/bundler/man/bundle-inject.12
-rw-r--r--lib/bundler/man/bundle-install.12
-rw-r--r--lib/bundler/man/bundle-issue.12
-rw-r--r--lib/bundler/man/bundle-licenses.12
-rw-r--r--lib/bundler/man/bundle-list.17
-rw-r--r--lib/bundler/man/bundle-list.1.ronn5
-rw-r--r--lib/bundler/man/bundle-lock.12
-rw-r--r--lib/bundler/man/bundle-open.12
-rw-r--r--lib/bundler/man/bundle-outdated.12
-rw-r--r--lib/bundler/man/bundle-platform.12
-rw-r--r--lib/bundler/man/bundle-plugin.147
-rw-r--r--lib/bundler/man/bundle-plugin.1.ronn51
-rw-r--r--lib/bundler/man/bundle-pristine.12
-rw-r--r--lib/bundler/man/bundle-remove.12
-rw-r--r--lib/bundler/man/bundle-show.12
-rw-r--r--lib/bundler/man/bundle-update.12
-rw-r--r--lib/bundler/man/bundle-version.12
-rw-r--r--lib/bundler/man/bundle-viz.12
-rw-r--r--lib/bundler/man/bundle.12
-rw-r--r--lib/bundler/man/gemfile.52
-rw-r--r--lib/bundler/resolver.rb2
-rw-r--r--lib/bundler/rubygems_ext.rb2
-rw-r--r--lib/rubygems.rb10
-rw-r--r--lib/rubygems/command.rb2
-rw-r--r--lib/rubygems/command_manager.rb6
-rw-r--r--lib/rubygems/dependency.rb2
-rw-r--r--lib/rubygems/dependency_installer.rb2
-rw-r--r--lib/rubygems/dependency_list.rb2
-rw-r--r--lib/rubygems/deprecate.rb2
-rw-r--r--lib/rubygems/errors.rb2
-rw-r--r--lib/rubygems/exceptions.rb4
-rw-r--r--lib/rubygems/ext/builder.rb6
-rw-r--r--lib/rubygems/ext/cargo_builder.rb2
-rw-r--r--lib/rubygems/ext/cmake_builder.rb4
-rw-r--r--lib/rubygems/ext/configure_builder.rb4
-rw-r--r--lib/rubygems/ext/ext_conf_builder.rb8
-rw-r--r--lib/rubygems/ext/rake_builder.rb4
-rw-r--r--lib/rubygems/installer.rb19
-rw-r--r--lib/rubygems/name_tuple.rb2
-rw-r--r--lib/rubygems/package/tar_writer.rb2
-rw-r--r--lib/rubygems/remote_fetcher.rb2
-rw-r--r--lib/rubygems/resolver.rb2
-rw-r--r--lib/rubygems/resolver/conflict.rb2
-rw-r--r--lib/rubygems/source.rb4
-rw-r--r--lib/rubygems/spec_fetcher.rb8
-rw-r--r--lib/rubygems/specification.rb2
-rw-r--r--lib/rubygems/text.rb2
-rw-r--r--lib/rubygems/user_interaction.rb12
-rw-r--r--lib/rubygems/validator.rb2
-rw-r--r--lib/syntax_suggest/api.rb6
-rw-r--r--prism/generate-srcs.mk.rb17
-rw-r--r--prism/srcs.mk142
-rw-r--r--prism/srcs.mk.in40
-rw-r--r--proc.c11
-rw-r--r--random.c36
-rw-r--r--range.c1
-rw-r--r--re.c5
-rw-r--r--shape.c6
-rw-r--r--spec/bundler/commands/list_spec.rb120
-rw-r--r--spec/bundler/commands/show_spec.rb24
-rw-r--r--spec/bundler/commands/update_spec.rb45
-rw-r--r--spec/bundler/install/gemfile/git_spec.rb64
-rw-r--r--spec/bundler/install/gemfile/specific_platform_spec.rb4
-rw-r--r--spec/bundler/lock/lockfile_spec.rb36
-rw-r--r--spec/bundler/other/cli_man_pages_spec.rb85
-rw-r--r--spec/bundler/other/major_deprecation_spec.rb24
-rw-r--r--spec/bundler/quality_spec.rb49
-rw-r--r--spec/bundler/resolver/platform_spec.rb2
-rw-r--r--spec/bundler/runtime/inline_spec.rb6
-rw-r--r--template/GNUmakefile.in3
-rw-r--r--template/Makefile.in35
-rw-r--r--test/.excludes-zjit/TestRubyOptimization.rb1
-rw-r--r--test/json/ractor_test.rb2
-rw-r--r--test/ruby/test_gc.rb2
-rw-r--r--test/ruby/test_hash.rb17
-rw-r--r--test/ruby/test_keyword.rb2
-rw-r--r--test/ruby/test_m17n.rb118
-rw-r--r--test/ruby/test_shapes.rb23
-rw-r--r--test/ruby/test_string.rb14
-rw-r--r--test/ruby/test_zjit.rb141
-rw-r--r--test/rubygems/helper.rb6
-rw-r--r--test/rubygems/installer_test_case.rb2
-rw-r--r--test/rubygems/mock_gem_ui.rb2
-rw-r--r--test/rubygems/test_gem_ext_ext_conf_builder.rb33
-rw-r--r--test/rubygems/test_gem_remote_fetcher.rb2
-rwxr-xr-xtool/make-snapshot27
-rw-r--r--tool/prereq.status3
-rwxr-xr-xtool/sync_default_gems.rb1
-rwxr-xr-xtool/update-deps19
-rw-r--r--vcpkg.json4
-rw-r--r--vm_callinfo.h2
-rw-r--r--vm_method.c6
-rw-r--r--win32/Makefile.sub1
-rw-r--r--yjit/src/codegen.rs12
-rw-r--r--zjit/bindgen/src/main.rs7
-rw-r--r--zjit/src/backend/lir.rs31
-rw-r--r--zjit/src/codegen.rs552
-rw-r--r--zjit/src/cruby_bindings.inc.rs5
-rw-r--r--zjit/src/gc.rs33
-rw-r--r--zjit/src/hir.rs132
-rw-r--r--zjit/src/invariants.rs27
-rw-r--r--zjit/src/profile.rs70
147 files changed, 2076 insertions, 1027 deletions
diff --git a/.gdbinit b/.gdbinit
index f624456d04..f204b3a235 100644
--- a/.gdbinit
+++ b/.gdbinit
@@ -51,7 +51,7 @@ define rp
printf "%sT_OBJECT%s: ", $color_type, $color_end
print ((struct RObject *)($arg0))->basic
if ($flags & ROBJECT_EMBED)
- print/x *((VALUE*)((struct RObject*)($arg0))->as.ary) @ (rb_shape_get_shape($arg0)->capacity)
+ print/x *((VALUE*)((struct RObject*)($arg0))->as.ary) @ (RSHAPE_CAPACITY(rb_obj_shape_id($arg0)))
else
print (((struct RObject *)($arg0))->as.heap)
if (((struct RObject*)($arg0))->as.heap.numiv) > 0
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 426893be2a..2c2982d1d4 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -16,3 +16,7 @@ updates:
directory: '/yjit'
schedule:
interval: 'daily'
+ - package-ecosystem: 'vcpkg'
+ directory: '/'
+ schedule:
+ interval: 'daily'
diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml
index 6d85cf8e9c..db93e90efb 100644
--- a/.github/workflows/check_dependencies.yml
+++ b/.github/workflows/check_dependencies.yml
@@ -48,11 +48,7 @@ jobs:
- name: Run configure
run: ./configure -C --disable-install-doc --disable-rubygems --with-gcc 'optflags=-O0' 'debugflags=-save-temps=obj -g'
- - run: make all golf
-
- - run: ./goruby -veh
-
- - run: ruby tool/update-deps --fix
+ - run: make fix-depends
- run: git diff --no-ext-diff --ignore-submodules --exit-code
diff --git a/.github/workflows/dependabot_automerge.yml b/.github/workflows/dependabot_automerge.yml
index 2d2427a907..3a2ba704ae 100644
--- a/.github/workflows/dependabot_automerge.yml
+++ b/.github/workflows/dependabot_automerge.yml
@@ -17,7 +17,7 @@ jobs:
id: metadata
- name: Wait for status checks
- uses: lewagon/wait-on-check-action@31f07a800aa1ba8518509dc8561cdf5a891deb4b # v1.4.0
+ uses: lewagon/wait-on-check-action@0dceb95e7c4cad8cc7422aee3885998f5cab9c79 # v1.4.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
ref: ${{ github.event.pull_request.head.sha || github.sha }}
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index 27cd43bf9c..8955ea91d4 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -191,6 +191,11 @@ jobs:
if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
+ - name: test-pc
+ run: |
+ DESTDIR=${RUNNER_TEMP-${TMPDIR-/tmp}}/installed
+ $SETARCH make test-pc "DESTDIR=$DESTDIR"
+
- uses: ./.github/actions/slack
with:
label: ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }}
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 0b7bf25d95..3e85f7a1c5 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -86,7 +86,7 @@ jobs:
- name: Restore vcpkg artifact
id: restore-vcpkg
- uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: src\vcpkg_installed
key: windows-${{ matrix.os }}-vcpkg-${{ hashFiles('src/vcpkg.json') }}
@@ -98,7 +98,7 @@ jobs:
if: ${{ ! steps.restore-vcpkg.outputs.cache-hit }}
- name: Save vcpkg artifact
- uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
+ uses: actions/cache/save@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: src\vcpkg_installed
key: windows-${{ matrix.os }}-vcpkg-${{ hashFiles('src/vcpkg.json') }}
diff --git a/.gitignore b/.gitignore
index ddf8e9a99a..6cf5fb5f32 100644
--- a/.gitignore
+++ b/.gitignore
@@ -272,6 +272,7 @@ lcov*.info
/prism/prettyprint.c
/prism/serialize.c
/prism/token_type.c
+/prism/srcs.mk
# tool/update-NEWS-gemlist.rb
/bundled_gems.json
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb
index b1e9e3a79d..4a58ece8ac 100644
--- a/bootstraptest/test_ractor.rb
+++ b/bootstraptest/test_ractor.rb
@@ -1573,6 +1573,33 @@ assert_equal 'true', %q{
rs.map{|r| r.value} == Array.new(RN){n}
}
+# check method cache invalidation
+assert_equal 'true', %q{
+ class Foo
+ def hello = nil
+ end
+
+ r1 = Ractor.new do
+ 1000.times do
+ class Foo
+ def hello = nil
+ end
+ end
+ end
+
+ r2 = Ractor.new do
+ 1000.times do
+ o = Foo.new
+ o.hello
+ end
+ end
+
+ r1.value
+ r2.value
+
+ true
+}
+
# check experimental warning
assert_match /\Atest_ractor\.rb:1:\s+warning:\s+Ractor is experimental/, %q{
Warning[:experimental] = $VERBOSE = true
diff --git a/common.mk b/common.mk
index 9e5098ef4b..2a2f3b7ff3 100644
--- a/common.mk
+++ b/common.mk
@@ -205,83 +205,6 @@ $(PRISM_BUILD_DIR)/.time $(PRISM_BUILD_DIR)/util/.time:
$(Q) $(MAKEDIRS) $(@D)
@$(NULLCMD) > $@
-main: $(srcdir)/lib/prism/compiler.rb
-srcs: $(srcdir)/lib/prism/compiler.rb
-$(srcdir)/lib/prism/compiler.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/compiler.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/compiler.rb $(srcdir)/lib/prism/compiler.rb
-
-main: $(srcdir)/lib/prism/dispatcher.rb
-srcs: $(srcdir)/lib/prism/dispatcher.rb
-$(srcdir)/lib/prism/dispatcher.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/dispatcher.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/dispatcher.rb $(srcdir)/lib/prism/dispatcher.rb
-
-main: $(srcdir)/lib/prism/dsl.rb
-srcs: $(srcdir)/lib/prism/dsl.rb
-$(srcdir)/lib/prism/dsl.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/dsl.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/dsl.rb $(srcdir)/lib/prism/dsl.rb
-
-main: $(srcdir)/lib/prism/inspect_visitor.rb
-srcs: $(srcdir)/lib/prism/inspect_visitor.rb
-$(srcdir)/lib/prism/inspect_visitor.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/inspect_visitor.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/inspect_visitor.rb $(srcdir)/lib/prism/inspect_visitor.rb
-
-main: $(srcdir)/lib/prism/mutation_compiler.rb
-srcs: $(srcdir)/lib/prism/mutation_compiler.rb
-$(srcdir)/lib/prism/mutation_compiler.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/mutation_compiler.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/mutation_compiler.rb $(srcdir)/lib/prism/mutation_compiler.rb
-
-main: $(srcdir)/lib/prism/node.rb
-srcs: $(srcdir)/lib/prism/node.rb
-$(srcdir)/lib/prism/node.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/node.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/node.rb $(srcdir)/lib/prism/node.rb
-
-main: $(srcdir)/lib/prism/reflection.rb
-srcs: $(srcdir)/lib/prism/reflection.rb
-$(srcdir)/lib/prism/reflection.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/reflection.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/reflection.rb $(srcdir)/lib/prism/reflection.rb
-
-main: $(srcdir)/lib/prism/serialize.rb
-srcs: $(srcdir)/lib/prism/serialize.rb
-$(srcdir)/lib/prism/serialize.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/serialize.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/serialize.rb $(srcdir)/lib/prism/serialize.rb
-
-main: $(srcdir)/lib/prism/visitor.rb
-srcs: $(srcdir)/lib/prism/visitor.rb
-$(srcdir)/lib/prism/visitor.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/visitor.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/visitor.rb $(srcdir)/lib/prism/visitor.rb
-
-srcs: prism/api_node.c
-prism/api_node.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/ext/prism/api_node.c.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb ext/prism/api_node.c $@
-
-srcs: prism/ast.h
-prism/ast.h: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/include/prism/ast.h.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb include/prism/ast.h $@
-
-srcs: prism/diagnostic.c
-prism/diagnostic.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/diagnostic.c.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/diagnostic.c $@
-
-srcs: prism/diagnostic.h
-prism/diagnostic.h: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/include/prism/diagnostic.h.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb include/prism/diagnostic.h $@
-
-srcs: prism/node.c
-prism/node.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/node.c.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/node.c $@
-
-srcs: prism/prettyprint.c
-prism/prettyprint.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/prettyprint.c.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/prettyprint.c $@
-
-srcs: prism/serialize.c
-prism/serialize.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/serialize.c.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/serialize.c $@
-
-srcs: prism/token_type.c
-prism/token_type.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/token_type.c.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/token_type.c $@
-
EXPORTOBJS = $(DLNOBJ) \
localeinit.$(OBJEXT) \
loadpath.$(OBJEXT) \
@@ -797,7 +720,8 @@ clean-srcs-local::
realclean-srcs-local:: clean-srcs-local
$(Q)$(CHDIR) $(srcdir) && $(RM) \
parse.c parse.h lex.c enc/trans/newline.c $(PRELUDES) revision.h \
- id.c id.h probes.dmyh configure aclocal.m4 tool/config.guess tool/config.sub gems/*.gem \
+ id.c id.h probes.dmyh configure aclocal.m4 tool/config.guess tool/config.sub \
+ $(PRISM_SRCDIR)/srcs.mk gems/*.gem \
|| $(NULLCMD)
clean-srcs-ext::
@@ -1290,7 +1214,6 @@ incs: $(INSNS) {$(VPATH)}node_name.inc {$(VPATH)}known_errors.inc \
{$(VPATH)}vm_call_iseq_optimized.inc $(srcdir)/revision.h \
$(REVISION_H) \
$(UNICODE_DATA_HEADERS) $(ENC_HEADERS) \
- $(srcs_vpath)prism/ast.h $(srcs_vpath)prism/diagnostic.h \
{$(VPATH)}id.h {$(VPATH)}probes.dmyh
insns: $(INSNS)
@@ -1379,6 +1302,11 @@ $(REVISION_H)$(yes_baseruby:yes=~disabled~):
# uncommon.mk: $(REVISION_H)
# $(MKFILES): $(REVISION_H)
+# $(common_mk_includes) is set by config.status or GNUmakefile
+common_mk__$(gnumake:yes=artifact)_ = uncommon.mk
+common_mk_$(gnumake)_artifact_ = $(MKFILES)
+$(common_mk__artifact_): $(srcdir)/common.mk $(common_mk_includes)
+
ripper_srcs: $(RIPPER_SRCS)
$(RIPPER_SRCS): $(srcdir)/parse.y $(srcdir)/defs/id.def
@@ -1915,6 +1843,9 @@ clean-gems:
CLEAN_CACHE = clean-extlibs
+prepare-package: prereq after-update
+clean-cache: $(CLEAN_CACHE)
+
info: info-program info-libruby_a info-libruby_so info-arch
info-program: PHONY
@echo PROGRAM=$(PROGRAM)
@@ -2046,3 +1977,6 @@ help: PHONY
$(CROSS_COMPILING:yes=)builtin.$(OBJEXT): {$(VPATH)}mini_builtin.c
$(CROSS_COMPILING:yes=)builtin.$(OBJEXT): {$(VPATH)}miniprelude.c
+
+!include $(srcdir)/prism/srcs.mk
+!include $(srcdir)/depend
diff --git a/configure.ac b/configure.ac
index c8018cdabb..fdff2469cb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4698,8 +4698,12 @@ AC_CONFIG_FILES(Makefile:template/Makefile.in, [
sed '/^MISSING/s/\$U\././g;/^VCS *=/s#@VCS@#'"$VCS"'#;/^VCSUP *=/s#@VCSUP@#'"$VCSUP"'#' Makefile
echo; test x"$EXEEXT" = x || echo 'miniruby: miniruby$(EXEEXT)'
AS_IF([test "$gnumake" != yes], [
- echo ['$(MKFILES): $(srcdir)/common.mk $(srcdir)/depend']
- sed ['s/{\$([^(){}]*)[^{}]*}//g'] ${srcdir}/common.mk ${srcdir}/depend
+ # extract NMake-style include list
+ set = `sed -n 's/^!include *//p' ${srcdir}/common.mk`
+ echo common_mk_includes "@S|@*" # generate the macro assignment
+ shift
+ common_mk_includes="`echo \"@S|@*\" | sed 's|\$(srcdir)|.|g'`"
+ (PWD= cd ${srcdir} && sed -f tool/prereq.status common.mk ${common_mk_includes})
AS_IF([test "$YJIT_SUPPORT" = yes], [
cat ${srcdir}/yjit/not_gmake.mk
echo ['$(MKFILES): ${srcdir}/yjit/not_gmake.mk']
@@ -4722,6 +4726,7 @@ AC_CONFIG_FILES(Makefile:template/Makefile.in, [
]) &&
test -z "`${MAKE-make} -f $tmpgmk info-program | grep '^PROGRAM=ruby$'`" &&
echo 'ruby: $(PROGRAM);' >> $tmpmk
+ rm -f uncommon.mk # remove stale uncommon.mk, it should be updated by GNUmakefile
test "$tmpmk" = "$tmpgmk" || rm -f "$tmpgmk"
]) && mv -f $tmpmk Makefile],
[EXEEXT='$EXEEXT' MAKE='${MAKE-make}' gnumake='$gnumake' GIT='$GIT' YJIT_SUPPORT='$YJIT_SUPPORT'])
diff --git a/defs/gmake.mk b/defs/gmake.mk
index 6382e3d003..bd4b8b8e39 100644
--- a/defs/gmake.mk
+++ b/defs/gmake.mk
@@ -505,6 +505,9 @@ update-deps:
$(GIT) --git-dir=$(GIT_DIR) merge --no-edit --ff-only $(update_deps)
$(GIT) --git-dir=$(GIT_DIR) branch --delete $(update_deps)
+fix-depends check-depends: all hello
+ $(BASERUBY) -C $(srcdir) tool/update-deps $(if $(filter fix-%,$@),--fix)
+
# order-only-prerequisites doesn't work for $(RUBYSPEC_CAPIEXT)
# because the same named directory exists in the source tree.
$(RUBYSPEC_CAPIEXT)/%.$(DLEXT): $(srcdir)/$(RUBYSPEC_CAPIEXT)/%.c $(RUBYSPEC_CAPIEXT_DEPS) \
diff --git a/depend b/depend
index ea2486e9e8..0fcf5ce652 100644
--- a/depend
+++ b/depend
@@ -303,7 +303,9 @@ ast.$(OBJEXT): $(top_srcdir)/internal/symbol.h
ast.$(OBJEXT): $(top_srcdir)/internal/variable.h
ast.$(OBJEXT): $(top_srcdir)/internal/vm.h
ast.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+ast.$(OBJEXT): $(top_srcdir)/prism/ast.h
ast.$(OBJEXT): $(top_srcdir)/prism/defines.h
+ast.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
ast.$(OBJEXT): $(top_srcdir)/prism/encoding.h
ast.$(OBJEXT): $(top_srcdir)/prism/node.h
ast.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -323,6 +325,7 @@ ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+ast.$(OBJEXT): $(top_srcdir)/prism/version.h
ast.$(OBJEXT): {$(VPATH)}assert.h
ast.$(OBJEXT): {$(VPATH)}ast.c
ast.$(OBJEXT): {$(VPATH)}ast.rbinc
@@ -501,9 +504,6 @@ ast.$(OBJEXT): {$(VPATH)}missing.h
ast.$(OBJEXT): {$(VPATH)}node.h
ast.$(OBJEXT): {$(VPATH)}onigmo.h
ast.$(OBJEXT): {$(VPATH)}oniguruma.h
-ast.$(OBJEXT): {$(VPATH)}prism/ast.h
-ast.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-ast.$(OBJEXT): {$(VPATH)}prism/version.h
ast.$(OBJEXT): {$(VPATH)}prism_compile.h
ast.$(OBJEXT): {$(VPATH)}ruby_assert.h
ast.$(OBJEXT): {$(VPATH)}ruby_atomic.h
@@ -746,7 +746,9 @@ builtin.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
builtin.$(OBJEXT): $(top_srcdir)/internal/variable.h
builtin.$(OBJEXT): $(top_srcdir)/internal/vm.h
builtin.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/ast.h
builtin.$(OBJEXT): $(top_srcdir)/prism/defines.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
builtin.$(OBJEXT): $(top_srcdir)/prism/encoding.h
builtin.$(OBJEXT): $(top_srcdir)/prism/node.h
builtin.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -766,6 +768,7 @@ builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/version.h
builtin.$(OBJEXT): {$(VPATH)}assert.h
builtin.$(OBJEXT): {$(VPATH)}atomic.h
builtin.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -944,9 +947,6 @@ builtin.$(OBJEXT): {$(VPATH)}missing.h
builtin.$(OBJEXT): {$(VPATH)}node.h
builtin.$(OBJEXT): {$(VPATH)}onigmo.h
builtin.$(OBJEXT): {$(VPATH)}oniguruma.h
-builtin.$(OBJEXT): {$(VPATH)}prism/ast.h
-builtin.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-builtin.$(OBJEXT): {$(VPATH)}prism/version.h
builtin.$(OBJEXT): {$(VPATH)}prism_compile.h
builtin.$(OBJEXT): {$(VPATH)}ruby_assert.h
builtin.$(OBJEXT): {$(VPATH)}ruby_atomic.h
@@ -1391,7 +1391,9 @@ compile.$(OBJEXT): $(top_srcdir)/internal/thread.h
compile.$(OBJEXT): $(top_srcdir)/internal/variable.h
compile.$(OBJEXT): $(top_srcdir)/internal/vm.h
compile.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+compile.$(OBJEXT): $(top_srcdir)/prism/ast.h
compile.$(OBJEXT): $(top_srcdir)/prism/defines.h
+compile.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
compile.$(OBJEXT): $(top_srcdir)/prism/encoding.h
compile.$(OBJEXT): $(top_srcdir)/prism/node.h
compile.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -1399,6 +1401,7 @@ compile.$(OBJEXT): $(top_srcdir)/prism/pack.h
compile.$(OBJEXT): $(top_srcdir)/prism/parser.h
compile.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
compile.$(OBJEXT): $(top_srcdir)/prism/prism.h
+compile.$(OBJEXT): $(top_srcdir)/prism/prism.h
compile.$(OBJEXT): $(top_srcdir)/prism/regexp.h
compile.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
@@ -1411,6 +1414,7 @@ compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+compile.$(OBJEXT): $(top_srcdir)/prism/version.h
compile.$(OBJEXT): $(top_srcdir)/prism_compile.c
compile.$(OBJEXT): {$(VPATH)}assert.h
compile.$(OBJEXT): {$(VPATH)}atomic.h
@@ -1597,10 +1601,6 @@ compile.$(OBJEXT): {$(VPATH)}node.h
compile.$(OBJEXT): {$(VPATH)}onigmo.h
compile.$(OBJEXT): {$(VPATH)}oniguruma.h
compile.$(OBJEXT): {$(VPATH)}optinsn.inc
-compile.$(OBJEXT): {$(VPATH)}prism/ast.h
-compile.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-compile.$(OBJEXT): {$(VPATH)}prism/prism.h
-compile.$(OBJEXT): {$(VPATH)}prism/version.h
compile.$(OBJEXT): {$(VPATH)}prism_compile.c
compile.$(OBJEXT): {$(VPATH)}prism_compile.h
compile.$(OBJEXT): {$(VPATH)}ractor.h
@@ -2067,7 +2067,9 @@ cont.$(OBJEXT): $(top_srcdir)/internal/thread.h
cont.$(OBJEXT): $(top_srcdir)/internal/variable.h
cont.$(OBJEXT): $(top_srcdir)/internal/vm.h
cont.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+cont.$(OBJEXT): $(top_srcdir)/prism/ast.h
cont.$(OBJEXT): $(top_srcdir)/prism/defines.h
+cont.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
cont.$(OBJEXT): $(top_srcdir)/prism/encoding.h
cont.$(OBJEXT): $(top_srcdir)/prism/node.h
cont.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -2087,6 +2089,7 @@ cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+cont.$(OBJEXT): $(top_srcdir)/prism/version.h
cont.$(OBJEXT): {$(VPATH)}$(COROUTINE_H)
cont.$(OBJEXT): {$(VPATH)}assert.h
cont.$(OBJEXT): {$(VPATH)}atomic.h
@@ -2267,9 +2270,6 @@ cont.$(OBJEXT): {$(VPATH)}missing.h
cont.$(OBJEXT): {$(VPATH)}node.h
cont.$(OBJEXT): {$(VPATH)}onigmo.h
cont.$(OBJEXT): {$(VPATH)}oniguruma.h
-cont.$(OBJEXT): {$(VPATH)}prism/ast.h
-cont.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-cont.$(OBJEXT): {$(VPATH)}prism/version.h
cont.$(OBJEXT): {$(VPATH)}prism_compile.h
cont.$(OBJEXT): {$(VPATH)}ractor.h
cont.$(OBJEXT): {$(VPATH)}ractor_core.h
@@ -5074,7 +5074,9 @@ eval.$(OBJEXT): $(top_srcdir)/internal/thread.h
eval.$(OBJEXT): $(top_srcdir)/internal/variable.h
eval.$(OBJEXT): $(top_srcdir)/internal/vm.h
eval.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+eval.$(OBJEXT): $(top_srcdir)/prism/ast.h
eval.$(OBJEXT): $(top_srcdir)/prism/defines.h
+eval.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
eval.$(OBJEXT): $(top_srcdir)/prism/encoding.h
eval.$(OBJEXT): $(top_srcdir)/prism/node.h
eval.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -5094,6 +5096,7 @@ eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+eval.$(OBJEXT): $(top_srcdir)/prism/version.h
eval.$(OBJEXT): {$(VPATH)}assert.h
eval.$(OBJEXT): {$(VPATH)}atomic.h
eval.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -5276,9 +5279,6 @@ eval.$(OBJEXT): {$(VPATH)}missing.h
eval.$(OBJEXT): {$(VPATH)}node.h
eval.$(OBJEXT): {$(VPATH)}onigmo.h
eval.$(OBJEXT): {$(VPATH)}oniguruma.h
-eval.$(OBJEXT): {$(VPATH)}prism/ast.h
-eval.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-eval.$(OBJEXT): {$(VPATH)}prism/version.h
eval.$(OBJEXT): {$(VPATH)}prism_compile.h
eval.$(OBJEXT): {$(VPATH)}probes.dmyh
eval.$(OBJEXT): {$(VPATH)}probes.h
@@ -5563,7 +5563,9 @@ gc.$(OBJEXT): $(top_srcdir)/internal/thread.h
gc.$(OBJEXT): $(top_srcdir)/internal/variable.h
gc.$(OBJEXT): $(top_srcdir)/internal/vm.h
gc.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+gc.$(OBJEXT): $(top_srcdir)/prism/ast.h
gc.$(OBJEXT): $(top_srcdir)/prism/defines.h
+gc.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
gc.$(OBJEXT): $(top_srcdir)/prism/encoding.h
gc.$(OBJEXT): $(top_srcdir)/prism/node.h
gc.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -5583,6 +5585,7 @@ gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+gc.$(OBJEXT): $(top_srcdir)/prism/version.h
gc.$(OBJEXT): {$(VPATH)}assert.h
gc.$(OBJEXT): {$(VPATH)}atomic.h
gc.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -5767,9 +5770,6 @@ gc.$(OBJEXT): {$(VPATH)}missing.h
gc.$(OBJEXT): {$(VPATH)}node.h
gc.$(OBJEXT): {$(VPATH)}onigmo.h
gc.$(OBJEXT): {$(VPATH)}oniguruma.h
-gc.$(OBJEXT): {$(VPATH)}prism/ast.h
-gc.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-gc.$(OBJEXT): {$(VPATH)}prism/version.h
gc.$(OBJEXT): {$(VPATH)}prism_compile.h
gc.$(OBJEXT): {$(VPATH)}probes.dmyh
gc.$(OBJEXT): {$(VPATH)}probes.h
@@ -5825,7 +5825,9 @@ goruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
goruby.$(OBJEXT): $(top_srcdir)/internal/variable.h
goruby.$(OBJEXT): $(top_srcdir)/internal/vm.h
goruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/ast.h
goruby.$(OBJEXT): $(top_srcdir)/prism/defines.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
goruby.$(OBJEXT): $(top_srcdir)/prism/encoding.h
goruby.$(OBJEXT): $(top_srcdir)/prism/node.h
goruby.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -5845,6 +5847,7 @@ goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/version.h
goruby.$(OBJEXT): {$(VPATH)}assert.h
goruby.$(OBJEXT): {$(VPATH)}atomic.h
goruby.$(OBJEXT): {$(VPATH)}backward.h
@@ -6024,9 +6027,6 @@ goruby.$(OBJEXT): {$(VPATH)}missing.h
goruby.$(OBJEXT): {$(VPATH)}node.h
goruby.$(OBJEXT): {$(VPATH)}onigmo.h
goruby.$(OBJEXT): {$(VPATH)}oniguruma.h
-goruby.$(OBJEXT): {$(VPATH)}prism/ast.h
-goruby.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-goruby.$(OBJEXT): {$(VPATH)}prism/version.h
goruby.$(OBJEXT): {$(VPATH)}prism_compile.h
goruby.$(OBJEXT): {$(VPATH)}ruby_assert.h
goruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h
@@ -6072,7 +6072,9 @@ hash.$(OBJEXT): $(top_srcdir)/internal/time.h
hash.$(OBJEXT): $(top_srcdir)/internal/variable.h
hash.$(OBJEXT): $(top_srcdir)/internal/vm.h
hash.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+hash.$(OBJEXT): $(top_srcdir)/prism/ast.h
hash.$(OBJEXT): $(top_srcdir)/prism/defines.h
+hash.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
hash.$(OBJEXT): $(top_srcdir)/prism/encoding.h
hash.$(OBJEXT): $(top_srcdir)/prism/node.h
hash.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -6092,6 +6094,7 @@ hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+hash.$(OBJEXT): $(top_srcdir)/prism/version.h
hash.$(OBJEXT): {$(VPATH)}assert.h
hash.$(OBJEXT): {$(VPATH)}atomic.h
hash.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -6272,9 +6275,6 @@ hash.$(OBJEXT): {$(VPATH)}missing.h
hash.$(OBJEXT): {$(VPATH)}node.h
hash.$(OBJEXT): {$(VPATH)}onigmo.h
hash.$(OBJEXT): {$(VPATH)}oniguruma.h
-hash.$(OBJEXT): {$(VPATH)}prism/ast.h
-hash.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-hash.$(OBJEXT): {$(VPATH)}prism/version.h
hash.$(OBJEXT): {$(VPATH)}prism_compile.h
hash.$(OBJEXT): {$(VPATH)}probes.dmyh
hash.$(OBJEXT): {$(VPATH)}probes.h
@@ -7149,7 +7149,9 @@ iseq.$(OBJEXT): $(top_srcdir)/internal/thread.h
iseq.$(OBJEXT): $(top_srcdir)/internal/variable.h
iseq.$(OBJEXT): $(top_srcdir)/internal/vm.h
iseq.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/ast.h
iseq.$(OBJEXT): $(top_srcdir)/prism/defines.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
iseq.$(OBJEXT): $(top_srcdir)/prism/encoding.h
iseq.$(OBJEXT): $(top_srcdir)/prism/node.h
iseq.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -7157,6 +7159,7 @@ iseq.$(OBJEXT): $(top_srcdir)/prism/pack.h
iseq.$(OBJEXT): $(top_srcdir)/prism/parser.h
iseq.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
iseq.$(OBJEXT): $(top_srcdir)/prism/prism.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/prism.h
iseq.$(OBJEXT): $(top_srcdir)/prism/regexp.h
iseq.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
@@ -7169,6 +7172,7 @@ iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/version.h
iseq.$(OBJEXT): {$(VPATH)}assert.h
iseq.$(OBJEXT): {$(VPATH)}atomic.h
iseq.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -7352,10 +7356,6 @@ iseq.$(OBJEXT): {$(VPATH)}missing.h
iseq.$(OBJEXT): {$(VPATH)}node.h
iseq.$(OBJEXT): {$(VPATH)}onigmo.h
iseq.$(OBJEXT): {$(VPATH)}oniguruma.h
-iseq.$(OBJEXT): {$(VPATH)}prism/ast.h
-iseq.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-iseq.$(OBJEXT): {$(VPATH)}prism/prism.h
-iseq.$(OBJEXT): {$(VPATH)}prism/version.h
iseq.$(OBJEXT): {$(VPATH)}prism_compile.h
iseq.$(OBJEXT): {$(VPATH)}ractor.h
iseq.$(OBJEXT): {$(VPATH)}ruby_assert.h
@@ -7393,7 +7393,9 @@ jit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
jit.$(OBJEXT): $(top_srcdir)/internal/variable.h
jit.$(OBJEXT): $(top_srcdir)/internal/vm.h
jit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+jit.$(OBJEXT): $(top_srcdir)/prism/ast.h
jit.$(OBJEXT): $(top_srcdir)/prism/defines.h
+jit.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
jit.$(OBJEXT): $(top_srcdir)/prism/encoding.h
jit.$(OBJEXT): $(top_srcdir)/prism/node.h
jit.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -7413,6 +7415,7 @@ jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+jit.$(OBJEXT): $(top_srcdir)/prism/version.h
jit.$(OBJEXT): {$(VPATH)}assert.h
jit.$(OBJEXT): {$(VPATH)}atomic.h
jit.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -7594,9 +7597,6 @@ jit.$(OBJEXT): {$(VPATH)}missing.h
jit.$(OBJEXT): {$(VPATH)}node.h
jit.$(OBJEXT): {$(VPATH)}onigmo.h
jit.$(OBJEXT): {$(VPATH)}oniguruma.h
-jit.$(OBJEXT): {$(VPATH)}prism/ast.h
-jit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-jit.$(OBJEXT): {$(VPATH)}prism/version.h
jit.$(OBJEXT): {$(VPATH)}prism_compile.h
jit.$(OBJEXT): {$(VPATH)}ruby_assert.h
jit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
@@ -7646,7 +7646,9 @@ load.$(OBJEXT): $(top_srcdir)/internal/thread.h
load.$(OBJEXT): $(top_srcdir)/internal/variable.h
load.$(OBJEXT): $(top_srcdir)/internal/vm.h
load.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+load.$(OBJEXT): $(top_srcdir)/prism/ast.h
load.$(OBJEXT): $(top_srcdir)/prism/defines.h
+load.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
load.$(OBJEXT): $(top_srcdir)/prism/encoding.h
load.$(OBJEXT): $(top_srcdir)/prism/node.h
load.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -7666,6 +7668,7 @@ load.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
load.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
load.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
load.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+load.$(OBJEXT): $(top_srcdir)/prism/version.h
load.$(OBJEXT): {$(VPATH)}assert.h
load.$(OBJEXT): {$(VPATH)}atomic.h
load.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -7845,9 +7848,6 @@ load.$(OBJEXT): {$(VPATH)}missing.h
load.$(OBJEXT): {$(VPATH)}node.h
load.$(OBJEXT): {$(VPATH)}onigmo.h
load.$(OBJEXT): {$(VPATH)}oniguruma.h
-load.$(OBJEXT): {$(VPATH)}prism/ast.h
-load.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-load.$(OBJEXT): {$(VPATH)}prism/version.h
load.$(OBJEXT): {$(VPATH)}prism_compile.h
load.$(OBJEXT): {$(VPATH)}probes.dmyh
load.$(OBJEXT): {$(VPATH)}probes.h
@@ -9000,7 +9000,9 @@ miniinit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/variable.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/vm.h
miniinit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/ast.h
miniinit.$(OBJEXT): $(top_srcdir)/prism/defines.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
miniinit.$(OBJEXT): $(top_srcdir)/prism/encoding.h
miniinit.$(OBJEXT): $(top_srcdir)/prism/node.h
miniinit.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -9020,6 +9022,7 @@ miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/version.h
miniinit.$(OBJEXT): {$(VPATH)}array.rb
miniinit.$(OBJEXT): {$(VPATH)}assert.h
miniinit.$(OBJEXT): {$(VPATH)}ast.rb
@@ -9215,9 +9218,6 @@ miniinit.$(OBJEXT): {$(VPATH)}oniguruma.h
miniinit.$(OBJEXT): {$(VPATH)}pack.rb
miniinit.$(OBJEXT): {$(VPATH)}pathname_builtin.rb
miniinit.$(OBJEXT): {$(VPATH)}prelude.rb
-miniinit.$(OBJEXT): {$(VPATH)}prism/ast.h
-miniinit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-miniinit.$(OBJEXT): {$(VPATH)}prism/version.h
miniinit.$(OBJEXT): {$(VPATH)}prism_compile.h
miniinit.$(OBJEXT): {$(VPATH)}ractor.rb
miniinit.$(OBJEXT): {$(VPATH)}ruby_assert.h
@@ -11008,7 +11008,10 @@ pathname.$(OBJEXT): {$(VPATH)}st.h
pathname.$(OBJEXT): {$(VPATH)}subst.h
prism/api_node.$(OBJEXT): $(hdrdir)/ruby.h
prism/api_node.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/api_node.c
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/ast.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/extension.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/node.h
@@ -11029,6 +11032,7 @@ prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/version.h
prism/api_node.$(OBJEXT): {$(VPATH)}assert.h
prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/assume.h
prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
@@ -11195,16 +11199,14 @@ prism/api_node.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
prism/api_node.$(OBJEXT): {$(VPATH)}missing.h
prism/api_node.$(OBJEXT): {$(VPATH)}onigmo.h
prism/api_node.$(OBJEXT): {$(VPATH)}oniguruma.h
-prism/api_node.$(OBJEXT): {$(VPATH)}prism/api_node.c
-prism/api_node.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/api_node.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism/api_node.$(OBJEXT): {$(VPATH)}prism/version.h
prism/api_node.$(OBJEXT): {$(VPATH)}st.h
prism/api_node.$(OBJEXT): {$(VPATH)}subst.h
prism/api_pack.$(OBJEXT): $(hdrdir)/ruby.h
prism/api_pack.$(OBJEXT): $(hdrdir)/ruby/ruby.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/api_pack.c
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/ast.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/extension.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/node.h
@@ -11225,6 +11227,7 @@ prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/version.h
prism/api_pack.$(OBJEXT): {$(VPATH)}assert.h
prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/assume.h
prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
@@ -11391,12 +11394,12 @@ prism/api_pack.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
prism/api_pack.$(OBJEXT): {$(VPATH)}missing.h
prism/api_pack.$(OBJEXT): {$(VPATH)}onigmo.h
prism/api_pack.$(OBJEXT): {$(VPATH)}oniguruma.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}prism/version.h
prism/api_pack.$(OBJEXT): {$(VPATH)}st.h
prism/api_pack.$(OBJEXT): {$(VPATH)}subst.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/ast.h
prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/diagnostic.c
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
@@ -11404,16 +11407,15 @@ prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/diagnostic.c
-prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
prism/encoding.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/encoding.$(OBJEXT): $(top_srcdir)/prism/encoding.c
prism/encoding.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/encoding.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/extension.$(OBJEXT): $(hdrdir)/ruby.h
prism/extension.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/ast.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/extension.c
prism/extension.$(OBJEXT): $(top_srcdir)/prism/extension.h
@@ -11435,6 +11437,7 @@ prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/version.h
prism/extension.$(OBJEXT): {$(VPATH)}assert.h
prism/extension.$(OBJEXT): {$(VPATH)}backward/2/assume.h
prism/extension.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
@@ -11601,13 +11604,13 @@ prism/extension.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
prism/extension.$(OBJEXT): {$(VPATH)}missing.h
prism/extension.$(OBJEXT): {$(VPATH)}onigmo.h
prism/extension.$(OBJEXT): {$(VPATH)}oniguruma.h
-prism/extension.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/extension.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism/extension.$(OBJEXT): {$(VPATH)}prism/version.h
prism/extension.$(OBJEXT): {$(VPATH)}st.h
prism/extension.$(OBJEXT): {$(VPATH)}subst.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/ast.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/node.c
prism/node.$(OBJEXT): $(top_srcdir)/prism/node.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/options.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/pack.h
@@ -11624,9 +11627,6 @@ prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-prism/node.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/node.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism/node.$(OBJEXT): {$(VPATH)}prism/node.c
prism/options.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/options.$(OBJEXT): $(top_srcdir)/prism/options.c
prism/options.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -11636,10 +11636,12 @@ prism/options.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
prism/pack.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/pack.$(OBJEXT): $(top_srcdir)/prism/pack.c
prism/pack.$(OBJEXT): $(top_srcdir)/prism/pack.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/ast.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/options.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/parser.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/prettyprint.c
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
@@ -11650,9 +11652,9 @@ prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/prettyprint.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/prettyprint.$(OBJEXT): {$(VPATH)}prism/prettyprint.c
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/ast.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/node.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -11674,9 +11676,8 @@ prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
prism/prism.$(OBJEXT): $(top_srcdir)/prism/version.h
-prism/prism.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/prism.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism/prism.$(OBJEXT): {$(VPATH)}prism/version.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/version.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/ast.h
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -11693,8 +11694,9 @@ prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/regexp.$(OBJEXT): {$(VPATH)}prism/ast.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/ast.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/node.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -11703,6 +11705,7 @@ prism/serialize.$(OBJEXT): $(top_srcdir)/prism/parser.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/prism.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/serialize.c
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
@@ -11714,10 +11717,8 @@ prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-prism/serialize.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/serialize.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism/serialize.$(OBJEXT): {$(VPATH)}prism/serialize.c
-prism/serialize.$(OBJEXT): {$(VPATH)}prism/version.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/version.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/ast.h
prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/node.h
@@ -11733,16 +11734,15 @@ prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/static_literals.$(OBJEXT): {$(VPATH)}prism/ast.h
+prism/token_type.$(OBJEXT): $(top_srcdir)/prism/ast.h
prism/token_type.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/token_type.$(OBJEXT): $(top_srcdir)/prism/token_type.c
prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/token_type.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/token_type.$(OBJEXT): {$(VPATH)}prism/token_type.c
prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.c
prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
@@ -11764,6 +11764,7 @@ prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.c
prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/ast.h
prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/parser.h
@@ -11774,7 +11775,6 @@ prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/util/pm_memchr.$(OBJEXT): {$(VPATH)}prism/ast.h
prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.c
prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
@@ -11784,7 +11784,9 @@ prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/defines.h
prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.c
prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/ast.h
prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/options.h
prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/parser.h
@@ -11799,11 +11801,11 @@ prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.c
prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-prism/util/pm_strpbrk.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/util/pm_strpbrk.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
prism_init.$(OBJEXT): $(hdrdir)/ruby.h
prism_init.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/ast.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/encoding.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/extension.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/node.h
@@ -11824,6 +11826,7 @@ prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/version.h
prism_init.$(OBJEXT): $(top_srcdir)/prism_init.c
prism_init.$(OBJEXT): {$(VPATH)}assert.h
prism_init.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -11991,9 +11994,6 @@ prism_init.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
prism_init.$(OBJEXT): {$(VPATH)}missing.h
prism_init.$(OBJEXT): {$(VPATH)}onigmo.h
prism_init.$(OBJEXT): {$(VPATH)}oniguruma.h
-prism_init.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism_init.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism_init.$(OBJEXT): {$(VPATH)}prism/version.h
prism_init.$(OBJEXT): {$(VPATH)}prism_init.c
prism_init.$(OBJEXT): {$(VPATH)}st.h
prism_init.$(OBJEXT): {$(VPATH)}subst.h
@@ -12024,7 +12024,9 @@ proc.$(OBJEXT): $(top_srcdir)/internal/symbol.h
proc.$(OBJEXT): $(top_srcdir)/internal/variable.h
proc.$(OBJEXT): $(top_srcdir)/internal/vm.h
proc.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+proc.$(OBJEXT): $(top_srcdir)/prism/ast.h
proc.$(OBJEXT): $(top_srcdir)/prism/defines.h
+proc.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
proc.$(OBJEXT): $(top_srcdir)/prism/encoding.h
proc.$(OBJEXT): $(top_srcdir)/prism/node.h
proc.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -12044,6 +12046,7 @@ proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+proc.$(OBJEXT): $(top_srcdir)/prism/version.h
proc.$(OBJEXT): {$(VPATH)}assert.h
proc.$(OBJEXT): {$(VPATH)}atomic.h
proc.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -12221,9 +12224,6 @@ proc.$(OBJEXT): {$(VPATH)}missing.h
proc.$(OBJEXT): {$(VPATH)}node.h
proc.$(OBJEXT): {$(VPATH)}onigmo.h
proc.$(OBJEXT): {$(VPATH)}oniguruma.h
-proc.$(OBJEXT): {$(VPATH)}prism/ast.h
-proc.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-proc.$(OBJEXT): {$(VPATH)}prism/version.h
proc.$(OBJEXT): {$(VPATH)}prism_compile.h
proc.$(OBJEXT): {$(VPATH)}proc.c
proc.$(OBJEXT): {$(VPATH)}ractor.h
@@ -14578,7 +14578,9 @@ ruby.$(OBJEXT): $(top_srcdir)/internal/thread.h
ruby.$(OBJEXT): $(top_srcdir)/internal/variable.h
ruby.$(OBJEXT): $(top_srcdir)/internal/vm.h
ruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/ast.h
ruby.$(OBJEXT): $(top_srcdir)/prism/defines.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
ruby.$(OBJEXT): $(top_srcdir)/prism/encoding.h
ruby.$(OBJEXT): $(top_srcdir)/prism/node.h
ruby.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -14598,6 +14600,7 @@ ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/version.h
ruby.$(OBJEXT): {$(VPATH)}assert.h
ruby.$(OBJEXT): {$(VPATH)}atomic.h
ruby.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -14777,9 +14780,6 @@ ruby.$(OBJEXT): {$(VPATH)}missing.h
ruby.$(OBJEXT): {$(VPATH)}node.h
ruby.$(OBJEXT): {$(VPATH)}onigmo.h
ruby.$(OBJEXT): {$(VPATH)}oniguruma.h
-ruby.$(OBJEXT): {$(VPATH)}prism/ast.h
-ruby.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-ruby.$(OBJEXT): {$(VPATH)}prism/version.h
ruby.$(OBJEXT): {$(VPATH)}prism_compile.h
ruby.$(OBJEXT): {$(VPATH)}ruby.c
ruby.$(OBJEXT): {$(VPATH)}ruby_assert.h
@@ -17280,7 +17280,9 @@ thread.$(OBJEXT): $(top_srcdir)/internal/time.h
thread.$(OBJEXT): $(top_srcdir)/internal/variable.h
thread.$(OBJEXT): $(top_srcdir)/internal/vm.h
thread.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+thread.$(OBJEXT): $(top_srcdir)/prism/ast.h
thread.$(OBJEXT): $(top_srcdir)/prism/defines.h
+thread.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
thread.$(OBJEXT): $(top_srcdir)/prism/encoding.h
thread.$(OBJEXT): $(top_srcdir)/prism/node.h
thread.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -17300,6 +17302,7 @@ thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+thread.$(OBJEXT): $(top_srcdir)/prism/version.h
thread.$(OBJEXT): {$(VPATH)}$(COROUTINE_H)
thread.$(OBJEXT): {$(VPATH)}assert.h
thread.$(OBJEXT): {$(VPATH)}atomic.h
@@ -17483,9 +17486,6 @@ thread.$(OBJEXT): {$(VPATH)}missing.h
thread.$(OBJEXT): {$(VPATH)}node.h
thread.$(OBJEXT): {$(VPATH)}onigmo.h
thread.$(OBJEXT): {$(VPATH)}oniguruma.h
-thread.$(OBJEXT): {$(VPATH)}prism/ast.h
-thread.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-thread.$(OBJEXT): {$(VPATH)}prism/version.h
thread.$(OBJEXT): {$(VPATH)}prism_compile.h
thread.$(OBJEXT): {$(VPATH)}ractor.h
thread.$(OBJEXT): {$(VPATH)}ractor_core.h
@@ -18568,7 +18568,9 @@ vm.$(OBJEXT): $(top_srcdir)/internal/transcode.h
vm.$(OBJEXT): $(top_srcdir)/internal/variable.h
vm.$(OBJEXT): $(top_srcdir)/internal/vm.h
vm.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+vm.$(OBJEXT): $(top_srcdir)/prism/ast.h
vm.$(OBJEXT): $(top_srcdir)/prism/defines.h
+vm.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
vm.$(OBJEXT): $(top_srcdir)/prism/encoding.h
vm.$(OBJEXT): $(top_srcdir)/prism/node.h
vm.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -18588,6 +18590,7 @@ vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+vm.$(OBJEXT): $(top_srcdir)/prism/version.h
vm.$(OBJEXT): {$(VPATH)}assert.h
vm.$(OBJEXT): {$(VPATH)}atomic.h
vm.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -18772,9 +18775,6 @@ vm.$(OBJEXT): {$(VPATH)}missing.h
vm.$(OBJEXT): {$(VPATH)}node.h
vm.$(OBJEXT): {$(VPATH)}onigmo.h
vm.$(OBJEXT): {$(VPATH)}oniguruma.h
-vm.$(OBJEXT): {$(VPATH)}prism/ast.h
-vm.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-vm.$(OBJEXT): {$(VPATH)}prism/version.h
vm.$(OBJEXT): {$(VPATH)}prism_compile.h
vm.$(OBJEXT): {$(VPATH)}probes.dmyh
vm.$(OBJEXT): {$(VPATH)}probes.h
@@ -18832,7 +18832,9 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/string.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/variable.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/vm.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/ast.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/defines.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/encoding.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/node.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -18852,6 +18854,7 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/version.h
vm_backtrace.$(OBJEXT): {$(VPATH)}assert.h
vm_backtrace.$(OBJEXT): {$(VPATH)}atomic.h
vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -19030,9 +19033,6 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}missing.h
vm_backtrace.$(OBJEXT): {$(VPATH)}node.h
vm_backtrace.$(OBJEXT): {$(VPATH)}onigmo.h
vm_backtrace.$(OBJEXT): {$(VPATH)}oniguruma.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}prism/ast.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}prism/version.h
vm_backtrace.$(OBJEXT): {$(VPATH)}prism_compile.h
vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_atomic.h
@@ -19065,7 +19065,9 @@ vm_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/vm.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/ast.h
vm_dump.$(OBJEXT): $(top_srcdir)/prism/defines.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
vm_dump.$(OBJEXT): $(top_srcdir)/prism/encoding.h
vm_dump.$(OBJEXT): $(top_srcdir)/prism/node.h
vm_dump.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -19085,6 +19087,7 @@ vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/version.h
vm_dump.$(OBJEXT): {$(VPATH)}addr2line.h
vm_dump.$(OBJEXT): {$(VPATH)}assert.h
vm_dump.$(OBJEXT): {$(VPATH)}atomic.h
@@ -19262,9 +19265,6 @@ vm_dump.$(OBJEXT): {$(VPATH)}missing.h
vm_dump.$(OBJEXT): {$(VPATH)}node.h
vm_dump.$(OBJEXT): {$(VPATH)}onigmo.h
vm_dump.$(OBJEXT): {$(VPATH)}oniguruma.h
-vm_dump.$(OBJEXT): {$(VPATH)}prism/ast.h
-vm_dump.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-vm_dump.$(OBJEXT): {$(VPATH)}prism/version.h
vm_dump.$(OBJEXT): {$(VPATH)}prism_compile.h
vm_dump.$(OBJEXT): {$(VPATH)}procstat_vm.c
vm_dump.$(OBJEXT): {$(VPATH)}ractor.h
@@ -19514,7 +19514,9 @@ vm_trace.$(OBJEXT): $(top_srcdir)/internal/thread.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/variable.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/vm.h
vm_trace.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/ast.h
vm_trace.$(OBJEXT): $(top_srcdir)/prism/defines.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
vm_trace.$(OBJEXT): $(top_srcdir)/prism/encoding.h
vm_trace.$(OBJEXT): $(top_srcdir)/prism/node.h
vm_trace.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -19534,6 +19536,7 @@ vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/version.h
vm_trace.$(OBJEXT): {$(VPATH)}assert.h
vm_trace.$(OBJEXT): {$(VPATH)}atomic.h
vm_trace.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -19713,9 +19716,6 @@ vm_trace.$(OBJEXT): {$(VPATH)}missing.h
vm_trace.$(OBJEXT): {$(VPATH)}node.h
vm_trace.$(OBJEXT): {$(VPATH)}onigmo.h
vm_trace.$(OBJEXT): {$(VPATH)}oniguruma.h
-vm_trace.$(OBJEXT): {$(VPATH)}prism/ast.h
-vm_trace.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-vm_trace.$(OBJEXT): {$(VPATH)}prism/version.h
vm_trace.$(OBJEXT): {$(VPATH)}prism_compile.h
vm_trace.$(OBJEXT): {$(VPATH)}ractor.h
vm_trace.$(OBJEXT): {$(VPATH)}ruby_assert.h
@@ -19962,7 +19962,9 @@ yjit.$(OBJEXT): $(top_srcdir)/internal/string.h
yjit.$(OBJEXT): $(top_srcdir)/internal/variable.h
yjit.$(OBJEXT): $(top_srcdir)/internal/vm.h
yjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/ast.h
yjit.$(OBJEXT): $(top_srcdir)/prism/defines.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
yjit.$(OBJEXT): $(top_srcdir)/prism/encoding.h
yjit.$(OBJEXT): $(top_srcdir)/prism/node.h
yjit.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -19982,6 +19984,7 @@ yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/version.h
yjit.$(OBJEXT): {$(VPATH)}assert.h
yjit.$(OBJEXT): {$(VPATH)}atomic.h
yjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -20164,9 +20167,6 @@ yjit.$(OBJEXT): {$(VPATH)}missing.h
yjit.$(OBJEXT): {$(VPATH)}node.h
yjit.$(OBJEXT): {$(VPATH)}onigmo.h
yjit.$(OBJEXT): {$(VPATH)}oniguruma.h
-yjit.$(OBJEXT): {$(VPATH)}prism/ast.h
-yjit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-yjit.$(OBJEXT): {$(VPATH)}prism/version.h
yjit.$(OBJEXT): {$(VPATH)}prism_compile.h
yjit.$(OBJEXT): {$(VPATH)}probes.dmyh
yjit.$(OBJEXT): {$(VPATH)}probes.h
@@ -20214,7 +20214,9 @@ zjit.$(OBJEXT): $(top_srcdir)/internal/string.h
zjit.$(OBJEXT): $(top_srcdir)/internal/variable.h
zjit.$(OBJEXT): $(top_srcdir)/internal/vm.h
zjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/ast.h
zjit.$(OBJEXT): $(top_srcdir)/prism/defines.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
zjit.$(OBJEXT): $(top_srcdir)/prism/encoding.h
zjit.$(OBJEXT): $(top_srcdir)/prism/node.h
zjit.$(OBJEXT): $(top_srcdir)/prism/options.h
@@ -20234,6 +20236,7 @@ zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/version.h
zjit.$(OBJEXT): {$(VPATH)}assert.h
zjit.$(OBJEXT): {$(VPATH)}atomic.h
zjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h
@@ -20415,9 +20418,6 @@ zjit.$(OBJEXT): {$(VPATH)}missing.h
zjit.$(OBJEXT): {$(VPATH)}node.h
zjit.$(OBJEXT): {$(VPATH)}onigmo.h
zjit.$(OBJEXT): {$(VPATH)}oniguruma.h
-zjit.$(OBJEXT): {$(VPATH)}prism/ast.h
-zjit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-zjit.$(OBJEXT): {$(VPATH)}prism/version.h
zjit.$(OBJEXT): {$(VPATH)}prism_compile.h
zjit.$(OBJEXT): {$(VPATH)}probes.dmyh
zjit.$(OBJEXT): {$(VPATH)}probes.h
diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c
index 5248a9e26a..9c6ed93049 100644
--- a/ext/json/generator/generator.c
+++ b/ext/json/generator/generator.c
@@ -137,8 +137,8 @@ static inline FORCE_INLINE void search_flush(search_state *search)
{
// Do not remove this conditional without profiling, specifically escape-heavy text.
// escape_UTF8_char_basic will advance search->ptr and search->cursor (effectively a search_flush).
- // For back-to-back characters that need to be escaped, specifcally for the SIMD code paths, this method
- // will be called just before calling escape_UTF8_char_basic. There will be no characers to append for the
+ // For back-to-back characters that need to be escaped, specifically for the SIMD code paths, this method
+ // will be called just before calling escape_UTF8_char_basic. There will be no characters to append for the
// consecutive characters that need to be escaped. While the fbuffer_append is a no-op if
// nothing needs to be flushed, we can save a few memory references with this conditional.
if (search->ptr > search->cursor) {
diff --git a/ext/json/lib/json.rb b/ext/json/lib/json.rb
index 735f238066..0ebff2f948 100644
--- a/ext/json/lib/json.rb
+++ b/ext/json/lib/json.rb
@@ -133,7 +133,7 @@ require 'json/common'
# When not specified:
# # The last value is used and a deprecation warning emitted.
# JSON.parse('{"a": 1, "a":2}') => {"a" => 2}
-# # waring: detected duplicate keys in JSON object.
+# # warning: detected duplicate keys in JSON object.
# # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`
#
# When set to `+true+`
diff --git a/ext/json/lib/json/add/string.rb b/ext/json/lib/json/add/string.rb
index 46f07967cd..9c3bde27fb 100644
--- a/ext/json/lib/json/add/string.rb
+++ b/ext/json/lib/json/add/string.rb
@@ -5,7 +5,7 @@ end
class String
# call-seq: json_create(o)
- #
+ #
# Raw Strings are JSON Objects (the raw bytes are stored in an array for the
# key "raw"). The Ruby String can be created by this class method.
def self.json_create(object)
@@ -13,7 +13,7 @@ class String
end
# call-seq: to_json_raw_object()
- #
+ #
# This method creates a raw object hash, that can be nested into
# other data structures and will be generated as a raw string. This
# method should be used, if you want to convert raw strings to JSON
@@ -26,10 +26,10 @@ class String
end
# call-seq: to_json_raw(*args)
- #
+ #
# This method creates a JSON text from the result of a call to
# to_json_raw_object of this String.
def to_json_raw(...)
to_json_raw_object.to_json(...)
end
-end \ No newline at end of file
+end
diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb
index 9a878cead9..e99d152a88 100644
--- a/ext/json/lib/json/common.rb
+++ b/ext/json/lib/json/common.rb
@@ -1002,7 +1002,7 @@ module JSON
# See {Parsing Options}[#module-JSON-label-Parsing+Options], and {Generating Options}[#module-JSON-label-Generating+Options].
#
# For generation, the <tt>strict: true</tt> option is always set. When a Ruby object with no native \JSON counterpart is
- # encoutered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native
+ # encountered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native
# \JSON counterpart:
#
# module MyApp
diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c
index ab9d6c205e..1e6ee753f0 100644
--- a/ext/json/parser/parser.c
+++ b/ext/json/parser/parser.c
@@ -1265,7 +1265,7 @@ static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
break;
}
- raise_parse_error("unreacheable: %s", state);
+ raise_parse_error("unreachable: %s", state);
}
static void json_ensure_eof(JSON_ParserState *state)
diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c
index 8291578f27..c18596cbf5 100644
--- a/ext/openssl/ossl_x509store.c
+++ b/ext/openssl/ossl_x509store.c
@@ -191,8 +191,8 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
GetX509Store(self, store);
rb_iv_set(self, "@verify_callback", cb);
- // We don't need to trigger a write barrier because `rb_iv_set` did it.
X509_STORE_set_ex_data(store, store_ex_verify_cb_idx, (void *)cb);
+ RB_OBJ_WRITTEN(self, Qundef, cb);
return cb;
}
@@ -611,6 +611,7 @@ ossl_x509stctx_verify(VALUE self)
GetX509StCtx(self, ctx);
VALUE cb = rb_iv_get(self, "@verify_callback");
X509_STORE_CTX_set_ex_data(ctx, stctx_ex_verify_cb_idx, (void *)cb);
+ RB_OBJ_WRITTEN(self, Qundef, cb);
switch (X509_verify_cert(ctx)) {
case 1:
diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c
index bc6c303c36..ca00e51ee7 100644
--- a/ext/socket/raddrinfo.c
+++ b/ext/socket/raddrinfo.c
@@ -578,6 +578,10 @@ start:
#endif
+#define GETNAMEINFO_WONT_BLOCK(host, serv, flags) \
+ ((!(host) || ((flags) & NI_NUMERICHOST)) && \
+ (!(serv) || ((flags) & NI_NUMERICSERV)))
+
#if GETADDRINFO_IMPL == 0
int
@@ -615,6 +619,10 @@ rb_getnameinfo(const struct sockaddr *sa, socklen_t salen,
char *host, size_t hostlen,
char *serv, size_t servlen, int flags)
{
+ if (GETNAMEINFO_WONT_BLOCK(host, serv, flags)) {
+ return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+ }
+
struct getnameinfo_arg arg;
int ret;
arg.sa = sa;
@@ -743,6 +751,10 @@ rb_getnameinfo(const struct sockaddr *sa, socklen_t salen,
struct getnameinfo_arg *arg;
int err = 0, gni_errno = 0;
+ if (GETNAMEINFO_WONT_BLOCK(host, serv, flags)) {
+ return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+ }
+
start:
retry = 0;
diff --git a/gc.c b/gc.c
index 160398f9a6..c2fc681253 100644
--- a/gc.c
+++ b/gc.c
@@ -4698,19 +4698,22 @@ rb_raw_obj_info_buitin_type(char *const buff, const size_t buff_size, const VALU
APPEND_S("shared -> ");
rb_raw_obj_info(BUFF_ARGS, ARY_SHARED_ROOT(obj));
}
- else if (ARY_EMBED_P(obj)) {
- APPEND_F("[%s%s] len: %ld (embed)",
- C(ARY_EMBED_P(obj), "E"),
- C(ARY_SHARED_P(obj), "S"),
- RARRAY_LEN(obj));
- }
else {
- APPEND_F("[%s%s] len: %ld, capa:%ld ptr:%p",
- C(ARY_EMBED_P(obj), "E"),
+ APPEND_F("[%s%s%s] ",
+ C(ARY_EMBED_P(obj), "E"),
C(ARY_SHARED_P(obj), "S"),
- RARRAY_LEN(obj),
- ARY_EMBED_P(obj) ? -1L : RARRAY(obj)->as.heap.aux.capa,
- (void *)RARRAY_CONST_PTR(obj));
+ C(ARY_SHARED_ROOT_P(obj), "R"));
+
+ if (ARY_EMBED_P(obj)) {
+ APPEND_F("len: %ld (embed)",
+ RARRAY_LEN(obj));
+ }
+ else {
+ APPEND_F("len: %ld, capa:%ld ptr:%p",
+ RARRAY_LEN(obj),
+ RARRAY(obj)->as.heap.aux.capa,
+ (void *)RARRAY_CONST_PTR(obj));
+ }
}
break;
case T_STRING: {
diff --git a/hash.c b/hash.c
index de9bc97ea6..8c645c3d84 100644
--- a/hash.c
+++ b/hash.c
@@ -321,40 +321,35 @@ objid_hash(VALUE obj)
#endif
}
-/**
+/*
* call-seq:
- * obj.hash -> integer
- *
- * Generates an Integer hash value for this object. This function must have the
- * property that <code>a.eql?(b)</code> implies <code>a.hash == b.hash</code>.
- *
- * The hash value is used along with #eql? by the Hash class to determine if
- * two objects reference the same hash key. Any hash value that exceeds the
- * capacity of an Integer will be truncated before being used.
+ * hash -> integer
*
- * The hash value for an object may not be identical across invocations or
- * implementations of Ruby. If you need a stable identifier across Ruby
- * invocations and implementations you will need to generate one with a custom
- * method.
+ * Returns the integer hash value for +self+;
+ * has the property that if <tt>foo.eql?(bar)</tt>
+ * then <tt>foo.hash == bar.hash</tt>.
*
- * Certain core classes such as Integer use built-in hash calculations and
- * do not call the #hash method when used as a hash key.
+ * \Class Hash uses both #hash and #eql? to determine whether two objects
+ * used as hash keys are to be treated as the same key.
+ * A hash value that exceeds the capacity of an Integer is truncated before being used.
*
- * When implementing your own #hash based on multiple values, the best
- * practice is to combine the class and any values using the hash code of an
- * array:
+ * Many core classes override method Object#hash;
+ * other core classes (e.g., Integer) calculate the hash internally,
+ * and do not call the #hash method when used as a hash key.
*
- * For example:
+ * When implementing #hash for a user-defined class,
+ * best practice is to use Array#hash with the class name and the values
+ * that are important in the instance;
+ * this takes advantage of that method's logic for safely and efficiently
+ * generating a hash value:
*
* def hash
* [self.class, a, b, c].hash
* end
*
- * The reason for this is that the Array#hash method already has logic for
- * safely and efficiently combining multiple hash values.
- *--
- * \private
- *++
+ * The hash value may differ among invocations or implementations of Ruby.
+ * If you need stable hash-like identifiers across Ruby invocations and implementations,
+ * use a custom method to generate them.
*/
VALUE
rb_obj_hash(VALUE obj)
diff --git a/internal/re.h b/internal/re.h
index 2788f8b42a..593e5c464f 100644
--- a/internal/re.h
+++ b/internal/re.h
@@ -25,4 +25,9 @@ int rb_match_count(VALUE match);
VALUE rb_reg_new_ary(VALUE ary, int options);
VALUE rb_reg_last_defined(VALUE match);
+#define ARG_REG_OPTION_MASK \
+ (ONIG_OPTION_IGNORECASE|ONIG_OPTION_MULTILINE|ONIG_OPTION_EXTEND)
+#define ARG_ENCODING_FIXED 16
+#define ARG_ENCODING_NONE 32
+
#endif /* INTERNAL_RE_H */
diff --git a/iseq.c b/iseq.c
index 4334bdd795..09346994dd 100644
--- a/iseq.c
+++ b/iseq.c
@@ -1497,9 +1497,9 @@ rb_iseq_remove_coverage_all(void)
/* define wrapper class methods (RubyVM::InstructionSequence) */
static void
-iseqw_mark(void *ptr)
+iseqw_mark_and_move(void *ptr)
{
- rb_gc_mark_movable(*(VALUE *)ptr);
+ rb_gc_mark_and_move((VALUE *)ptr);
}
static size_t
@@ -1508,20 +1508,13 @@ iseqw_memsize(const void *ptr)
return rb_iseq_memsize(*(const rb_iseq_t **)ptr);
}
-static void
-iseqw_ref_update(void *ptr)
-{
- VALUE *vptr = ptr;
- *vptr = rb_gc_location(*vptr);
-}
-
static const rb_data_type_t iseqw_data_type = {
"T_IMEMO/iseq",
{
- iseqw_mark,
+ iseqw_mark_and_move,
RUBY_TYPED_DEFAULT_FREE,
iseqw_memsize,
- iseqw_ref_update,
+ iseqw_mark_and_move,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
};
diff --git a/lib/bundler/checksum.rb b/lib/bundler/checksum.rb
index 356f4a48bc..ce05818bb0 100644
--- a/lib/bundler/checksum.rb
+++ b/lib/bundler/checksum.rb
@@ -205,6 +205,12 @@ module Bundler
@store[spec.lock_name].nil?
end
+ def empty?(spec)
+ return false unless spec.source.is_a?(Bundler::Source::Rubygems)
+
+ @store[spec.lock_name].empty?
+ end
+
def register(spec, checksum)
register_checksum(spec.lock_name, checksum)
end
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb
index ea85f9af22..47a39069cc 100644
--- a/lib/bundler/cli.rb
+++ b/lib/bundler/cli.rb
@@ -287,8 +287,8 @@ module Bundler
method_option "outdated", type: :boolean, banner: "Show verbose output including whether gems are outdated."
def show(gem_name = nil)
if ARGV.include?("--outdated")
- message = "the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement"
- removed_message = "the `--outdated` flag to `bundle show` was undocumented and has been removed without replacement"
+ message = "the `--outdated` flag to `bundle show` will be removed in favor of `bundle show --verbose`"
+ removed_message = "the `--outdated` flag to `bundle show` has been removed in favor of `bundle show --verbose`"
SharedHelpers.major_deprecation(2, message, removed_message: removed_message)
end
require_relative "cli/show"
@@ -299,6 +299,7 @@ module Bundler
method_option "name-only", type: :boolean, banner: "print only the gem names"
method_option "only-group", type: :array, default: [], banner: "print gems from a given set of groups"
method_option "without-group", type: :array, default: [], banner: "print all gems except from a given set of groups"
+ method_option "format", type: :string, banner: "format output ('json' is the only supported format)"
method_option "paths", type: :boolean, banner: "print the path to each gem in the bundle"
def list
require_relative "cli/list"
@@ -412,6 +413,7 @@ module Bundler
D
def cache
print_remembered_flag_deprecation("--all", "cache_all", "true") if ARGV.include?("--all")
+ print_remembered_flag_deprecation("--no-all", "cache_all", "false") if ARGV.include?("--no-all")
if flag_passed?("--path")
message =
@@ -518,11 +520,11 @@ module Bundler
Viz requires the ruby-graphviz gem (and its dependencies).
The associated gems must also be installed via 'bundle install'.
D
- method_option :file, type: :string, default: "gem_graph", aliases: "-f", desc: "The name to use for the generated file. see format option"
- method_option :format, type: :string, default: "png", aliases: "-F", desc: "This is output format option. Supported format is png, jpg, svg, dot ..."
- method_option :requirements, type: :boolean, default: false, aliases: "-R", desc: "Set to show the version of each required dependency."
- method_option :version, type: :boolean, default: false, aliases: "-v", desc: "Set to show each gem version."
- method_option :without, type: :array, default: [], aliases: "-W", banner: "GROUP[ GROUP...]", desc: "Exclude gems that are part of the specified named group."
+ method_option :file, type: :string, default: "gem_graph", aliases: "-f", banner: "The name to use for the generated file. see format option"
+ method_option :format, type: :string, default: "png", aliases: "-F", banner: "This is output format option. Supported format is png, jpg, svg, dot ..."
+ method_option :requirements, type: :boolean, default: false, aliases: "-R", banner: "Set to show the version of each required dependency."
+ method_option :version, type: :boolean, default: false, aliases: "-v", banner: "Set to show each gem version."
+ method_option :without, type: :array, default: [], aliases: "-W", banner: "Exclude gems that are part of the specified named group."
def viz
SharedHelpers.major_deprecation 2, "The `viz` command has been renamed to `graph` and moved to a plugin. See https://github.com/rubygems/bundler-graph"
require_relative "cli/viz"
@@ -531,19 +533,19 @@ module Bundler
end
desc "gem NAME [OPTIONS]", "Creates a skeleton for creating a rubygem"
- method_option :exe, type: :boolean, default: false, aliases: ["--bin", "-b"], desc: "Generate a binary executable for your library."
- method_option :coc, type: :boolean, desc: "Generate a code of conduct file. Set a default with `bundle config set --global gem.coc true`."
- method_option :edit, type: :string, aliases: "-e", required: false, banner: "EDITOR", lazy_default: [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? }, desc: "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)"
- method_option :ext, type: :string, desc: "Generate the boilerplate for C extension code.", enum: EXTENSIONS
- method_option :git, type: :boolean, default: true, desc: "Initialize a git repo inside your library."
- method_option :mit, type: :boolean, desc: "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`."
- method_option :rubocop, type: :boolean, desc: "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true`."
- method_option :changelog, type: :boolean, desc: "Generate changelog file. Set a default with `bundle config set --global gem.changelog true`."
+ method_option :exe, type: :boolean, default: false, aliases: ["--bin", "-b"], banner: "Generate a binary executable for your library."
+ method_option :coc, type: :boolean, banner: "Generate a code of conduct file. Set a default with `bundle config set --global gem.coc true`."
+ method_option :edit, type: :string, aliases: "-e", required: false, lazy_default: [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? }, banner: "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)"
+ method_option :ext, type: :string, banner: "Generate the boilerplate for C extension code.", enum: EXTENSIONS
+ method_option :git, type: :boolean, default: true, banner: "Initialize a git repo inside your library."
+ method_option :mit, type: :boolean, banner: "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`."
+ method_option :rubocop, type: :boolean, banner: "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true`."
+ method_option :changelog, type: :boolean, banner: "Generate changelog file. Set a default with `bundle config set --global gem.changelog true`."
method_option :test, type: :string, lazy_default: Bundler.settings["gem.test"] || "", aliases: "-t", banner: "Use the specified test framework for your library", enum: %w[rspec minitest test-unit], desc: "Generate a test directory for your library, either rspec, minitest or test-unit. Set a default with `bundle config set --global gem.test (rspec|minitest|test-unit)`."
- method_option :ci, type: :string, lazy_default: Bundler.settings["gem.ci"] || "", enum: %w[github gitlab circle], desc: "Generate CI configuration, either GitHub Actions, GitLab CI or CircleCI. Set a default with `bundle config set --global gem.ci (github|gitlab|circle)`"
- method_option :linter, type: :string, lazy_default: Bundler.settings["gem.linter"] || "", enum: %w[rubocop standard], desc: "Add a linter and code formatter, either RuboCop or Standard. Set a default with `bundle config set --global gem.linter (rubocop|standard)`"
+ method_option :ci, type: :string, lazy_default: Bundler.settings["gem.ci"] || "", enum: %w[github gitlab circle], banner: "Generate CI configuration, either GitHub Actions, GitLab CI or CircleCI. Set a default with `bundle config set --global gem.ci (github|gitlab|circle)`"
+ method_option :linter, type: :string, lazy_default: Bundler.settings["gem.linter"] || "", enum: %w[rubocop standard], banner: "Add a linter and code formatter, either RuboCop or Standard. Set a default with `bundle config set --global gem.linter (rubocop|standard)`"
method_option :github_username, type: :string, default: Bundler.settings["gem.github_username"], banner: "Set your username on GitHub", desc: "Fill in GitHub username on README so that you don't have to do it manually. Set a default with `bundle config set --global gem.github_username <your_username>`."
- method_option :bundle, type: :boolean, default: Bundler.settings["gem.bundle"], desc: "Automatically run `bundle install` after creation. Set a default with `bundle config set --global gem.bundle true`"
+ method_option :bundle, type: :boolean, default: Bundler.settings["gem.bundle"], banner: "Automatically run `bundle install` after creation. Set a default with `bundle config set --global gem.bundle true`"
def gem(name)
require_relative "cli/gem"
@@ -713,7 +715,12 @@ module Bundler
command_name = cmd.name
return if PARSEABLE_COMMANDS.include?(command_name)
command = ["bundle", command_name] + args
- command << Thor::Options.to_switches(options.sort_by(&:first)).strip
+ options_to_print = options.dup
+ options_to_print.delete_if do |k, v|
+ next unless o = cmd.options[k]
+ o.default == v
+ end
+ command << Thor::Options.to_switches(options_to_print.sort_by(&:first)).strip
command.reject!(&:empty?)
Bundler.ui.info "Running `#{command * " "}` with bundler #{Bundler.verbose_version}"
end
diff --git a/lib/bundler/cli/list.rb b/lib/bundler/cli/list.rb
index f56bf5b86a..6a467f45a9 100644
--- a/lib/bundler/cli/list.rb
+++ b/lib/bundler/cli/list.rb
@@ -1,11 +1,14 @@
# frozen_string_literal: true
+require "json"
+
module Bundler
class CLI::List
def initialize(options)
@options = options
@without_group = options["without-group"].map(&:to_sym)
@only_group = options["only-group"].map(&:to_sym)
+ @format = options["format"]
end
def run
@@ -25,6 +28,36 @@ module Bundler
end
end.reject {|s| s.name == "bundler" }.sort_by(&:name)
+ case @format
+ when "json"
+ print_json(specs: specs)
+ when nil
+ print_human(specs: specs)
+ else
+ raise InvalidOption, "Unknown option`--format=#{@format}`. Supported formats: `json`"
+ end
+ end
+
+ private
+
+ def print_json(specs:)
+ gems = if @options["name-only"]
+ specs.map {|s| { name: s.name } }
+ else
+ specs.map do |s|
+ {
+ name: s.name,
+ version: s.version.to_s,
+ git_version: s.git_version&.strip,
+ }.tap do |h|
+ h[:path] = s.full_gem_path if @options["paths"]
+ end
+ end
+ end
+ Bundler.ui.info({ gems: gems }.to_json)
+ end
+
+ def print_human(specs:)
return Bundler.ui.info "No gems in the Gemfile" if specs.empty?
return specs.each {|s| Bundler.ui.info s.name } if @options["name-only"]
@@ -37,8 +70,6 @@ module Bundler
Bundler.ui.info "Use `bundle info` to print more detailed information about a gem"
end
- private
-
def verify_group_exists(groups)
(@without_group + @only_group).each do |group|
raise InvalidOption, "`#{group}` group could not be found." unless groups.include?(group)
diff --git a/lib/bundler/cli/show.rb b/lib/bundler/cli/show.rb
index 13bb8b774b..b55eb7bad5 100644
--- a/lib/bundler/cli/show.rb
+++ b/lib/bundler/cli/show.rb
@@ -57,12 +57,8 @@ module Bundler
def fetch_latest_specs
definition = Bundler.definition(true)
- if options[:outdated]
- Bundler.ui.info "Fetching remote specs for outdated check...\n\n"
- Bundler.ui.silence { definition.remotely! }
- else
- definition.with_cache!
- end
+ Bundler.ui.info "Fetching remote specs for outdated check...\n\n"
+ Bundler.ui.silence { definition.remotely! }
Bundler.reset!
definition.specs
end
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 6c7a3e9c38..52f9c6e125 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -492,8 +492,6 @@ module Bundler
@unlocking
end
- attr_writer :source_requirements
-
def add_checksums
@locked_checksums = true
@@ -533,7 +531,7 @@ module Bundler
return unless added.any? || deleted.any? || changed.any? || resolve_needed?
- msg = String.new("#{change_reason.capitalize.strip}, but ")
+ msg = String.new("#{change_reason[0].upcase}#{change_reason[1..-1].strip}, but ")
msg << "the lockfile " unless msg.start_with?("Your lockfile")
msg << "can't be updated because #{update_refused_reason}"
msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
@@ -559,6 +557,7 @@ module Bundler
@missing_lockfile_dep ||
@unlocking_bundler ||
@locked_spec_with_missing_checksums ||
+ @locked_spec_with_empty_checksums ||
@locked_spec_with_missing_deps ||
@locked_spec_with_invalid_deps
end
@@ -614,7 +613,7 @@ module Bundler
end
def resolver
- @resolver ||= Resolver.new(resolution_base, gem_version_promoter, @most_specific_locked_platform)
+ @resolver ||= new_resolver(resolution_base)
end
def expanded_dependencies
@@ -632,8 +631,7 @@ module Bundler
@resolution_base ||= begin
last_resolve = converge_locked_specs
remove_invalid_platforms!
- new_resolution_platforms = @current_platform_missing ? @new_platforms + [Bundler.local_platform] : @new_platforms
- base = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @unlocking_all || @gems_to_unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms)
+ base = new_resolution_base(last_resolve: last_resolve, unlock: @unlocking_all || @gems_to_unlock)
base = additional_base_requirements_to_prevent_downgrades(base)
base = additional_base_requirements_to_force_updates(base)
base
@@ -839,6 +837,7 @@ module Bundler
[@missing_lockfile_dep, "your lockfile is missing \"#{@missing_lockfile_dep}\""],
[@unlocking_bundler, "an update to the version of Bundler itself was requested"],
[@locked_spec_with_missing_checksums, "your lockfile is missing a CHECKSUMS entry for \"#{@locked_spec_with_missing_checksums}\""],
+ [@locked_spec_with_empty_checksums, "your lockfile has an empty CHECKSUMS entry for \"#{@locked_spec_with_empty_checksums}\""],
[@locked_spec_with_missing_deps, "your lockfile includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"],
[@locked_spec_with_invalid_deps, "your lockfile does not satisfy dependencies of \"#{@locked_spec_with_invalid_deps}\""],
].select(&:first).map(&:last).join(", ")
@@ -898,13 +897,23 @@ module Bundler
@locked_spec_with_invalid_deps = nil
@locked_spec_with_missing_deps = nil
@locked_spec_with_missing_checksums = nil
+ @locked_spec_with_empty_checksums = nil
missing_deps = []
missing_checksums = []
+ empty_checksums = []
invalid = []
@locked_specs.each do |s|
- missing_checksums << s if @locked_checksums && s.source.checksum_store.missing?(s)
+ if @locked_checksums
+ checksum_store = s.source.checksum_store
+
+ if checksum_store.missing?(s)
+ missing_checksums << s
+ elsif checksum_store.empty?(s)
+ empty_checksums << s
+ end
+ end
validation = @locked_specs.validate_deps(s)
@@ -913,6 +922,7 @@ module Bundler
end
@locked_spec_with_missing_checksums = missing_checksums.first.name if missing_checksums.any?
+ @locked_spec_with_empty_checksums = empty_checksums.first.name if empty_checksums.any?
if missing_deps.any?
@locked_specs.delete(missing_deps)
@@ -1136,7 +1146,7 @@ module Bundler
def additional_base_requirements_to_force_updates(resolution_base)
return resolution_base if @explicit_unlocks.empty?
- full_update = dup_for_full_unlock.resolve
+ full_update = SpecSet.new(new_resolver_for_full_update.start)
@explicit_unlocks.each do |name|
version = full_update.version_for(name)
resolution_base.base_requirements[name] = Gem::Requirement.new("= #{version}") if version
@@ -1144,17 +1154,6 @@ module Bundler
resolution_base
end
- def dup_for_full_unlock
- unlocked_definition = self.class.new(@lockfile, @dependencies, @sources, true, @ruby_version, @optional_groups, @gemfiles)
- unlocked_definition.source_requirements = source_requirements
- unlocked_definition.gem_version_promoter.tap do |gvp|
- gvp.level = gem_version_promoter.level
- gvp.strict = gem_version_promoter.strict
- gvp.pre = gem_version_promoter.pre
- end
- unlocked_definition
- end
-
def remove_invalid_platforms!
return if Bundler.frozen_bundle?
@@ -1173,5 +1172,22 @@ module Bundler
def source_map
@source_map ||= SourceMap.new(sources, dependencies, @locked_specs)
end
+
+ def new_resolver_for_full_update
+ new_resolver(unlocked_resolution_base)
+ end
+
+ def unlocked_resolution_base
+ new_resolution_base(last_resolve: SpecSet.new([]), unlock: true)
+ end
+
+ def new_resolution_base(last_resolve:, unlock:)
+ new_resolution_platforms = @current_platform_missing ? @new_platforms + [Bundler.local_platform] : @new_platforms
+ Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms)
+ end
+
+ def new_resolver(base)
+ Resolver.new(base, gem_version_promoter, @most_specific_locked_platform)
+ end
end
end
diff --git a/lib/bundler/man/bundle-add.1 b/lib/bundler/man/bundle-add.1
index baa4a376c8..74422cbd31 100644
--- a/lib/bundler/man/bundle-add.1
+++ b/lib/bundler/man/bundle-add.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-ADD" "1" "July 2025" ""
+.TH "BUNDLE\-ADD" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-binstubs.1 b/lib/bundler/man/bundle-binstubs.1
index 0131dd663e..be9c6d0d09 100644
--- a/lib/bundler/man/bundle-binstubs.1
+++ b/lib/bundler/man/bundle-binstubs.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-BINSTUBS" "1" "July 2025" ""
+.TH "BUNDLE\-BINSTUBS" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-binstubs\fR \- Install the binstubs of the listed gems
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-cache.1 b/lib/bundler/man/bundle-cache.1
index 4c5dcff052..1d16b164fa 100644
--- a/lib/bundler/man/bundle-cache.1
+++ b/lib/bundler/man/bundle-cache.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-CACHE" "1" "July 2025" ""
+.TH "BUNDLE\-CACHE" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-check.1 b/lib/bundler/man/bundle-check.1
index 376becdbe4..4f0d51bb71 100644
--- a/lib/bundler/man/bundle-check.1
+++ b/lib/bundler/man/bundle-check.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-CHECK" "1" "July 2025" ""
+.TH "BUNDLE\-CHECK" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-clean.1 b/lib/bundler/man/bundle-clean.1
index 85e6186f49..df66523829 100644
--- a/lib/bundler/man/bundle-clean.1
+++ b/lib/bundler/man/bundle-clean.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-CLEAN" "1" "July 2025" ""
+.TH "BUNDLE\-CLEAN" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1
index 6f12696ab6..5157e51453 100644
--- a/lib/bundler/man/bundle-config.1
+++ b/lib/bundler/man/bundle-config.1
@@ -1,16 +1,16 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-CONFIG" "1" "July 2025" ""
+.TH "BUNDLE\-CONFIG" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-config\fR \- Set bundler configuration options
.SH "SYNOPSIS"
-\fBbundle config\fR list
+\fBbundle config\fR [list]
.br
-\fBbundle config\fR [get] NAME
+\fBbundle config\fR [get [\-\-local|\-\-global]] NAME
.br
-\fBbundle config\fR [set] NAME VALUE
+\fBbundle config\fR [set [\-\-local|\-\-global]] NAME VALUE
.br
-\fBbundle config\fR unset NAME
+\fBbundle config\fR unset [\-\-local|\-\-global] NAME
.SH "DESCRIPTION"
This command allows you to interact with Bundler's configuration system\.
.P
@@ -25,23 +25,40 @@ Global config (\fB~/\.bundle/config\fR)
Bundler default config
.IP "" 0
.P
+Executing \fBbundle\fR with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\.
+.SH "SUB\-COMMANDS"
+.SS "list (default command)"
Executing \fBbundle config list\fR will print a list of all bundler configuration for the current bundle, and where that configuration was set\.
+.SS "get"
+Executing \fBbundle config get <name>\fR will print the value of that configuration setting, and all locations where it was set\.
.P
-Executing \fBbundle config get <name>\fR will print the value of that configuration setting, and where it was set\.
-.P
-Executing \fBbundle config set <name> <value>\fR defaults to setting \fBlocal\fR configuration if executing from within a local application, otherwise it will set \fBglobal\fR configuration\. See \fB\-\-local\fR and \fB\-\-global\fR options below\.
+\fBOPTIONS\fR
+.TP
+\fB\-\-local\fR
+Get configuration from configuration file for the local application, namely, \fB<project_root>/\.bundle/config\fR, or \fB$BUNDLE_APP_CONFIG/config\fR if \fBBUNDLE_APP_CONFIG\fR is set\.
+.TP
+\fB\-\-global\fR
+Get configuration from configuration file global to all bundles executed as the current user, namely, from \fB~/\.bundle/config\fR\.
+.SS "set"
+Executing \fBbundle config set <name> <value>\fR defaults to setting \fBlocal\fR configuration if executing from within a local application, otherwise it will set \fBglobal\fR configuration\.
.P
+\fBOPTIONS\fR
+.TP
+\fB\-\-local\fR
Executing \fBbundle config set \-\-local <name> <value>\fR will set that configuration in the directory for the local application\. The configuration will be stored in \fB<project_root>/\.bundle/config\fR\. If \fBBUNDLE_APP_CONFIG\fR is set, the configuration will be stored in \fB$BUNDLE_APP_CONFIG/config\fR\.
-.P
+.TP
+\fB\-\-global\fR
Executing \fBbundle config set \-\-global <name> <value>\fR will set that configuration to the value specified for all bundles executed as the current user\. The configuration will be stored in \fB~/\.bundle/config\fR\. If \fIname\fR already is set, \fIname\fR will be overridden and user will be warned\.
-.P
+.SS "unset"
Executing \fBbundle config unset <name>\fR will delete the configuration in both local and global sources\.
.P
-Executing \fBbundle config unset \-\-global <name>\fR will delete the configuration only from the user configuration\.
-.P
+\fBOPTIONS\fR
+.TP
+\fB\-\-local\fR
Executing \fBbundle config unset \-\-local <name>\fR will delete the configuration only from the local application\.
-.P
-Executing bundle with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\.
+.TP
+\fB\-\-global\fR
+Executing \fBbundle config unset \-\-global <name>\fR will delete the configuration only from the user configuration\.
.SH "CONFIGURATION KEYS"
Configuration keys in bundler have two forms: the canonical form and the environment variable form\.
.P
diff --git a/lib/bundler/man/bundle-config.1.ronn b/lib/bundler/man/bundle-config.1.ronn
index 7f31eb4c39..2b2e39f03e 100644
--- a/lib/bundler/man/bundle-config.1.ronn
+++ b/lib/bundler/man/bundle-config.1.ronn
@@ -3,10 +3,10 @@ bundle-config(1) -- Set bundler configuration options
## SYNOPSIS
-`bundle config` list<br>
-`bundle config` [get] NAME<br>
-`bundle config` [set] NAME VALUE<br>
-`bundle config` unset NAME
+`bundle config` [list]<br>
+`bundle config` [get [--local|--global]] NAME<br>
+`bundle config` [set [--local|--global]] NAME VALUE<br>
+`bundle config` unset [--local|--global] NAME
## DESCRIPTION
@@ -19,38 +19,67 @@ Bundler loads configuration settings in this order:
3. Global config (`~/.bundle/config`)
4. Bundler default config
+Executing `bundle` with the `BUNDLE_IGNORE_CONFIG` environment variable set will
+cause it to ignore all configuration.
+
+## SUB-COMMANDS
+
+### list (default command)
+
Executing `bundle config list` will print a list of all bundler
configuration for the current bundle, and where that configuration
was set.
+### get
+
Executing `bundle config get <name>` will print the value of that configuration
-setting, and where it was set.
+setting, and all locations where it was set.
+
+**OPTIONS**
+
+* `--local`:
+ Get configuration from configuration file for the local application, namely,
+ `<project_root>/.bundle/config`, or `$BUNDLE_APP_CONFIG/config` if
+ `BUNDLE_APP_CONFIG` is set.
+
+* `--global`:
+ Get configuration from configuration file global to all bundles executed as
+ the current user, namely, from `~/.bundle/config`.
+
+### set
Executing `bundle config set <name> <value>` defaults to setting `local`
configuration if executing from within a local application, otherwise it will
-set `global` configuration. See `--local` and `--global` options below.
+set `global` configuration.
-Executing `bundle config set --local <name> <value>` will set that configuration
-in the directory for the local application. The configuration will be stored in
-`<project_root>/.bundle/config`. If `BUNDLE_APP_CONFIG` is set, the configuration
-will be stored in `$BUNDLE_APP_CONFIG/config`.
+**OPTIONS**
-Executing `bundle config set --global <name> <value>` will set that
-configuration to the value specified for all bundles executed as the current
-user. The configuration will be stored in `~/.bundle/config`. If <name> already
-is set, <name> will be overridden and user will be warned.
+* `--local`:
+ Executing `bundle config set --local <name> <value>` will set that configuration
+ in the directory for the local application. The configuration will be stored in
+ `<project_root>/.bundle/config`. If `BUNDLE_APP_CONFIG` is set, the configuration
+ will be stored in `$BUNDLE_APP_CONFIG/config`.
+
+* `--global`:
+ Executing `bundle config set --global <name> <value>` will set that
+ configuration to the value specified for all bundles executed as the current
+ user. The configuration will be stored in `~/.bundle/config`. If <name> already
+ is set, <name> will be overridden and user will be warned.
+
+### unset
Executing `bundle config unset <name>` will delete the configuration in both
local and global sources.
-Executing `bundle config unset --global <name>` will delete the configuration
-only from the user configuration.
+**OPTIONS**
-Executing `bundle config unset --local <name>` will delete the configuration
-only from the local application.
+* `--local`:
+ Executing `bundle config unset --local <name>` will delete the configuration
+ only from the local application.
-Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will
-cause it to ignore all configuration.
+* `--global`:
+ Executing `bundle config unset --global <name>` will delete the configuration
+ only from the user configuration.
## CONFIGURATION KEYS
diff --git a/lib/bundler/man/bundle-console.1 b/lib/bundler/man/bundle-console.1
index a263fef376..18c765372b 100644
--- a/lib/bundler/man/bundle-console.1
+++ b/lib/bundler/man/bundle-console.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-CONSOLE" "1" "July 2025" ""
+.TH "BUNDLE\-CONSOLE" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-console\fR \- Open an IRB session with the bundle pre\-loaded
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-doctor.1 b/lib/bundler/man/bundle-doctor.1
index 2b695dc2ee..6d4b0376a6 100644
--- a/lib/bundler/man/bundle-doctor.1
+++ b/lib/bundler/man/bundle-doctor.1
@@ -1,12 +1,12 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-DOCTOR" "1" "July 2025" ""
+.TH "BUNDLE\-DOCTOR" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-doctor\fR \- Checks the bundle for common problems
.SH "SYNOPSIS"
\fBbundle doctor [diagnose]\fR [\-\-quiet] [\-\-gemfile=GEMFILE] [\-\-ssl]
.br
-\fBbundle doctor ssl\fR [\-\-host=HOST] [\-\-tls\-version=VERSION] [\-\-verify\-mode=MODE]
+\fBbundle doctor ssl\fR [\-\-host=HOST] [\-\-tls\-version=TLS\-VERSION] [\-\-verify\-mode=VERIFY\-MODE]
.br
\fBbundle doctor\fR help [COMMAND]
.SH "DESCRIPTION"
@@ -57,12 +57,12 @@ Open a TLS connection and verify the outcome\.
\fB\-\-host=HOST\fR
Perform the diagnostic on HOST\. Defaults to \fBrubygems\.org\fR\.
.TP
-\fB\-\-tls\-version=VERSION\fR
+\fB\-\-tls\-version=TLS\-VERSION\fR
Specify the TLS version when opening the connection to HOST\.
.IP
Accepted values are: \fB1\.1\fR or \fB1\.2\fR\.
.TP
-\fB\-\-verify\-mode=MODE\fR
+\fB\-\-verify\-mode=VERIFY\-MODE\fR
Specify the TLS verify mode when opening the connection to HOST\. Defaults to \fBSSL_VERIFY_PEER\fR\.
.IP
Accepted values are: \fBCLIENT_ONCE\fR, \fBFAIL_IF_NO_PEER_CERT\fR, \fBNONE\fR, \fBPEER\fR\.
diff --git a/lib/bundler/man/bundle-doctor.1.ronn b/lib/bundler/man/bundle-doctor.1.ronn
index 7e8a21b1c5..7495099ff5 100644
--- a/lib/bundler/man/bundle-doctor.1.ronn
+++ b/lib/bundler/man/bundle-doctor.1.ronn
@@ -7,8 +7,8 @@ bundle-doctor(1) -- Checks the bundle for common problems
[--gemfile=GEMFILE]
[--ssl]<br>
`bundle doctor ssl` [--host=HOST]
- [--tls-version=VERSION]
- [--verify-mode=MODE]<br>
+ [--tls-version=TLS-VERSION]
+ [--verify-mode=VERIFY-MODE]<br>
`bundle doctor` help [COMMAND]
## DESCRIPTION
@@ -65,12 +65,12 @@ The diagnostic will perform a few checks such as:
* `--host=HOST`:
Perform the diagnostic on HOST. Defaults to `rubygems.org`.
-* `--tls-version=VERSION`:
+* `--tls-version=TLS-VERSION`:
Specify the TLS version when opening the connection to HOST.
Accepted values are: `1.1` or `1.2`.
-* `--verify-mode=MODE`:
+* `--verify-mode=VERIFY-MODE`:
Specify the TLS verify mode when opening the connection to HOST.
Defaults to `SSL_VERIFY_PEER`.
diff --git a/lib/bundler/man/bundle-env.1 b/lib/bundler/man/bundle-env.1
index 3e6c9f6e17..28ccc17f03 100644
--- a/lib/bundler/man/bundle-env.1
+++ b/lib/bundler/man/bundle-env.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-ENV" "1" "July 2025" ""
+.TH "BUNDLE\-ENV" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-env\fR \- Print information about the environment Bundler is running under
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-exec.1 b/lib/bundler/man/bundle-exec.1
index 79cdad0288..cd53916cff 100644
--- a/lib/bundler/man/bundle-exec.1
+++ b/lib/bundler/man/bundle-exec.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-EXEC" "1" "July 2025" ""
+.TH "BUNDLE\-EXEC" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-exec\fR \- Execute a command in the context of the bundle
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-fund.1 b/lib/bundler/man/bundle-fund.1
index 3f6e3a46df..a91c180951 100644
--- a/lib/bundler/man/bundle-fund.1
+++ b/lib/bundler/man/bundle-fund.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-FUND" "1" "July 2025" ""
+.TH "BUNDLE\-FUND" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-fund\fR \- Lists information about gems seeking funding assistance
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-gem.1 b/lib/bundler/man/bundle-gem.1
index 44a02c033c..5fe2777230 100644
--- a/lib/bundler/man/bundle-gem.1
+++ b/lib/bundler/man/bundle-gem.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-GEM" "1" "July 2025" ""
+.TH "BUNDLE\-GEM" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-help.1 b/lib/bundler/man/bundle-help.1
index e6bbea6dad..9ea28bef14 100644
--- a/lib/bundler/man/bundle-help.1
+++ b/lib/bundler/man/bundle-help.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-HELP" "1" "July 2025" ""
+.TH "BUNDLE\-HELP" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-help\fR \- Displays detailed help for each subcommand
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-info.1 b/lib/bundler/man/bundle-info.1
index 435518e120..29d649d342 100644
--- a/lib/bundler/man/bundle-info.1
+++ b/lib/bundler/man/bundle-info.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-INFO" "1" "July 2025" ""
+.TH "BUNDLE\-INFO" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-info\fR \- Show information for the given gem in your bundle
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-init.1 b/lib/bundler/man/bundle-init.1
index 48b3232b8c..be9399c20f 100644
--- a/lib/bundler/man/bundle-init.1
+++ b/lib/bundler/man/bundle-init.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-INIT" "1" "July 2025" ""
+.TH "BUNDLE\-INIT" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-init\fR \- Generates a Gemfile into the current working directory
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-inject.1 b/lib/bundler/man/bundle-inject.1
index abc63c392e..7e30e26a4e 100644
--- a/lib/bundler/man/bundle-inject.1
+++ b/lib/bundler/man/bundle-inject.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-INJECT" "1" "July 2025" ""
+.TH "BUNDLE\-INJECT" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-install.1 b/lib/bundler/man/bundle-install.1
index bf06747558..f9bbade2fd 100644
--- a/lib/bundler/man/bundle-install.1
+++ b/lib/bundler/man/bundle-install.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-INSTALL" "1" "July 2025" ""
+.TH "BUNDLE\-INSTALL" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-install\fR \- Install the dependencies specified in your Gemfile
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-issue.1 b/lib/bundler/man/bundle-issue.1
index 668da5712f..3c7e5305f3 100644
--- a/lib/bundler/man/bundle-issue.1
+++ b/lib/bundler/man/bundle-issue.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-ISSUE" "1" "July 2025" ""
+.TH "BUNDLE\-ISSUE" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-issue\fR \- Get help reporting Bundler issues
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-licenses.1 b/lib/bundler/man/bundle-licenses.1
index cccb860854..eb0ad5ae40 100644
--- a/lib/bundler/man/bundle-licenses.1
+++ b/lib/bundler/man/bundle-licenses.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-LICENSES" "1" "July 2025" ""
+.TH "BUNDLE\-LICENSES" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-licenses\fR \- Print the license of all gems in the bundle
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-list.1 b/lib/bundler/man/bundle-list.1
index 26c2833218..a345787a5e 100644
--- a/lib/bundler/man/bundle-list.1
+++ b/lib/bundler/man/bundle-list.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-LIST" "1" "July 2025" ""
+.TH "BUNDLE\-LIST" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-list\fR \- List all the gems in the bundle
.SH "SYNOPSIS"
@@ -19,6 +19,8 @@ bundle list \-\-without\-group test
bundle list \-\-only\-group dev
.P
bundle list \-\-only\-group dev test \-\-paths
+.P
+bundle list \-\-format json
.SH "OPTIONS"
.TP
\fB\-\-name\-only\fR
@@ -32,4 +34,7 @@ A space\-separated list of groups of gems to skip during printing\.
.TP
\fB\-\-only\-group=<list>\fR
A space\-separated list of groups of gems to print\.
+.TP
+\fB\-\-format=FORMAT\fR
+Format output ('json' is the only supported format)
diff --git a/lib/bundler/man/bundle-list.1.ronn b/lib/bundler/man/bundle-list.1.ronn
index 81bee0ac33..9ec2b13282 100644
--- a/lib/bundler/man/bundle-list.1.ronn
+++ b/lib/bundler/man/bundle-list.1.ronn
@@ -21,6 +21,8 @@ bundle list --only-group dev
bundle list --only-group dev test --paths
+bundle list --format json
+
## OPTIONS
* `--name-only`:
@@ -34,3 +36,6 @@ bundle list --only-group dev test --paths
* `--only-group=<list>`:
A space-separated list of groups of gems to print.
+
+* `--format=FORMAT`:
+ Format output ('json' is the only supported format)
diff --git a/lib/bundler/man/bundle-lock.1 b/lib/bundler/man/bundle-lock.1
index 5faa46da18..79aa1e2452 100644
--- a/lib/bundler/man/bundle-lock.1
+++ b/lib/bundler/man/bundle-lock.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-LOCK" "1" "July 2025" ""
+.TH "BUNDLE\-LOCK" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-lock\fR \- Creates / Updates a lockfile without installing
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-open.1 b/lib/bundler/man/bundle-open.1
index e8a24f3541..b1c2022f40 100644
--- a/lib/bundler/man/bundle-open.1
+++ b/lib/bundler/man/bundle-open.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-OPEN" "1" "July 2025" ""
+.TH "BUNDLE\-OPEN" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-open\fR \- Opens the source directory for a gem in your bundle
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-outdated.1 b/lib/bundler/man/bundle-outdated.1
index 3259b0f023..d4790f8876 100644
--- a/lib/bundler/man/bundle-outdated.1
+++ b/lib/bundler/man/bundle-outdated.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-OUTDATED" "1" "July 2025" ""
+.TH "BUNDLE\-OUTDATED" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-outdated\fR \- List installed gems with newer versions available
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-platform.1 b/lib/bundler/man/bundle-platform.1
index 1032acc4e6..78de506b57 100644
--- a/lib/bundler/man/bundle-platform.1
+++ b/lib/bundler/man/bundle-platform.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-PLATFORM" "1" "July 2025" ""
+.TH "BUNDLE\-PLATFORM" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-platform\fR \- Displays platform compatibility information
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-plugin.1 b/lib/bundler/man/bundle-plugin.1
index 5803b7a554..5fcc88b50d 100644
--- a/lib/bundler/man/bundle-plugin.1
+++ b/lib/bundler/man/bundle-plugin.1
@@ -1,10 +1,10 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-PLUGIN" "1" "July 2025" ""
+.TH "BUNDLE\-PLUGIN" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-plugin\fR \- Manage Bundler plugins
.SH "SYNOPSIS"
-\fBbundle plugin\fR install PLUGINS [\-\-source=\fISOURCE\fR] [\-\-version=\fIversion\fR] [\-\-git=\fIgit\-url\fR] [\-\-branch=\fIbranch\fR|\-\-ref=\fIrev\fR] [\-\-path=\fIpath\fR]
+\fBbundle plugin\fR install PLUGINS [\-\-source=SOURCE] [\-\-version=VERSION] [\-\-git=GIT] [\-\-branch=BRANCH|\-\-ref=REF] [\-\-local\-git=LOCAL_GIT] [\-\-path=PATH]
.br
\fBbundle plugin\fR uninstall PLUGINS [\-\-all]
.br
@@ -16,18 +16,23 @@ You can install, uninstall, and list plugin(s) with this command to extend funct
.SH "SUB\-COMMANDS"
.SS "install"
Install the given plugin(s)\.
+.P
+For example, \fBbundle plugin install bundler\-graph\fR will install bundler\-graph gem from globally configured sources (defaults to RubyGems\.org)\. Note that the global source specified in Gemfile is ignored\.
+.P
+\fBOPTIONS\fR
.TP
-\fBbundle plugin install bundler\-graph\fR
-Install bundler\-graph gem from globally configured sources (defaults to RubyGems\.org)\. The global source, specified in source in Gemfile is ignored\.
-.TP
-\fBbundle plugin install bundler\-graph \-\-source https://example\.com\fR
-Install bundler\-graph gem from example\.com\. The global source, specified in source in Gemfile is not considered\.
+\fB\-\-source=SOURCE\fR
+Install the plugin gem from a specific source, rather than from globally configured sources\.
+.IP
+Example: \fBbundle plugin install bundler\-graph \-\-source https://example\.com\fR
.TP
-\fBbundle plugin install bundler\-graph \-\-version 0\.2\.1\fR
-You can specify the version of the gem via \fB\-\-version\fR\.
+\fB\-\-version=VERSION\fR
+Specify a version of the plugin gem to install via \fB\-\-version\fR\.
+.IP
+Example: \fBbundle plugin install bundler\-graph \-\-version 0\.2\.1\fR
.TP
-\fBbundle plugin install bundler\-graph \-\-git https://github\.com/rubygems/bundler\-graph\fR
-Install bundler\-graph gem from Git repository\. You can use standard Git URLs like:
+\fB\-\-git=GIT\fR
+Install the plugin gem from a Git repository\. You can use standard Git URLs like:
.IP
\fBssh://[user@]host\.xz[:port]/path/to/repo\.git\fR
.br
@@ -37,12 +42,24 @@ Install bundler\-graph gem from Git repository\. You can use standard Git URLs l
.br
\fBfile:///path/to/repo\fR
.IP
-When you specify \fB\-\-git\fR, you can use \fB\-\-branch\fR or \fB\-\-ref\fR to specify any branch, tag, or commit hash (revision) to use\.
+Example: \fBbundle plugin install bundler\-graph \-\-git https://github\.com/rubygems/bundler\-graph\fR
.TP
-\fBbundle plugin install bundler\-graph \-\-path \.\./bundler\-graph\fR
-Install bundler\-graph gem from a local path\.
+\fB\-\-branch=BRANCH\fR
+When you specify \fB\-\-git\fR, you can use \fB\-\-branch\fR to use\.
.TP
-\fBbundle plugin install bundler\-graph \-\-local\-git \.\./bundler\-graph\fR
+\fB\-\-ref=REF\fR
+When you specify \fB\-\-git\fR, you can use \fB\-\-ref\fR to specify any tag, or commit hash (revision) to use\.
+.TP
+\fB\-\-path=PATH\fR
+Install the plugin gem from a local path\.
+.IP
+Example: \fBbundle plugin install bundler\-graph \-\-path \.\./bundler\-graph\fR
+.TP
+\fB\-\-local\-git=LOCAL_GIT\fR
+Install the plugin gem from a local Git repository\.
+.IP
+Example: \fBbundle plugin install bundler\-graph \-\-local\-git \.\./bundler\-graph\fR\.
+.IP
This option is deprecated in favor of \fB\-\-git\fR\.
.SS "uninstall"
Uninstall the plugin(s) specified in PLUGINS\.
diff --git a/lib/bundler/man/bundle-plugin.1.ronn b/lib/bundler/man/bundle-plugin.1.ronn
index 74879aa681..efb4240761 100644
--- a/lib/bundler/man/bundle-plugin.1.ronn
+++ b/lib/bundler/man/bundle-plugin.1.ronn
@@ -3,9 +3,10 @@ bundle-plugin(1) -- Manage Bundler plugins
## SYNOPSIS
-`bundle plugin` install PLUGINS [--source=<SOURCE>] [--version=<version>]
- [--git=<git-url>] [--branch=<branch>|--ref=<rev>]
- [--path=<path>]<br>
+`bundle plugin` install PLUGINS [--source=SOURCE] [--version=VERSION]
+ [--git=GIT] [--branch=BRANCH|--ref=REF]
+ [--local-git=LOCAL_GIT]
+ [--path=PATH]<br>
`bundle plugin` uninstall PLUGINS [--all]<br>
`bundle plugin` list<br>
`bundle plugin` help [COMMAND]
@@ -20,29 +21,49 @@ You can install, uninstall, and list plugin(s) with this command to extend funct
Install the given plugin(s).
-* `bundle plugin install bundler-graph`:
- Install bundler-graph gem from globally configured sources (defaults to RubyGems.org). The global source, specified in source in Gemfile is ignored.
+For example, `bundle plugin install bundler-graph` will install bundler-graph
+gem from globally configured sources (defaults to RubyGems.org). Note that the
+global source specified in Gemfile is ignored.
-* `bundle plugin install bundler-graph --source https://example.com`:
- Install bundler-graph gem from example.com. The global source, specified in source in Gemfile is not considered.
+**OPTIONS**
+
+* `--source=SOURCE`:
+ Install the plugin gem from a specific source, rather than from globally configured sources.
+
+ Example: `bundle plugin install bundler-graph --source https://example.com`
-* `bundle plugin install bundler-graph --version 0.2.1`:
- You can specify the version of the gem via `--version`.
+* `--version=VERSION`:
+ Specify a version of the plugin gem to install via `--version`.
-* `bundle plugin install bundler-graph --git https://github.com/rubygems/bundler-graph`:
- Install bundler-graph gem from Git repository. You can use standard Git URLs like:
+ Example: `bundle plugin install bundler-graph --version 0.2.1`
+
+* `--git=GIT`:
+ Install the plugin gem from a Git repository. You can use standard Git URLs like:
`ssh://[user@]host.xz[:port]/path/to/repo.git`<br>
`http[s]://host.xz[:port]/path/to/repo.git`<br>
`/path/to/repo`<br>
`file:///path/to/repo`
- When you specify `--git`, you can use `--branch` or `--ref` to specify any branch, tag, or commit hash (revision) to use.
+ Example: `bundle plugin install bundler-graph --git https://github.com/rubygems/bundler-graph`
+
+* `--branch=BRANCH`:
+ When you specify `--git`, you can use `--branch` to use.
+
+* `--ref=REF`:
+ When you specify `--git`, you can use `--ref` to specify any tag, or commit
+ hash (revision) to use.
+
+* `--path=PATH`:
+ Install the plugin gem from a local path.
+
+ Example: `bundle plugin install bundler-graph --path ../bundler-graph`
+
+* `--local-git=LOCAL_GIT`:
+ Install the plugin gem from a local Git repository.
-* `bundle plugin install bundler-graph --path ../bundler-graph`:
- Install bundler-graph gem from a local path.
+ Example: `bundle plugin install bundler-graph --local-git ../bundler-graph`.
-* `bundle plugin install bundler-graph --local-git ../bundler-graph`:
This option is deprecated in favor of `--git`.
### uninstall
diff --git a/lib/bundler/man/bundle-pristine.1 b/lib/bundler/man/bundle-pristine.1
index 5c7871069c..e39f264cef 100644
--- a/lib/bundler/man/bundle-pristine.1
+++ b/lib/bundler/man/bundle-pristine.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-PRISTINE" "1" "July 2025" ""
+.TH "BUNDLE\-PRISTINE" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-pristine\fR \- Restores installed gems to their pristine condition
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-remove.1 b/lib/bundler/man/bundle-remove.1
index df8ce3232a..6750817680 100644
--- a/lib/bundler/man/bundle-remove.1
+++ b/lib/bundler/man/bundle-remove.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-REMOVE" "1" "July 2025" ""
+.TH "BUNDLE\-REMOVE" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-remove\fR \- Removes gems from the Gemfile
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-show.1 b/lib/bundler/man/bundle-show.1
index ca10c00701..67b387559d 100644
--- a/lib/bundler/man/bundle-show.1
+++ b/lib/bundler/man/bundle-show.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-SHOW" "1" "July 2025" ""
+.TH "BUNDLE\-SHOW" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-update.1 b/lib/bundler/man/bundle-update.1
index 8655aa5cd3..fbcabb69a8 100644
--- a/lib/bundler/man/bundle-update.1
+++ b/lib/bundler/man/bundle-update.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-UPDATE" "1" "July 2025" ""
+.TH "BUNDLE\-UPDATE" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-update\fR \- Update your gems to the latest available versions
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-version.1 b/lib/bundler/man/bundle-version.1
index e591f59766..261140ff38 100644
--- a/lib/bundler/man/bundle-version.1
+++ b/lib/bundler/man/bundle-version.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-VERSION" "1" "July 2025" ""
+.TH "BUNDLE\-VERSION" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-version\fR \- Prints Bundler version information
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-viz.1 b/lib/bundler/man/bundle-viz.1
index b5dd1db7b7..f2570103dc 100644
--- a/lib/bundler/man/bundle-viz.1
+++ b/lib/bundler/man/bundle-viz.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE\-VIZ" "1" "July 2025" ""
+.TH "BUNDLE\-VIZ" "1" "August 2025" ""
.SH "NAME"
\fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle.1 b/lib/bundler/man/bundle.1
index 269e28141d..f87a98150d 100644
--- a/lib/bundler/man/bundle.1
+++ b/lib/bundler/man/bundle.1
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "BUNDLE" "1" "July 2025" ""
+.TH "BUNDLE" "1" "August 2025" ""
.SH "NAME"
\fBbundle\fR \- Ruby Dependency Management
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/gemfile.5 b/lib/bundler/man/gemfile.5
index c926e1ff2d..cd04d3d198 100644
--- a/lib/bundler/man/gemfile.5
+++ b/lib/bundler/man/gemfile.5
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.10.1
.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
-.TH "GEMFILE" "5" "July 2025" ""
+.TH "GEMFILE" "5" "August 2025" ""
.SH "NAME"
\fBGemfile\fR \- A format for describing gem dependencies for Ruby programs
.SH "SYNOPSIS"
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index fba9badec7..1dbf565d46 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -165,7 +165,7 @@ module Bundler
PubGrub::VersionConstraint.new(package, range: range)
end
- def versions_for(package, range=VersionRange.any)
+ def versions_for(package, range = VersionRange.any)
range.select_versions(@sorted_versions[package])
end
diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb
index 8cf3b56b83..fedf44b0e6 100644
--- a/lib/bundler/rubygems_ext.rb
+++ b/lib/bundler/rubygems_ext.rb
@@ -417,7 +417,7 @@ module Gem
unless Gem::NameTuple.new("a", Gem::Version.new("1"), Gem::Platform.new("x86_64-linux")).platform.is_a?(String)
alias_method :initialize_with_platform, :initialize
- def initialize(name, version, platform=Gem::Platform::RUBY)
+ def initialize(name, version, platform = Gem::Platform::RUBY)
if Gem::Platform === platform
initialize_with_platform(name, version, platform.to_s)
else
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index d4e88579e8..f8f1451ee6 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -224,7 +224,7 @@ module Gem
finish_resolve rs
end
- def self.finish_resolve(request_set=Gem::RequestSet.new)
+ def self.finish_resolve(request_set = Gem::RequestSet.new)
request_set.import Gem::Specification.unresolved_deps.values
request_set.import Gem.loaded_specs.values.map {|s| Gem::Dependency.new(s.name, s.version) }
@@ -341,7 +341,7 @@ module Gem
##
# The path where gem executables are to be installed.
- def self.bindir(install_dir=Gem.dir)
+ def self.bindir(install_dir = Gem.dir)
return File.join install_dir, "bin" unless
install_dir.to_s == Gem.default_dir.to_s
Gem.default_bindir
@@ -350,7 +350,7 @@ module Gem
##
# The path were rubygems plugins are to be installed.
- def self.plugindir(install_dir=Gem.dir)
+ def self.plugindir(install_dir = Gem.dir)
File.join install_dir, "plugins"
end
@@ -534,7 +534,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Note that find_files will return all files even if they are from different
# versions of the same gem. See also find_latest_files
- def self.find_files(glob, check_load_path=true)
+ def self.find_files(glob, check_load_path = true)
files = []
files = find_files_from_load_path glob if check_load_path
@@ -571,7 +571,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Unlike find_files, find_latest_files will return only files from the
# latest version of a gem.
- def self.find_latest_files(glob, check_load_path=true)
+ def self.find_latest_files(glob, check_load_path = true)
files = []
files = find_files_from_load_path glob if check_load_path
diff --git a/lib/rubygems/command.rb b/lib/rubygems/command.rb
index 3a149ea38e..d38363f293 100644
--- a/lib/rubygems/command.rb
+++ b/lib/rubygems/command.rb
@@ -117,7 +117,7 @@ class Gem::Command
# Unhandled arguments (gem names, files, etc.) are left in
# <tt>options[:args]</tt>.
- def initialize(command, summary=nil, defaults={})
+ def initialize(command, summary = nil, defaults = {})
@command = command
@summary = summary
@program_name = "gem #{command}"
diff --git a/lib/rubygems/command_manager.rb b/lib/rubygems/command_manager.rb
index 15834ce4dd..8521517a24 100644
--- a/lib/rubygems/command_manager.rb
+++ b/lib/rubygems/command_manager.rb
@@ -118,7 +118,7 @@ class Gem::CommandManager
##
# Register the Symbol +command+ as a gem command.
- def register_command(command, obj=false)
+ def register_command(command, obj = false)
@commands[command] = obj
end
@@ -148,7 +148,7 @@ class Gem::CommandManager
##
# Run the command specified by +args+.
- def run(args, build_args=nil)
+ def run(args, build_args = nil)
process_args(args, build_args)
rescue StandardError, Gem::Timeout::Error => ex
if ex.respond_to?(:detailed_message)
@@ -165,7 +165,7 @@ class Gem::CommandManager
terminate_interaction(1)
end
- def process_args(args, build_args=nil)
+ def process_args(args, build_args = nil)
if args.empty?
say Gem::Command::HELP
terminate_interaction 1
diff --git a/lib/rubygems/dependency.rb b/lib/rubygems/dependency.rb
index d1ec9222af..1e91f493a6 100644
--- a/lib/rubygems/dependency.rb
+++ b/lib/rubygems/dependency.rb
@@ -217,7 +217,7 @@ class Gem::Dependency
# NOTE: Unlike #matches_spec? this method does not return true when the
# version is a prerelease version unless this is a prerelease dependency.
- def match?(obj, version=nil, allow_prerelease=false)
+ def match?(obj, version = nil, allow_prerelease = false)
if !version
name = obj.name
version = obj.version
diff --git a/lib/rubygems/dependency_installer.rb b/lib/rubygems/dependency_installer.rb
index b119dca1cf..b4152e83e9 100644
--- a/lib/rubygems/dependency_installer.rb
+++ b/lib/rubygems/dependency_installer.rb
@@ -127,7 +127,7 @@ class Gem::DependencyInstaller
# sources. Gems are sorted with newer gems preferred over older gems, and
# local gems preferred over remote gems.
- def find_gems_with_sources(dep, best_only=false) # :nodoc:
+ def find_gems_with_sources(dep, best_only = false) # :nodoc:
set = Gem::AvailableSet.new
if consider_local?
diff --git a/lib/rubygems/dependency_list.rb b/lib/rubygems/dependency_list.rb
index ad5e59e8c1..99643a426d 100644
--- a/lib/rubygems/dependency_list.rb
+++ b/lib/rubygems/dependency_list.rb
@@ -140,7 +140,7 @@ class Gem::DependencyList
# If removing the gemspec creates breaks a currently ok dependency, then it
# is NOT ok to remove the gemspec.
- def ok_to_remove?(full_name, check_dev=true)
+ def ok_to_remove?(full_name, check_dev = true)
gem_to_remove = find_name full_name
# If the state is inconsistent, at least don't crash
diff --git a/lib/rubygems/deprecate.rb b/lib/rubygems/deprecate.rb
index a20649cbda..303b344d42 100644
--- a/lib/rubygems/deprecate.rb
+++ b/lib/rubygems/deprecate.rb
@@ -126,7 +126,7 @@ module Gem
# telling the user of +repl+ (unless +repl+ is :none) and the
# Rubygems version that it is planned to go away.
- def rubygems_deprecate(name, replacement=:none, version=nil)
+ def rubygems_deprecate(name, replacement = :none, version = nil)
class_eval do
old = "_deprecated_#{name}"
alias_method old, name
diff --git a/lib/rubygems/errors.rb b/lib/rubygems/errors.rb
index 57fb3eb120..4bbc5217e0 100644
--- a/lib/rubygems/errors.rb
+++ b/lib/rubygems/errors.rb
@@ -26,7 +26,7 @@ module Gem
# system. Instead of rescuing from this class, make sure to rescue from the
# superclass Gem::LoadError to catch all types of load errors.
class MissingSpecError < Gem::LoadError
- def initialize(name, requirement, extra_message=nil)
+ def initialize(name, requirement, extra_message = nil)
@name = name
@requirement = requirement
@extra_message = extra_message
diff --git a/lib/rubygems/exceptions.rb b/lib/rubygems/exceptions.rb
index 793324b875..adf7ad6d7d 100644
--- a/lib/rubygems/exceptions.rb
+++ b/lib/rubygems/exceptions.rb
@@ -110,7 +110,7 @@ class Gem::SpecificGemNotFoundException < Gem::GemNotFoundException
# and +version+. Any +errors+ encountered when attempting to find the gem
# are also stored.
- def initialize(name, version, errors=nil)
+ def initialize(name, version, errors = nil)
super "Could not find a valid gem '#{name}' (#{version}) locally or in a repository"
@name = name
@@ -261,7 +261,7 @@ class Gem::UnsatisfiableDependencyError < Gem::DependencyError
# Creates a new UnsatisfiableDependencyError for the unsatisfiable
# Gem::Resolver::DependencyRequest +dep+
- def initialize(dep, platform_mismatch=nil)
+ def initialize(dep, platform_mismatch = nil)
if platform_mismatch && !platform_mismatch.empty?
plats = platform_mismatch.map {|x| x.platform.to_s }.sort.uniq
super "Unable to resolve dependency: No match for '#{dep}' on this platform. Found: #{plats.join(", ")}"
diff --git a/lib/rubygems/ext/builder.rb b/lib/rubygems/ext/builder.rb
index 05cd735bd9..b47996d092 100644
--- a/lib/rubygems/ext/builder.rb
+++ b/lib/rubygems/ext/builder.rb
@@ -11,6 +11,9 @@ require_relative "../user_interaction"
class Gem::Ext::Builder
include Gem::UserInteraction
+ class NoMakefileError < Gem::InstallError
+ end
+
attr_accessor :build_args # :nodoc:
def self.class_name
@@ -21,7 +24,8 @@ class Gem::Ext::Builder
def self.make(dest_path, results, make_dir = Dir.pwd, sitedir = nil, targets = ["clean", "", "install"],
target_rbconfig: Gem.target_rbconfig)
unless File.exist? File.join(make_dir, "Makefile")
- raise Gem::InstallError, "Makefile not found"
+ # No makefile exists, nothing to do.
+ raise NoMakefileError, "No Makefile found in #{make_dir}"
end
# try to find make program from Ruby configure arguments first
diff --git a/lib/rubygems/ext/cargo_builder.rb b/lib/rubygems/ext/cargo_builder.rb
index 21b50f394d..e58d0bb75c 100644
--- a/lib/rubygems/ext/cargo_builder.rb
+++ b/lib/rubygems/ext/cargo_builder.rb
@@ -15,7 +15,7 @@ class Gem::Ext::CargoBuilder < Gem::Ext::Builder
end
def build(extension, dest_path, results, args = [], lib_dir = nil, cargo_dir = Dir.pwd,
- target_rbconfig=Gem.target_rbconfig)
+ target_rbconfig = Gem.target_rbconfig)
require "tempfile"
require "fileutils"
diff --git a/lib/rubygems/ext/cmake_builder.rb b/lib/rubygems/ext/cmake_builder.rb
index 34564f668d..c7bfbb8a57 100644
--- a/lib/rubygems/ext/cmake_builder.rb
+++ b/lib/rubygems/ext/cmake_builder.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
class Gem::Ext::CmakeBuilder < Gem::Ext::Builder
- def self.build(extension, dest_path, results, args=[], lib_dir=nil, cmake_dir=Dir.pwd,
- target_rbconfig=Gem.target_rbconfig)
+ def self.build(extension, dest_path, results, args = [], lib_dir = nil, cmake_dir = Dir.pwd,
+ target_rbconfig = Gem.target_rbconfig)
if target_rbconfig.path
warn "--target-rbconfig is not yet supported for CMake extensions. Ignoring"
end
diff --git a/lib/rubygems/ext/configure_builder.rb b/lib/rubygems/ext/configure_builder.rb
index d91b1ec5e8..76c1cd8b19 100644
--- a/lib/rubygems/ext/configure_builder.rb
+++ b/lib/rubygems/ext/configure_builder.rb
@@ -7,8 +7,8 @@
#++
class Gem::Ext::ConfigureBuilder < Gem::Ext::Builder
- def self.build(extension, dest_path, results, args=[], lib_dir=nil, configure_dir=Dir.pwd,
- target_rbconfig=Gem.target_rbconfig)
+ def self.build(extension, dest_path, results, args = [], lib_dir = nil, configure_dir = Dir.pwd,
+ target_rbconfig = Gem.target_rbconfig)
if target_rbconfig.path
warn "--target-rbconfig is not yet supported for configure-based extensions. Ignoring"
end
diff --git a/lib/rubygems/ext/ext_conf_builder.rb b/lib/rubygems/ext/ext_conf_builder.rb
index e652a221f8..ec2fa59412 100644
--- a/lib/rubygems/ext/ext_conf_builder.rb
+++ b/lib/rubygems/ext/ext_conf_builder.rb
@@ -7,8 +7,8 @@
#++
class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
- def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=Dir.pwd,
- target_rbconfig=Gem.target_rbconfig)
+ def self.build(extension, dest_path, results, args = [], lib_dir = nil, extension_dir = Dir.pwd,
+ target_rbconfig = Gem.target_rbconfig)
require "fileutils"
require "tempfile"
@@ -66,6 +66,10 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
end
results
+ rescue Gem::Ext::Builder::NoMakefileError => error
+ results << error.message
+ results << "Skipping make for #{extension} as no Makefile was found."
+ # We are good, do not re-raise the error.
ensure
FileUtils.rm_rf tmp_dest if tmp_dest
end
diff --git a/lib/rubygems/ext/rake_builder.rb b/lib/rubygems/ext/rake_builder.rb
index 8edd8d1373..0eac5a180c 100644
--- a/lib/rubygems/ext/rake_builder.rb
+++ b/lib/rubygems/ext/rake_builder.rb
@@ -7,8 +7,8 @@
#++
class Gem::Ext::RakeBuilder < Gem::Ext::Builder
- def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=Dir.pwd,
- target_rbconfig=Gem.target_rbconfig)
+ def self.build(extension, dest_path, results, args = [], lib_dir = nil, extension_dir = Dir.pwd,
+ target_rbconfig = Gem.target_rbconfig)
if target_rbconfig.path
warn "--target-rbconfig is not yet supported for Rake extensions. Ignoring"
end
diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb
index 2b3200223a..0cfe59b5bb 100644
--- a/lib/rubygems/installer.rb
+++ b/lib/rubygems/installer.rb
@@ -67,23 +67,6 @@ class Gem::Installer
attr_reader :package
class << self
- #
- # Changes in rubygems to lazily loading `rubygems/command` (in order to
- # lazily load `optparse` as a side effect) affect bundler's custom installer
- # which uses `Gem::Command` without requiring it (up until bundler 2.2.29).
- # This hook is to compensate for that missing require.
- #
- # TODO: Remove when rubygems no longer supports running on bundler older
- # than 2.2.29.
-
- def inherited(klass)
- if klass.name == "Bundler::RubyGemsGemInstaller"
- require "rubygems/command"
- end
-
- super(klass)
- end
-
##
# Overrides the executable format.
#
@@ -170,7 +153,7 @@ class Gem::Installer
# process. If not set, then Gem::Command.build_args is used
# :post_install_message:: Print gem post install message if true
- def initialize(package, options={})
+ def initialize(package, options = {})
require "fileutils"
@options = options
diff --git a/lib/rubygems/name_tuple.rb b/lib/rubygems/name_tuple.rb
index 3f4a6fcf3d..67c6f30a3d 100644
--- a/lib/rubygems/name_tuple.rb
+++ b/lib/rubygems/name_tuple.rb
@@ -6,7 +6,7 @@
# wrap the data returned from the indexes.
class Gem::NameTuple
- def initialize(name, version, platform=Gem::Platform::RUBY)
+ def initialize(name, version, platform = Gem::Platform::RUBY)
@name = name
@version = version
diff --git a/lib/rubygems/package/tar_writer.rb b/lib/rubygems/package/tar_writer.rb
index 7dcb9737c0..39fed9e2af 100644
--- a/lib/rubygems/package/tar_writer.rb
+++ b/lib/rubygems/package/tar_writer.rb
@@ -99,7 +99,7 @@ class Gem::Package::TarWriter
# Gem.source_date_epoch if not specified), and yields an IO for
# writing the file to
- def add_file(name, mode, mtime=nil) # :yields: io
+ def add_file(name, mode, mtime = nil) # :yields: io
check_closed
name, prefix = split_name name
diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb
index 355a668b39..6ed0842963 100644
--- a/lib/rubygems/remote_fetcher.rb
+++ b/lib/rubygems/remote_fetcher.rb
@@ -72,7 +72,7 @@ class Gem::RemoteFetcher
# +headers+: A set of additional HTTP headers to be sent to the server when
# fetching the gem.
- def initialize(proxy=nil, dns=nil, headers={})
+ def initialize(proxy = nil, dns = nil, headers = {})
require_relative "core_ext/tcpsocket_init" if Gem.configuration.ipv4_fallback_enabled
require_relative "vendored_net_http"
require_relative "vendor/uri/lib/uri"
diff --git a/lib/rubygems/resolver.rb b/lib/rubygems/resolver.rb
index 9bf5f80930..ed4cbde3ba 100644
--- a/lib/rubygems/resolver.rb
+++ b/lib/rubygems/resolver.rb
@@ -144,7 +144,7 @@ class Gem::Resolver
[spec, activation_request]
end
- def requests(s, act, reqs=[]) # :nodoc:
+ def requests(s, act, reqs = []) # :nodoc:
return reqs if @ignore_dependencies
s.fetch_development_dependencies if @development
diff --git a/lib/rubygems/resolver/conflict.rb b/lib/rubygems/resolver/conflict.rb
index 367a36b43d..77c3add4b3 100644
--- a/lib/rubygems/resolver/conflict.rb
+++ b/lib/rubygems/resolver/conflict.rb
@@ -21,7 +21,7 @@ class Gem::Resolver::Conflict
# Creates a new resolver conflict when +dependency+ is in conflict with an
# already +activated+ specification.
- def initialize(dependency, activated, failed_dep=dependency)
+ def initialize(dependency, activated, failed_dep = dependency)
@dependency = dependency
@activated = activated
@failed_dep = failed_dep
diff --git a/lib/rubygems/source.rb b/lib/rubygems/source.rb
index 772ad04bc9..8b031e27a8 100644
--- a/lib/rubygems/source.rb
+++ b/lib/rubygems/source.rb
@@ -190,7 +190,7 @@ class Gem::Source
# Downloads +spec+ and writes it to +dir+. See also
# Gem::RemoteFetcher#download.
- def download(spec, dir=Dir.pwd)
+ def download(spec, dir = Dir.pwd)
fetcher = Gem::RemoteFetcher.fetcher
fetcher.download spec, uri.to_s, dir
end
@@ -210,7 +210,7 @@ class Gem::Source
end
end
- def typo_squatting?(host, distance_threshold=4)
+ def typo_squatting?(host, distance_threshold = 4)
return if @uri.host.nil?
levenshtein_distance(@uri.host, host).between? 1, distance_threshold
end
diff --git a/lib/rubygems/spec_fetcher.rb b/lib/rubygems/spec_fetcher.rb
index 285f117b39..835dedf948 100644
--- a/lib/rubygems/spec_fetcher.rb
+++ b/lib/rubygems/spec_fetcher.rb
@@ -83,7 +83,7 @@ class Gem::SpecFetcher
#
# If +matching_platform+ is false, gems for all platforms are returned.
- def search_for_dependency(dependency, matching_platform=true)
+ def search_for_dependency(dependency, matching_platform = true)
found = {}
rejected_specs = {}
@@ -130,7 +130,7 @@ class Gem::SpecFetcher
##
# Return all gem name tuples who's names match +obj+
- def detect(type=:complete)
+ def detect(type = :complete)
tuples = []
list, _ = available_specs(type)
@@ -150,7 +150,7 @@ class Gem::SpecFetcher
#
# If +matching_platform+ is false, gems for all platforms are returned.
- def spec_for_dependency(dependency, matching_platform=true)
+ def spec_for_dependency(dependency, matching_platform = true)
tuples, errors = search_for_dependency(dependency, matching_platform)
specs = []
@@ -280,7 +280,7 @@ class Gem::SpecFetcher
# Retrieves NameTuples from +source+ of the given +type+ (:prerelease,
# etc.). If +gracefully_ignore+ is true, errors are ignored.
- def tuples_for(source, type, gracefully_ignore=false) # :nodoc:
+ def tuples_for(source, type, gracefully_ignore = false) # :nodoc:
@caches[type][source.uri] ||=
source.load_specs(type).sort_by(&:name)
rescue Gem::RemoteFetcher::FetchError
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index 68ebbf8bc3..1d351f8aff 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -1757,7 +1757,7 @@ class Gem::Specification < Gem::BasicSpecification
#
# [depending_gem, dependency, [list_of_gems_that_satisfy_dependency]]
- def dependent_gems(check_dev=true)
+ def dependent_gems(check_dev = true)
out = []
Gem::Specification.each do |spec|
deps = check_dev ? spec.dependencies : spec.runtime_dependencies
diff --git a/lib/rubygems/text.rb b/lib/rubygems/text.rb
index da0795b771..88d4ce59b4 100644
--- a/lib/rubygems/text.rb
+++ b/lib/rubygems/text.rb
@@ -21,7 +21,7 @@ module Gem::Text
# Wraps +text+ to +wrap+ characters and optionally indents by +indent+
# characters
- def format_text(text, wrap, indent=0)
+ def format_text(text, wrap, indent = 0)
result = []
work = clean_text(text)
diff --git a/lib/rubygems/user_interaction.rb b/lib/rubygems/user_interaction.rb
index 0172c4ee89..5711376294 100644
--- a/lib/rubygems/user_interaction.rb
+++ b/lib/rubygems/user_interaction.rb
@@ -193,7 +193,7 @@ class Gem::StreamUI
# then special operations (like asking for passwords) will use the TTY
# commands to disable character echo.
- def initialize(in_stream, out_stream, err_stream=$stderr, usetty=true)
+ def initialize(in_stream, out_stream, err_stream = $stderr, usetty = true)
@ins = in_stream
@outs = out_stream
@errs = err_stream
@@ -246,7 +246,7 @@ class Gem::StreamUI
# to a tty, raises an exception if default is nil, otherwise returns
# default.
- def ask_yes_no(question, default=nil)
+ def ask_yes_no(question, default = nil)
unless tty?
if default.nil?
raise Gem::OperationNotSupportedError,
@@ -325,14 +325,14 @@ class Gem::StreamUI
##
# Display a statement.
- def say(statement="")
+ def say(statement = "")
@outs.puts statement
end
##
# Display an informational alert. Will ask +question+ if it is not nil.
- def alert(statement, question=nil)
+ def alert(statement, question = nil)
@outs.puts "INFO: #{statement}"
ask(question) if question
end
@@ -340,7 +340,7 @@ class Gem::StreamUI
##
# Display a warning on stderr. Will ask +question+ if it is not nil.
- def alert_warning(statement, question=nil)
+ def alert_warning(statement, question = nil)
@errs.puts "WARNING: #{statement}"
ask(question) if question
end
@@ -349,7 +349,7 @@ class Gem::StreamUI
# Display an error message in a location expected to get error messages.
# Will ask +question+ if it is not nil.
- def alert_error(statement, question=nil)
+ def alert_error(statement, question = nil)
@errs.puts "ERROR: #{statement}"
ask(question) if question
end
diff --git a/lib/rubygems/validator.rb b/lib/rubygems/validator.rb
index 57e0747eb4..eb5b513570 100644
--- a/lib/rubygems/validator.rb
+++ b/lib/rubygems/validator.rb
@@ -59,7 +59,7 @@ class Gem::Validator
#--
# TODO needs further cleanup
- def alien(gems=[])
+ def alien(gems = [])
errors = Hash.new {|h,k| h[k] = {} }
Gem::Specification.each do |spec|
diff --git a/lib/syntax_suggest/api.rb b/lib/syntax_suggest/api.rb
index 46c9c8adac..0f82d8362a 100644
--- a/lib/syntax_suggest/api.rb
+++ b/lib/syntax_suggest/api.rb
@@ -146,11 +146,7 @@ module SyntaxSuggest
def self.valid_without?(without_lines:, code_lines:)
lines = code_lines - Array(without_lines).flatten
- if lines.empty?
- true
- else
- valid?(lines)
- end
+ lines.empty? || valid?(lines)
end
# SyntaxSuggest.invalid? [Private]
diff --git a/prism/generate-srcs.mk.rb b/prism/generate-srcs.mk.rb
new file mode 100644
index 0000000000..af031ef2e4
--- /dev/null
+++ b/prism/generate-srcs.mk.rb
@@ -0,0 +1,17 @@
+require_relative 'templates/template'
+
+puts %[
+PRISM_TEMPLATES_DIR = $(PRISM_SRCDIR)/templates
+PRISM_TEMPLATE = $(PRISM_TEMPLATES_DIR)/template.rb
+PRISM_CONFIG = $(PRISM_SRCDIR)/config.yml
+]
+
+Prism::Template::TEMPLATES.map do |t|
+ /\.(?:[ch]|rb)\z/ =~ t or next
+ s = t.sub(%r[\A(?:(src)|ext|include)/]) {$1 && 'prism/'}
+ puts %[
+main srcs: $(srcdir)/#{s}
+$(srcdir)/#{s}: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/#{t}.erb
+\t$(Q) $(BASERUBY) $(PRISM_TEMPLATE) #{t} $@
+]
+end
diff --git a/prism/srcs.mk b/prism/srcs.mk
new file mode 100644
index 0000000000..aa5c0fa2b5
--- /dev/null
+++ b/prism/srcs.mk
@@ -0,0 +1,142 @@
+PRISM_TEMPLATES_DIR = $(PRISM_SRCDIR)/templates
+PRISM_TEMPLATE = $(PRISM_TEMPLATES_DIR)/template.rb
+PRISM_CONFIG = $(PRISM_SRCDIR)/config.yml
+
+srcs uncommon.mk: prism/.srcs.mk.time
+
+prism/.srcs.mk.time:
+prism/$(HAVE_BASERUBY:yes=.srcs.mk.time): \
+ $(PRISM_SRCDIR)/templates/template.rb \
+ $(PRISM_SRCDIR)/srcs.mk.in
+ $(BASERUBY) $(tooldir)/generic_erb.rb -c -t$@ -o $(PRISM_SRCDIR)/srcs.mk $(PRISM_SRCDIR)/srcs.mk.in
+
+realclean-prism-srcs::
+ $(RM) $(PRISM_SRCDIR)/srcs.mk
+
+realclean-srcs-local:: realclean-prism-srcs
+
+main srcs: $(srcdir)/prism/api_node.c
+$(srcdir)/prism/api_node.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/ext/prism/api_node.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) ext/prism/api_node.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/api_node.c
+
+main incs: $(srcdir)/prism/ast.h
+$(srcdir)/prism/ast.h: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/include/prism/ast.h.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) include/prism/ast.h $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/ast.h
+
+main incs: $(srcdir)/prism/diagnostic.h
+$(srcdir)/prism/diagnostic.h: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/include/prism/diagnostic.h.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) include/prism/diagnostic.h $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/diagnostic.h
+
+main srcs: $(srcdir)/lib/prism/compiler.rb
+$(srcdir)/lib/prism/compiler.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/compiler.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/compiler.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/compiler.rb
+
+main srcs: $(srcdir)/lib/prism/dispatcher.rb
+$(srcdir)/lib/prism/dispatcher.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/dispatcher.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/dispatcher.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/dispatcher.rb
+
+main srcs: $(srcdir)/lib/prism/dot_visitor.rb
+$(srcdir)/lib/prism/dot_visitor.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/dot_visitor.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/dot_visitor.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/dot_visitor.rb
+
+main srcs: $(srcdir)/lib/prism/dsl.rb
+$(srcdir)/lib/prism/dsl.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/dsl.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/dsl.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/dsl.rb
+
+main srcs: $(srcdir)/lib/prism/inspect_visitor.rb
+$(srcdir)/lib/prism/inspect_visitor.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/inspect_visitor.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/inspect_visitor.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/inspect_visitor.rb
+
+main srcs: $(srcdir)/lib/prism/mutation_compiler.rb
+$(srcdir)/lib/prism/mutation_compiler.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/mutation_compiler.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/mutation_compiler.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/mutation_compiler.rb
+
+main srcs: $(srcdir)/lib/prism/node.rb
+$(srcdir)/lib/prism/node.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/node.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/node.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/node.rb
+
+main srcs: $(srcdir)/lib/prism/reflection.rb
+$(srcdir)/lib/prism/reflection.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/reflection.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/reflection.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/reflection.rb
+
+main srcs: $(srcdir)/lib/prism/serialize.rb
+$(srcdir)/lib/prism/serialize.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/serialize.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/serialize.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/serialize.rb
+
+main srcs: $(srcdir)/lib/prism/visitor.rb
+$(srcdir)/lib/prism/visitor.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/visitor.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/visitor.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/visitor.rb
+
+main srcs: $(srcdir)/prism/diagnostic.c
+$(srcdir)/prism/diagnostic.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/src/diagnostic.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) src/diagnostic.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/diagnostic.c
+
+main srcs: $(srcdir)/prism/node.c
+$(srcdir)/prism/node.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/src/node.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) src/node.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/node.c
+
+main srcs: $(srcdir)/prism/prettyprint.c
+$(srcdir)/prism/prettyprint.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/src/prettyprint.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) src/prettyprint.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/prettyprint.c
+
+main srcs: $(srcdir)/prism/serialize.c
+$(srcdir)/prism/serialize.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/src/serialize.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) src/serialize.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/serialize.c
+
+main srcs: $(srcdir)/prism/token_type.c
+$(srcdir)/prism/token_type.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/src/token_type.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) src/token_type.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/token_type.c
diff --git a/prism/srcs.mk.in b/prism/srcs.mk.in
new file mode 100644
index 0000000000..655de155d5
--- /dev/null
+++ b/prism/srcs.mk.in
@@ -0,0 +1,40 @@
+<% # -*- ruby -*-
+require_relative 'templates/template'
+
+script = File.basename(__FILE__)
+srcs = output ? File.basename(output) : script.chomp('.in')
+mk = 'uncommon.mk'
+
+# %>
+PRISM_TEMPLATES_DIR = $(PRISM_SRCDIR)/templates
+PRISM_TEMPLATE = $(PRISM_TEMPLATES_DIR)/template.rb
+PRISM_CONFIG = $(PRISM_SRCDIR)/config.yml
+
+srcs <%=%><%=mk%>: prism/.srcs.mk.time
+
+prism/.srcs.mk.time:
+prism/$(HAVE_BASERUBY:yes=.srcs.mk.time): \
+ $(PRISM_SRCDIR)/templates/template.rb \
+ $(PRISM_SRCDIR)/<%=%><%=script%>
+ $(BASERUBY) $(tooldir)/generic_erb.rb -c -t$@ -o $(PRISM_SRCDIR)/<%=%><%=srcs%> $(PRISM_SRCDIR)/<%=%><%=script%>
+
+realclean-prism-srcs::
+ $(RM) $(PRISM_SRCDIR)/<%=%><%=srcs%>
+
+realclean-srcs-local:: realclean-prism-srcs
+<% Prism::Template::TEMPLATES.map do |t|
+ /\.(?:[ch]|rb)\z/ =~ t or next
+ s = '$(srcdir)/' + t.sub(%r[\A(?:(src)|ext|include)/]) {$1 && 'prism/'}
+ s.sub!(%r[\A\$(srcdir)/prism/], '$(PRISM_SRCDIR)/')
+ target = s.end_with?('.h') ? 'incs' : 'srcs'
+# %>
+
+main <%=%><%=target%>: <%=%><%=s%>
+<%=%><%=s%>: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/<%=%><%=t%>.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) <%=%><%=t%> $@
+
+realclean-prism-srcs::
+ $(RM) <%=%><%=s%>
+<%
+end
+# %>
diff --git a/proc.c b/proc.c
index 68f63040b7..554ec5e237 100644
--- a/proc.c
+++ b/proc.c
@@ -716,12 +716,15 @@ rb_func_proc_dup(VALUE src_obj)
VALUE proc_obj = TypedData_Make_Struct(rb_obj_class(src_obj), cfunc_proc_t, &proc_data_type, proc);
memcpy(&proc->basic, src_proc, sizeof(rb_proc_t));
+ RB_OBJ_WRITTEN(proc_obj, Qundef, proc->basic.block.as.captured.self);
+ RB_OBJ_WRITTEN(proc_obj, Qundef, proc->basic.block.as.captured.code.val);
+ const VALUE *src_ep = src_proc->block.as.captured.ep;
VALUE *ep = *(VALUE **)&proc->basic.block.as.captured.ep = proc->env + VM_ENV_DATA_SIZE - 1;
- ep[VM_ENV_DATA_INDEX_FLAGS] = src_proc->block.as.captured.ep[VM_ENV_DATA_INDEX_FLAGS];
- ep[VM_ENV_DATA_INDEX_ME_CREF] = src_proc->block.as.captured.ep[VM_ENV_DATA_INDEX_ME_CREF];
- ep[VM_ENV_DATA_INDEX_SPECVAL] = src_proc->block.as.captured.ep[VM_ENV_DATA_INDEX_SPECVAL];
- ep[VM_ENV_DATA_INDEX_ENV] = src_proc->block.as.captured.ep[VM_ENV_DATA_INDEX_ENV];
+ ep[VM_ENV_DATA_INDEX_FLAGS] = src_ep[VM_ENV_DATA_INDEX_FLAGS];
+ ep[VM_ENV_DATA_INDEX_ME_CREF] = src_ep[VM_ENV_DATA_INDEX_ME_CREF];
+ ep[VM_ENV_DATA_INDEX_SPECVAL] = src_ep[VM_ENV_DATA_INDEX_SPECVAL];
+ RB_OBJ_WRITE(proc_obj, &ep[VM_ENV_DATA_INDEX_ENV], src_ep[VM_ENV_DATA_INDEX_ENV]);
return proc_obj;
}
diff --git a/random.c b/random.c
index 85d72057cd..9b8cec40b4 100644
--- a/random.c
+++ b/random.c
@@ -142,18 +142,21 @@ static const rb_random_interface_t random_mt_if = {
};
static rb_random_mt_t *
-rand_mt_start(rb_random_mt_t *r)
+rand_mt_start(rb_random_mt_t *r, VALUE obj)
{
if (!genrand_initialized(&r->mt)) {
r->base.seed = rand_init(&random_mt_if, &r->base, random_seed(Qundef));
+ if (obj) {
+ RB_OBJ_WRITTEN(obj, Qundef, r->base.seed);
+ }
}
return r;
}
static rb_random_t *
-rand_start(rb_random_mt_t *r)
+rand_start(rb_random_mt_t *r, VALUE obj)
{
- return &rand_mt_start(r)->base;
+ return &rand_mt_start(r, obj)->base;
}
static rb_ractor_local_key_t default_rand_key;
@@ -192,7 +195,13 @@ default_rand(void)
static rb_random_mt_t *
default_mt(void)
{
- return rand_mt_start(default_rand());
+ return rand_mt_start(default_rand(), Qfalse);
+}
+
+static rb_random_t *
+default_rand_start(void)
+{
+ return &default_mt()->base;
}
unsigned int
@@ -293,7 +302,7 @@ get_rnd(VALUE obj)
rb_random_t *ptr;
TypedData_Get_Struct(obj, rb_random_t, &rb_random_data_type, ptr);
if (RTYPEDDATA_TYPE(obj) == &random_mt_type)
- return rand_start((rb_random_mt_t *)ptr);
+ return rand_start((rb_random_mt_t *)ptr, obj);
return ptr;
}
@@ -309,11 +318,11 @@ static rb_random_t *
try_get_rnd(VALUE obj)
{
if (obj == rb_cRandom) {
- return rand_start(default_rand());
+ return default_rand_start();
}
if (!rb_typeddata_is_kind_of(obj, &rb_random_data_type)) return NULL;
if (RTYPEDDATA_TYPE(obj) == &random_mt_type)
- return rand_start(DATA_PTR(obj));
+ return rand_start(DATA_PTR(obj), obj);
rb_random_t *rnd = DATA_PTR(obj);
if (!rnd) {
rb_raise(rb_eArgError, "uninitialized random: %s",
@@ -829,6 +838,7 @@ rand_mt_copy(VALUE obj, VALUE orig)
mt = &rnd1->mt;
*rnd1 = *rnd2;
+ RB_OBJ_WRITTEN(obj, Qundef, rnd1->base.seed);
mt->next = mt->state + numberof(mt->state) - mt->left + 1;
return obj;
}
@@ -916,7 +926,7 @@ rand_mt_load(VALUE obj, VALUE dump)
}
mt->left = (unsigned int)x;
mt->next = mt->state + numberof(mt->state) - x + 1;
- rnd->base.seed = rb_to_int(seed);
+ RB_OBJ_WRITE(obj, &rnd->base.seed, rb_to_int(seed));
return obj;
}
@@ -975,7 +985,7 @@ static VALUE
rb_f_srand(int argc, VALUE *argv, VALUE obj)
{
VALUE seed, old;
- rb_random_mt_t *r = rand_mt_start(default_rand());
+ rb_random_mt_t *r = default_mt();
if (rb_check_arity(argc, 0, 1) == 0) {
seed = random_seed(obj);
@@ -1337,7 +1347,7 @@ rb_random_bytes(VALUE obj, long n)
static VALUE
random_s_bytes(VALUE obj, VALUE len)
{
- rb_random_t *rnd = rand_start(default_rand());
+ rb_random_t *rnd = default_rand_start();
return rand_bytes(&random_mt_if, rnd, NUM2LONG(rb_to_int(len)));
}
@@ -1359,7 +1369,7 @@ random_s_bytes(VALUE obj, VALUE len)
static VALUE
random_s_seed(VALUE obj)
{
- rb_random_mt_t *rnd = rand_mt_start(default_rand());
+ rb_random_mt_t *rnd = default_mt();
return rnd->base.seed;
}
@@ -1689,7 +1699,7 @@ static VALUE
rb_f_rand(int argc, VALUE *argv, VALUE obj)
{
VALUE vmax;
- rb_random_t *rnd = rand_start(default_rand());
+ rb_random_t *rnd = default_rand_start();
if (rb_check_arity(argc, 0, 1) && !NIL_P(vmax = argv[0])) {
VALUE v = rand_range(obj, rnd, vmax);
@@ -1716,7 +1726,7 @@ rb_f_rand(int argc, VALUE *argv, VALUE obj)
static VALUE
random_s_rand(int argc, VALUE *argv, VALUE obj)
{
- VALUE v = rand_random(argc, argv, Qnil, rand_start(default_rand()));
+ VALUE v = rand_random(argc, argv, Qnil, default_rand_start());
check_random_number(v, argv);
return v;
}
diff --git a/range.c b/range.c
index 12077a068e..615154be4c 100644
--- a/range.c
+++ b/range.c
@@ -47,6 +47,7 @@ static VALUE r_cover_p(VALUE, VALUE, VALUE, VALUE);
static void
range_init(VALUE range, VALUE beg, VALUE end, VALUE exclude_end)
{
+ // Changing this condition has implications for JITs. If you do, please let maintainers know.
if ((!FIXNUM_P(beg) || !FIXNUM_P(end)) && !NIL_P(beg) && !NIL_P(end)) {
VALUE v;
diff --git a/re.c b/re.c
index 9348622eea..13d7f0ef9e 100644
--- a/re.c
+++ b/re.c
@@ -290,11 +290,6 @@ rb_memsearch(const void *x0, long m, const void *y0, long n, rb_encoding *enc)
#define KCODE_FIXED FL_USER4
-#define ARG_REG_OPTION_MASK \
- (ONIG_OPTION_IGNORECASE|ONIG_OPTION_MULTILINE|ONIG_OPTION_EXTEND)
-#define ARG_ENCODING_FIXED 16
-#define ARG_ENCODING_NONE 32
-
static int
char_to_option(int c)
{
diff --git a/shape.c b/shape.c
index df4faf960c..d58f9f1d0c 100644
--- a/shape.c
+++ b/shape.c
@@ -369,7 +369,7 @@ RUBY_FUNC_EXPORTED shape_id_t
rb_obj_shape_id(VALUE obj)
{
if (RB_SPECIAL_CONST_P(obj)) {
- return SPECIAL_CONST_SHAPE_ID;
+ rb_bug("rb_obj_shape_id: called on a special constant");
}
if (BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE) {
@@ -1180,6 +1180,7 @@ rb_shape_copy_complex_ivars(VALUE dest, VALUE obj, shape_id_t src_shape_id, st_t
st_delete(table, &id, NULL);
}
rb_obj_init_too_complex(dest, table);
+ rb_gc_writebarrier_remember(dest);
}
size_t
@@ -1424,6 +1425,9 @@ rb_shape_parent(VALUE self)
static VALUE
rb_shape_debug_shape(VALUE self, VALUE obj)
{
+ if (RB_SPECIAL_CONST_P(obj)) {
+ rb_raise(rb_eArgError, "Can't get shape of special constant");
+ }
return shape_id_t_to_rb_cShape(rb_obj_shape_id(obj));
}
diff --git a/spec/bundler/commands/list_spec.rb b/spec/bundler/commands/list_spec.rb
index cc0db9169d..c890646a81 100644
--- a/spec/bundler/commands/list_spec.rb
+++ b/spec/bundler/commands/list_spec.rb
@@ -1,6 +1,28 @@
# frozen_string_literal: true
+require "json"
+
RSpec.describe "bundle list" do
+ def find_gem_name(json:, name:)
+ parse_json(json)["gems"].detect {|h| h["name"] == name }
+ end
+
+ def parse_json(json)
+ JSON.parse(json)
+ end
+
+ context "in verbose mode" do
+ it "logs the actual flags passed to the command" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ G
+
+ bundle "list --verbose"
+
+ expect(out).to include("Running `bundle list --verbose`")
+ end
+ end
+
context "with name-only and paths option" do
it "raises an error" do
bundle "list --name-only --paths", raise_on_error: false
@@ -17,6 +39,20 @@ RSpec.describe "bundle list" do
end
end
+ context "with invalid format option" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ G
+ end
+
+ it "raises an error" do
+ bundle "list --format=nope", raise_on_error: false
+
+ expect(err).to eq "Unknown option`--format=nope`. Supported formats: `json`"
+ end
+ end
+
describe "with without-group option" do
before do
install_gemfile <<-G
@@ -36,6 +72,17 @@ RSpec.describe "bundle list" do
expect(out).to include(" * rails (2.3.2)")
expect(out).not_to include(" * rspec (1.2.7)")
end
+
+ it "prints the gems not in the specified group with json" do
+ bundle "list --without-group test --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["version"]).to eq("1.0.0")
+ gem = find_gem_name(json: out, name: "rails")
+ expect(gem["version"]).to eq("2.3.2")
+ gem = find_gem_name(json: out, name: "rspec")
+ expect(gem).to be_nil
+ end
end
context "when group is not found" do
@@ -54,6 +101,17 @@ RSpec.describe "bundle list" do
expect(out).not_to include(" * rails (2.3.2)")
expect(out).not_to include(" * rspec (1.2.7)")
end
+
+ it "prints the gems not in the specified groups with json" do
+ bundle "list --without-group test production --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["version"]).to eq("1.0.0")
+ gem = find_gem_name(json: out, name: "rails")
+ expect(gem).to be_nil
+ gem = find_gem_name(json: out, name: "rspec")
+ expect(gem).to be_nil
+ end
end
end
@@ -75,6 +133,15 @@ RSpec.describe "bundle list" do
expect(out).to include(" * myrack (1.0.0)")
expect(out).not_to include(" * rspec (1.2.7)")
end
+
+ it "prints the gems in the specified group with json" do
+ bundle "list --only-group default --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["version"]).to eq("1.0.0")
+ gem = find_gem_name(json: out, name: "rspec")
+ expect(gem).to be_nil
+ end
end
context "when group is not found" do
@@ -93,6 +160,17 @@ RSpec.describe "bundle list" do
expect(out).to include(" * rails (2.3.2)")
expect(out).not_to include(" * rspec (1.2.7)")
end
+
+ it "prints the gems in the specified groups with json" do
+ bundle "list --only-group default production --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["version"]).to eq("1.0.0")
+ gem = find_gem_name(json: out, name: "rails")
+ expect(gem["version"]).to eq("2.3.2")
+ gem = find_gem_name(json: out, name: "rspec")
+ expect(gem).to be_nil
+ end
end
end
@@ -112,6 +190,15 @@ RSpec.describe "bundle list" do
expect(out).to include("myrack")
expect(out).to include("rspec")
end
+
+ it "prints only the name of the gems in the bundle with json" do
+ bundle "list --name-only --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem.keys).to eq(["name"])
+ gem = find_gem_name(json: out, name: "rspec")
+ expect(gem.keys).to eq(["name"])
+ end
end
context "with paths option" do
@@ -146,6 +233,27 @@ RSpec.describe "bundle list" do
expect(out).to match(%r{.*\/git_test\-\w})
expect(out).to match(%r{.*\/gemspec_test})
end
+
+ it "prints the path of each gem in the bundle with json" do
+ bundle "list --paths --format=json"
+
+ gem = find_gem_name(json: out, name: "rails")
+ expect(gem["path"]).to match(%r{.*\/rails\-2\.3\.2})
+ expect(gem["git_version"]).to be_nil
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["path"]).to match(%r{.*\/myrack\-1\.2})
+ expect(gem["git_version"]).to be_nil
+
+ gem = find_gem_name(json: out, name: "git_test")
+ expect(gem["path"]).to match(%r{.*\/git_test\-\w})
+ expect(gem["git_version"]).to be_truthy
+ expect(gem["git_version"].strip).to eq(gem["git_version"])
+
+ gem = find_gem_name(json: out, name: "gemspec_test")
+ expect(gem["path"]).to match(%r{.*\/gemspec_test})
+ expect(gem["git_version"]).to be_nil
+ end
end
context "when no gems are in the gemfile" do
@@ -159,6 +267,11 @@ RSpec.describe "bundle list" do
bundle "list"
expect(out).to include("No gems in the Gemfile")
end
+
+ it "prints empty json" do
+ bundle "list --format=json"
+ expect(parse_json(out)["gems"]).to eq([])
+ end
end
context "without options" do
@@ -175,6 +288,13 @@ RSpec.describe "bundle list" do
bundle "list"
expect(out).to include(" * myrack (1.0.0)")
end
+
+ it "lists gems installed in the bundle with json" do
+ bundle "list --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["version"]).to eq("1.0.0")
+ end
end
context "when using the ls alias" do
diff --git a/spec/bundler/commands/show_spec.rb b/spec/bundler/commands/show_spec.rb
index 82ec6e51f2..ba903ac495 100644
--- a/spec/bundler/commands/show_spec.rb
+++ b/spec/bundler/commands/show_spec.rb
@@ -3,8 +3,10 @@
RSpec.describe "bundle show" do
context "with a standard Gemfile" do
before :each do
+ build_repo2
+
install_gemfile <<-G
- source "https://gem.repo1"
+ source "https://gem.repo2"
gem "rails"
G
end
@@ -86,6 +88,24 @@ RSpec.describe "bundle show" do
\tStatus: Up to date
MSG
end
+
+ it "includes up to date status in summary of gems" do
+ update_repo2 do
+ build_gem "rails", "3.0.0"
+ end
+
+ bundle "show --verbose"
+
+ expect(out).to include <<~MSG
+ * rails (2.3.2)
+ \tSummary: This is just a fake gem for testing
+ \tHomepage: http://example.com
+ \tStatus: Outdated - 2.3.2 < 3.0.0
+ MSG
+
+ # check lockfile is not accidentally updated
+ expect(lockfile).to include("actionmailer (2.3.2)")
+ end
end
context "with a git repo in the Gemfile" do
@@ -219,6 +239,6 @@ RSpec.describe "bundle show" do
end
end
-RSpec.describe "bundle show", bundler: "4" do
+RSpec.describe "bundle show", bundler: "5" do
pending "shows a friendly error about the command removal"
end
diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb
index 22bb1662e6..7702c72397 100644
--- a/spec/bundler/commands/update_spec.rb
+++ b/spec/bundler/commands/update_spec.rb
@@ -445,6 +445,49 @@ RSpec.describe "bundle update" do
expect(out).to include("Installing sneakers 2.11.0").and include("Installing rake 13.0.6")
end
+ it "downgrades indirect dependencies if required to fulfill an explicit upgrade request" do
+ build_repo4 do
+ build_gem "rbs", "3.6.1"
+ build_gem "rbs", "3.9.4"
+
+ build_gem "solargraph", "0.56.0" do |s|
+ s.add_dependency "rbs", "~> 3.3"
+ end
+
+ build_gem "solargraph", "0.56.2" do |s|
+ s.add_dependency "rbs", "~> 3.6.1"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem 'solargraph', '~> 0.56.0'
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ rbs (3.9.4)
+ solargraph (0.56.0)
+ rbs (~> 3.3)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ solargraph (~> 0.56.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --update solargraph"
+
+ expect(lockfile).to include("solargraph (0.56.2)")
+ end
+
it "does not downgrade direct dependencies unnecessarily" do
build_repo4 do
build_gem "redis", "4.8.1"
@@ -1809,7 +1852,7 @@ RSpec.describe "bundle update --bundler" do
system_gems "bundler-9.9.9", path: local_gem_path
bundle "update --bundler=9.9.9", env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false
- expect(err).to include("An update to the version of bundler itself was requested, but the lockfile can't be updated because frozen mode is set")
+ expect(err).to include("An update to the version of Bundler itself was requested, but the lockfile can't be updated because frozen mode is set")
end
end
diff --git a/spec/bundler/install/gemfile/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb
index cd83ad71c0..216548cf27 100644
--- a/spec/bundler/install/gemfile/git_spec.rb
+++ b/spec/bundler/install/gemfile/git_spec.rb
@@ -2,12 +2,8 @@
RSpec.describe "bundle install with git sources" do
describe "when floating on main" do
- before :each do
- build_git "foo" do |s|
- s.executables = "foobar"
- end
-
- install_gemfile <<-G
+ let(:base_gemfile) do
+ <<-G
source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem 'foo'
@@ -15,7 +11,16 @@ RSpec.describe "bundle install with git sources" do
G
end
+ let(:install_base_gemfile) do
+ build_git "foo" do |s|
+ s.executables = "foobar"
+ end
+
+ install_gemfile base_gemfile
+ end
+
it "fetches gems" do
+ install_base_gemfile
expect(the_bundle).to include_gems("foo 1.0")
run <<-RUBY
@@ -26,17 +31,57 @@ RSpec.describe "bundle install with git sources" do
expect(out).to eq("WIN")
end
+ it "does not (yet?) enforce CHECKSUMS" do
+ build_git "foo"
+ revision = revision_for(lib_path("foo-1.0"))
+
+ bundle "config set lockfile_checksums true"
+ gemfile base_gemfile
+
+ lockfile <<~L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{revision}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ CHECKSUMS
+ foo (1.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "config set frozen true"
+
+ bundle "install"
+ expect(the_bundle).to include_gems("foo 1.0")
+ end
+
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
end
it "does not write to cache on bundler/setup" do
+ install_base_gemfile
FileUtils.rm_r(default_cache_path)
ruby "require 'bundler/setup'"
expect(default_cache_path).not_to exist
end
it "caches the git repo globally and properly uses the cached repo on the next invocation" do
+ install_base_gemfile
pristine_system_gems
bundle "config set global_gem_cache true"
bundle :install
@@ -48,6 +93,7 @@ RSpec.describe "bundle install with git sources" do
end
it "caches the evaluated gemspec" do
+ install_base_gemfile
git = update_git "foo" do |s|
s.executables = ["foobar"] # we added this the first time, so keep it now
s.files = ["bin/foobar"] # updating git nukes the files list
@@ -66,6 +112,7 @@ RSpec.describe "bundle install with git sources" do
end
it "does not update the git source implicitly" do
+ install_base_gemfile
update_git "foo"
install_gemfile bundled_app2("Gemfile"), <<-G, dir: bundled_app2
@@ -84,6 +131,7 @@ RSpec.describe "bundle install with git sources" do
end
it "sets up git gem executables on the path" do
+ install_base_gemfile
bundle "exec foobar"
expect(out).to eq("1.0")
end
@@ -136,7 +184,7 @@ RSpec.describe "bundle install with git sources" do
it "still works after moving the application directory" do
bundle "config set --local path vendor/bundle"
- bundle "install"
+ install_base_gemfile
FileUtils.mv bundled_app, tmp("bundled_app.bck")
@@ -145,7 +193,7 @@ RSpec.describe "bundle install with git sources" do
it "can still install after moving the application directory" do
bundle "config set --local path vendor/bundle"
- bundle "install"
+ install_base_gemfile
FileUtils.mv bundled_app, tmp("bundled_app.bck")
diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb
index 71065c36f3..62540f0488 100644
--- a/spec/bundler/install/gemfile/specific_platform_spec.rb
+++ b/spec/bundler/install/gemfile/specific_platform_spec.rb
@@ -1432,7 +1432,7 @@ RSpec.describe "bundle install with specific platforms" do
end
end
- it "does not fail when a platform variant is incompatible with the current ruby and another equivalent platform specific variant is part of the resolution", rubygems: ">= 3.3.21" do
+ it "does not fail when a platform variant is incompatible with the current ruby and another equivalent platform specific variant is part of the resolution" do
build_repo4 do
build_gem "nokogiri", "1.15.5"
@@ -1578,7 +1578,7 @@ RSpec.describe "bundle install with specific platforms" do
end
end
- it "adds current musl platform, when there are also gnu variants", rubygems: ">= 3.3.21" do
+ it "adds current musl platform, when there are also gnu variants" do
build_repo4 do
build_gem "rcee_precompiled", "0.5.0" do |s|
s.platform = "x86_64-linux-gnu"
diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb
index e1fbe6934a..6b98e0924e 100644
--- a/spec/bundler/lock/lockfile_spec.rb
+++ b/spec/bundler/lock/lockfile_spec.rb
@@ -1638,7 +1638,7 @@ RSpec.describe "the lockfile format" do
G
expect(err).to eq <<~L.strip
- Your lockfile is missing a checksums entry for \"myrack_middleware\", but can't be updated because frozen mode is set
+ Your lockfile is missing a CHECKSUMS entry for \"myrack_middleware\", but can't be updated because frozen mode is set
Run `bundle install` elsewhere and add the updated Gemfile.lock to version control.
L
@@ -1646,6 +1646,40 @@ RSpec.describe "the lockfile format" do
expect(the_bundle).not_to include_gems "myrack_middleware 1.0"
end
+ it "raises a clear error when frozen mode is set and lockfile has empty checksums in CHECKSUMS section, and does not install any gems" do
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack (0.9.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+
+ CHECKSUMS
+ myrack (0.9.1)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false
+ source "https://gem.repo2"
+ gem "myrack"
+ G
+
+ expect(err).to eq <<~L.strip
+ Your lockfile has an empty CHECKSUMS entry for \"myrack\", but can't be updated because frozen mode is set
+
+ Run `bundle install` elsewhere and add the updated Gemfile.lock to version control.
+ L
+
+ expect(the_bundle).not_to include_gems "myrack 0.9.1"
+ end
+
it "automatically fixes the lockfile when it's missing deps, they conflict with other locked deps, but conflicts are fixable" do
build_repo4 do
build_gem "other_dep", "0.9"
diff --git a/spec/bundler/other/cli_man_pages_spec.rb b/spec/bundler/other/cli_man_pages_spec.rb
index 84ffca14e6..6efd2904d6 100644
--- a/spec/bundler/other/cli_man_pages_spec.rb
+++ b/spec/bundler/other/cli_man_pages_spec.rb
@@ -1,49 +1,72 @@
# frozen_string_literal: true
RSpec.describe "bundle commands" do
- it "expects all commands to have a man page" do
- Bundler::CLI.all_commands.each_key do |command_name|
- next if command_name == "cli_help"
+ it "expects all commands to have all options and subcommands documented" do
+ check_commands!(Bundler::CLI)
- expect(man_page(command_name)).to exist
+ Bundler::CLI.subcommand_classes.each_value do |klass|
+ check_commands!(klass)
end
end
- it "expects all commands to have all options documented" do
- Bundler::CLI.all_commands.each do |command_name, command|
- next if command_name == "cli_help"
+ private
+
+ def check_commands!(command_class)
+ command_class.commands.each do |command_name, command|
+ next if command.is_a?(Bundler::Thor::HiddenCommand)
+
+ if command_class == Bundler::CLI
+ man_page = man_page(command_name)
+ expect(man_page).to exist
+
+ check_options!(command, man_page)
+ else
+ man_page = man_page(command.ancestor_name)
+ expect(man_page).to exist
- man_page_content = man_page(command_name).read
+ check_options!(command, man_page)
+ check_subcommand!(command_name, man_page)
+ end
+ end
+ end
- command.options.each do |_, option|
- aliases = option.aliases
- formatted_aliases = aliases.sort.map {|name| "`#{name}`" }.join(", ") if aliases
+ def check_options!(command, man_page)
+ command.options.each do |_, option|
+ check_option!(option, man_page)
+ end
+ end
- help = if option.type == :boolean
- "* #{append_aliases("`#{option.switch_name}`", formatted_aliases)}:"
- elsif option.enum
- formatted_aliases = "`#{option.switch_name}`" if aliases.empty? && option.lazy_default
- "* #{prepend_aliases(option.enum.sort.map {|enum| "`#{option.switch_name}=#{enum}`" }.join(", "), formatted_aliases)}:"
- else
- names = [option.switch_name, *aliases]
- value =
- case option.type
- when :array then "<list>"
- when :numeric then "<number>"
- else option.name.upcase
- end
+ def check_option!(option, man_page)
+ man_page_content = man_page.read
- value = option.type != :numeric && option.lazy_default ? "[=#{value}]" : "=#{value}"
+ aliases = option.aliases
+ formatted_aliases = aliases.sort.map {|name| "`#{name}`" }.join(", ") if aliases
- "* #{names.map {|name| "`#{name}#{value}`" }.join(", ")}:"
+ help = if option.type == :boolean
+ "* #{append_aliases("`#{option.switch_name}`", formatted_aliases)}:"
+ elsif option.enum
+ formatted_aliases = "`#{option.switch_name}`" if aliases.empty? && option.lazy_default
+ "* #{prepend_aliases(option.enum.sort.map {|enum| "`#{option.switch_name}=#{enum}`" }.join(", "), formatted_aliases)}:"
+ else
+ names = [option.switch_name, *aliases]
+ value =
+ case option.type
+ when :array then "<list>"
+ when :numeric then "<number>"
+ else option.name.upcase
end
- expect(man_page_content).to include(help)
- end
+ value = option.type != :numeric && option.lazy_default ? "[=#{value}]" : "=#{value}"
+
+ "* #{names.map {|name| "`#{name}#{value}`" }.join(", ")}:"
end
+
+ expect(man_page_content).to include(help)
end
- private
+ def check_subcommand!(name, man_page)
+ expect(man_page.read).to match(name)
+ end
def append_aliases(text, aliases)
return text if aliases.empty?
@@ -57,6 +80,10 @@ RSpec.describe "bundle commands" do
"#{aliases}, #{text}"
end
+ def man_page_content(command_name)
+ man_page(command_name).read
+ end
+
def man_page(command_name)
source_root.join("lib/bundler/man/bundle-#{command_name}.1.ronn")
end
diff --git a/spec/bundler/other/major_deprecation_spec.rb b/spec/bundler/other/major_deprecation_spec.rb
index 51d490ea72..d57abe45f3 100644
--- a/spec/bundler/other/major_deprecation_spec.rb
+++ b/spec/bundler/other/major_deprecation_spec.rb
@@ -199,6 +199,28 @@ RSpec.describe "major deprecations" do
pending "fails with a helpful error", bundler: "4"
end
+ context "bundle cache --no-all" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "cache --no-all", raise_on_error: false
+ end
+
+ it "should print a deprecation warning" do
+ expect(deprecations).to include(
+ "The `--no-all` flag is deprecated because it relies on being " \
+ "remembered across bundler invocations, which bundler will no " \
+ "longer do in future versions. Instead please use `bundle config set " \
+ "cache_all false`, and stop using this flag"
+ )
+ end
+
+ pending "fails with a helpful error", bundler: "4"
+ end
+
context "bundle cache --path" do
before do
install_gemfile <<-G
@@ -592,7 +614,7 @@ RSpec.describe "major deprecations" do
end
it "prints a deprecation warning informing about its removal" do
- expect(deprecations).to include("the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement")
+ expect(deprecations).to include("the `--outdated` flag to `bundle show` will be removed in favor of `bundle show --verbose`")
end
pending "fails with a helpful message", bundler: "4"
diff --git a/spec/bundler/quality_spec.rb b/spec/bundler/quality_spec.rb
index 18d8e20030..3e5a960a96 100644
--- a/spec/bundler/quality_spec.rb
+++ b/spec/bundler/quality_spec.rb
@@ -251,58 +251,9 @@ RSpec.describe "The library itself" do
expect(lib_code).to eq(spec_code)
end
- it "documents all cli command options in their associated man pages" do
- commands = normalize_commands_and_options(Bundler::CLI)
- cli_and_man_pages_in_sync!(commands)
-
- Bundler::CLI.subcommand_classes.each do |_, klass|
- subcommands = normalize_commands_and_options(klass)
-
- cli_and_man_pages_in_sync!(subcommands)
- end
- end
-
private
def each_line(filename, &block)
File.readlines(filename, encoding: "UTF-8").each_with_index(&block)
end
-
- def normalize_commands_and_options(command_class)
- commands = {}
-
- command_class.commands.each do |command_name, command|
- next if command.is_a?(Bundler::Thor::HiddenCommand)
-
- key = command.ancestor_name || command_name
- commands[key] ||= []
- # Verify that all subcommands are documented in the main command's man page.
- commands[key] << command_name unless command_class == Bundler::CLI
-
- command.options.each do |_, option|
- commands[key] << option.switch_name
- end
- end
-
- commands
- end
-
- def cli_and_man_pages_in_sync!(commands)
- commands.each do |command_name, opts|
- man_page_path = man_tracked_files.find {|f| File.basename(f) == "bundle-#{command_name}.1.ronn" }
- expect(man_page_path).to_not be_nil, "The command #{command_name} has no associated man page."
-
- next if opts.empty?
-
- man_page_content = File.read(man_page_path)
- opts.each do |option_name|
- error_msg = <<~EOM
- The command #{command_name} has no mention of the option or subcommand `#{option_name}` in its man page.
- Document the `#{option_name}` in the man page to discard this error.
- EOM
-
- expect(man_page_content).to match(option_name), error_msg
- end
- end
- end
end
diff --git a/spec/bundler/resolver/platform_spec.rb b/spec/bundler/resolver/platform_spec.rb
index 13f3e15282..a1d095d024 100644
--- a/spec/bundler/resolver/platform_spec.rb
+++ b/spec/bundler/resolver/platform_spec.rb
@@ -387,7 +387,7 @@ RSpec.describe "Resolving platform craziness" do
should_resolve_as %w[thin-1.2.7-x64-mingw-ucrt]
end
- it "finds universal-mingw gems on x64-mingw-ucrt", rubygems: ">= 3.3.18" do
+ it "finds universal-mingw gems on x64-mingw-ucrt" do
platform "x64-mingw-ucrt"
dep "win32-api"
should_resolve_as %w[win32-api-1.5.1-universal-mingw32]
diff --git a/spec/bundler/runtime/inline_spec.rb b/spec/bundler/runtime/inline_spec.rb
index 0467d8b14a..cffaab3579 100644
--- a/spec/bundler/runtime/inline_spec.rb
+++ b/spec/bundler/runtime/inline_spec.rb
@@ -590,14 +590,10 @@ RSpec.describe "bundler/inline#gemfile" do
expect(err).to be_empty
end
- it "does not load default timeout" do
+ it "does not load default timeout", rubygems: ">= 3.5.0" do
default_timeout_version = ruby "gem 'timeout', '< 999999'; require 'timeout'; puts Timeout::VERSION", raise_on_error: false
skip "timeout isn't a default gem" if default_timeout_version.empty?
- # This only works on RubyGems 3.5.0 or higher
- ruby "require 'rubygems/timeout'", raise_on_error: false
- skip "rubygems under test does not yet vendor timeout" unless last_command.success?
-
build_repo4 do
build_gem "timeout", "999"
end
diff --git a/template/GNUmakefile.in b/template/GNUmakefile.in
index 22ff1078dc..452e7cdeef 100644
--- a/template/GNUmakefile.in
+++ b/template/GNUmakefile.in
@@ -27,5 +27,8 @@ override UNICODE_TABLES_DEPENDENTS = \
$(UNICODE_TABLES_DATA_FILES)))),\
force,none)
+# extract NMake-style include list
+$(eval common_mk_includes := $(shell sed -n 's/^!include *//p' $(srcdir)/common.mk))
+
-include uncommon.mk
include $(srcdir)/defs/gmake.mk
diff --git a/template/Makefile.in b/template/Makefile.in
index 66ac10de1b..39f702b66d 100644
--- a/template/Makefile.in
+++ b/template/Makefile.in
@@ -350,13 +350,40 @@ $(LIBRUBY_$(LIBRUBY_WITH_EXT)): $(LIBRUBY_SO_UPDATE)
PKG_CONFIG = @PKG_CONFIG@
ruby_pc = @ruby_pc@
$(ruby_pc): config.status Makefile
- $(Q)./config.status --file=-:$(srcdir)/template/ruby.pc.in | \
+ $(Q) \
+ pkg="$(@libdirname@)/pkgconfig" prefix="$(prefix)"; \
+ if [ "$(LIBRUBY_RELATIVE)" = yes ]; then \
+ case "$$pkg" in "$$prefix"/?*) \
+ pkg="$${pkg#$$prefix/}"; \
+ prefix='$${pcfiledir}'`echo "/$${pkg}" | sed -e 's|/[^/][^/]*|/..|g'`; \
+ esac; \
+ fi; \
+ ./config.status --file=-:$(srcdir)/template/ruby.pc.in | \
sed -e 's/\$$(\([A-Za-z_][A-Za-z0-9_]*\))/$${\1}/g' \
- -e 's|^prefix=.*|prefix=$(prefix)|' \
+ -e "s|^prefix=.*|prefix=$$prefix|" \
> ruby.tmp.pc
$(Q)pkg_config=${PKG_CONFIG} && PKG_CONFIG_PATH=. $${pkg_config:-:} --print-errors ruby.tmp
$(Q)$(MV) -f ruby.tmp.pc $(ruby_pc)
+test-pc: install-data
+ set -ex; \
+ [ -z "$${pkg_config=$(PKG_CONFIG)}" ] && exit; \
+ export PKG_CONFIG_PATH=$(DESTDIR)/$(libdir)/pkgconfig$${PKG_CONFIG_PATH:+:$$PKG_CONFIG_PATH}; \
+ $${pkg_config} --exists $(ruby_pc:.pc=); \
+ path=`$${pkg_config} --variable=prefix $(ruby_pc:.pc=)`; \
+ if [ "$(LIBRUBY_RELATIVE)" = yes ]; then \
+ test "$$path" -ef "$(DESTDIR)$(prefix)"; \
+ else \
+ test "$$path" = "$(prefix)"; \
+ fi
+
+install-data: pkgconfig-data pre-install-data do-install-data post-install-data
+pre-install-data:: install-prereq
+do-install-data: $(PREP) pre-install-data
+ $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=data
+post-install-data::
+ @$(NULLCMD)
+
modular-gc-precheck:
$(Q) if test -z $(modular_gc_dir); then \
echo "You must configure with --with-modular-gc to use modular GC"; \
@@ -399,8 +426,8 @@ $(MKFILES): config.status $(srcdir)/version.h $(ABI_VERSION_HDR)
$(MAKE) -f conftest.mk | grep '^AUTO_REMAKE$$' >/dev/null 2>&1 || \
{ echo "$@ updated, restart."; exit 1; }
-uncommon.mk: $(srcdir)/common.mk $(srcdir)/depend
- sed 's/{\$$([^(){}]*)[^{}]*}//g' $(srcdir)/common.mk $(srcdir)/depend > $@
+uncommon.mk: $(srcdir)/tool/prereq.status
+ sed -f $(srcdir)/tool/prereq.status $(srcdir)/common.mk $(common_mk_includes) > $@
.PHONY: reconfig
reconfig-args = $(srcdir)/$(CONFIGURE) $(yes_silence:yes=--silent) $(configure_args)
diff --git a/test/.excludes-zjit/TestRubyOptimization.rb b/test/.excludes-zjit/TestRubyOptimization.rb
new file mode 100644
index 0000000000..5361ab02c7
--- /dev/null
+++ b/test/.excludes-zjit/TestRubyOptimization.rb
@@ -0,0 +1 @@
+exclude(:test_side_effect_in_popped_splat, 'Test fails with ZJIT due to locals invalidation')
diff --git a/test/json/ractor_test.rb b/test/json/ractor_test.rb
index dda34c64c0..0ebdb0e91a 100644
--- a/test/json/ractor_test.rb
+++ b/test/json/ractor_test.rb
@@ -42,7 +42,7 @@ class JSONInRactorTest < Test::Unit::TestCase
else
puts "Expected:"
puts expected_json
- puts "Acutual:"
+ puts "Actual:"
puts actual_json
puts
exit 1
diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb
index 5fc9ea508c..7aba333e92 100644
--- a/test/ruby/test_gc.rb
+++ b/test/ruby/test_gc.rb
@@ -447,7 +447,7 @@ class TestGc < Test::Unit::TestCase
end
def test_singleton_method_added
- assert_in_out_err([], <<-EOS, [], [], "[ruby-dev:44436]")
+ assert_in_out_err([], <<-EOS, [], [], "[ruby-dev:44436]", timeout: 30)
class BasicObject
undef singleton_method_added
def singleton_method_added(mid)
diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb
index dbf041a732..576a5f6064 100644
--- a/test/ruby/test_hash.rb
+++ b/test/ruby/test_hash.rb
@@ -880,21 +880,20 @@ class TestHash < Test::Unit::TestCase
assert_equal(quote1, eval(quote1).inspect)
assert_equal(quote2, eval(quote2).inspect)
assert_equal(quote3, eval(quote3).inspect)
- begin
- verbose_bak, $VERBOSE = $VERBOSE, nil
- enc = Encoding.default_external
- Encoding.default_external = Encoding::ASCII
+
+ EnvUtil.with_default_external(Encoding::ASCII) do
utf8_ascii_hash = '{"\\u3042": 1}'
assert_equal(eval(utf8_ascii_hash).inspect, utf8_ascii_hash)
- Encoding.default_external = Encoding::UTF_8
+ end
+
+ EnvUtil.with_default_external(Encoding::UTF_8) do
utf8_hash = "{\u3042: 1}"
assert_equal(eval(utf8_hash).inspect, utf8_hash)
- Encoding.default_external = Encoding::Windows_31J
+ end
+
+ EnvUtil.with_default_external(Encoding::Windows_31J) do
sjis_hash = "{\x87]: 1}".force_encoding('sjis')
assert_equal(eval(sjis_hash).inspect, sjis_hash)
- ensure
- Encoding.default_external = enc
- $VERBOSE = verbose_bak
end
end
diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb
index 4563308fa2..1e3e0e53b1 100644
--- a/test/ruby/test_keyword.rb
+++ b/test/ruby/test_keyword.rb
@@ -4033,7 +4033,7 @@ class TestKeywordArguments < Test::Unit::TestCase
tap { m }
GC.start
tap { m }
- }, bug8964
+ }, bug8964, timeout: 30
assert_normal_exit %q{
prc = Proc.new {|a: []|}
GC.stress = true
diff --git a/test/ruby/test_m17n.rb b/test/ruby/test_m17n.rb
index b0e2e9f849..9f7a3c7f4b 100644
--- a/test/ruby/test_m17n.rb
+++ b/test/ruby/test_m17n.rb
@@ -186,33 +186,35 @@ class TestM17N < Test::Unit::TestCase
end
def test_string_inspect_encoding
- EnvUtil.suppress_warning do
- begin
- orig_int = Encoding.default_internal
- orig_ext = Encoding.default_external
- Encoding.default_internal = nil
- [Encoding::UTF_8, Encoding::EUC_JP, Encoding::Windows_31J, Encoding::GB18030].
- each do |e|
- Encoding.default_external = e
- str = "\x81\x30\x81\x30".force_encoding('GB18030')
- assert_equal(Encoding::GB18030 == e ? %{"#{str}"} : '"\x{81308130}"', str.inspect)
- str = e("\xa1\x8f\xa1\xa1")
- expected = "\"\\xA1\x8F\xA1\xA1\"".force_encoding("EUC-JP")
- assert_equal(Encoding::EUC_JP == e ? expected : "\"\\xA1\\x{8FA1A1}\"", str.inspect)
- str = s("\x81@")
- assert_equal(Encoding::Windows_31J == e ? %{"#{str}"} : '"\x{8140}"', str.inspect)
- str = "\u3042\u{10FFFD}"
- assert_equal(Encoding::UTF_8 == e ? %{"#{str}"} : '"\u3042\u{10FFFD}"', str.inspect)
- end
- Encoding.default_external = Encoding::UTF_8
- [Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE,
- Encoding::UTF8_SOFTBANK].each do |e|
- str = "abc".encode(e)
- assert_equal('"abc"', str.inspect)
- end
- ensure
- Encoding.default_internal = orig_int
- Encoding.default_external = orig_ext
+ [
+ Encoding::UTF_8,
+ Encoding::EUC_JP,
+ Encoding::Windows_31J,
+ Encoding::GB18030,
+ ].each do |e|
+ EnvUtil.with_default_external(e) do
+ str = "\x81\x30\x81\x30".force_encoding('GB18030')
+ assert_equal(Encoding::GB18030 == e ? %{"#{str}"} : '"\x{81308130}"', str.inspect)
+ str = e("\xa1\x8f\xa1\xa1")
+ expected = "\"\\xA1\x8F\xA1\xA1\"".force_encoding("EUC-JP")
+ assert_equal(Encoding::EUC_JP == e ? expected : "\"\\xA1\\x{8FA1A1}\"", str.inspect)
+ str = s("\x81@")
+ assert_equal(Encoding::Windows_31J == e ? %{"#{str}"} : '"\x{8140}"', str.inspect)
+ str = "\u3042\u{10FFFD}"
+ assert_equal(Encoding::UTF_8 == e ? %{"#{str}"} : '"\u3042\u{10FFFD}"', str.inspect)
+ end
+ end
+
+ EnvUtil.with_default_external(Encoding::UTF_8) do
+ [
+ Encoding::UTF_16BE,
+ Encoding::UTF_16LE,
+ Encoding::UTF_32BE,
+ Encoding::UTF_32LE,
+ Encoding::UTF8_SOFTBANK
+ ].each do |e|
+ str = "abc".encode(e)
+ assert_equal('"abc"', str.inspect)
end
end
end
@@ -246,59 +248,43 @@ class TestM17N < Test::Unit::TestCase
end
def test_object_utf16_32_inspect
- EnvUtil.suppress_warning do
- begin
- orig_int = Encoding.default_internal
- orig_ext = Encoding.default_external
- Encoding.default_internal = nil
- Encoding.default_external = Encoding::UTF_8
- o = Object.new
- [Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE].each do |e|
- o.instance_eval "undef inspect;def inspect;'abc'.encode('#{e}');end"
- assert_equal '[abc]', [o].inspect
- end
- ensure
- Encoding.default_internal = orig_int
- Encoding.default_external = orig_ext
+ EnvUtil.with_default_external(Encoding::UTF_8) do
+ o = Object.new
+ [Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE].each do |e|
+ o.instance_eval "undef inspect;def inspect;'abc'.encode('#{e}');end"
+ assert_equal '[abc]', [o].inspect
end
end
end
def test_object_inspect_external
- orig_v, $VERBOSE = $VERBOSE, false
- orig_int, Encoding.default_internal = Encoding.default_internal, nil
- orig_ext = Encoding.default_external
-
omit "https://bugs.ruby-lang.org/issues/18338"
o = Object.new
- Encoding.default_external = Encoding::UTF_16BE
- def o.inspect
- "abc"
- end
- assert_nothing_raised(Encoding::CompatibilityError) { [o].inspect }
+ EnvUtil.with_default_external(Encoding::UTF_16BE) do
+ def o.inspect
+ "abc"
+ end
+ assert_nothing_raised(Encoding::CompatibilityError) { [o].inspect }
- def o.inspect
- "abc".encode(Encoding.default_external)
+ def o.inspect
+ "abc".encode(Encoding.default_external)
+ end
+ assert_equal '[abc]', [o].inspect
end
- assert_equal '[abc]', [o].inspect
-
- Encoding.default_external = Encoding::US_ASCII
- def o.inspect
- "\u3042"
- end
- assert_equal '[\u3042]', [o].inspect
+ EnvUtil.with_default_external(Encoding::US_ASCII) do
+ def o.inspect
+ "\u3042"
+ end
+ assert_equal '[\u3042]', [o].inspect
- def o.inspect
- "\x82\xa0".force_encoding(Encoding::Windows_31J)
+ def o.inspect
+ "\x82\xa0".force_encoding(Encoding::Windows_31J)
+ end
+ assert_equal '[\x{82A0}]', [o].inspect
end
- assert_equal '[\x{82A0}]', [o].inspect
- ensure
- Encoding.default_internal = orig_int
- Encoding.default_external = orig_ext
- $VERBOSE = orig_v
end
def test_str_dump
diff --git a/test/ruby/test_shapes.rb b/test/ruby/test_shapes.rb
index 77bba6421b..aa488e0421 100644
--- a/test/ruby/test_shapes.rb
+++ b/test/ruby/test_shapes.rb
@@ -1032,12 +1032,23 @@ class TestShapes < Test::Unit::TestCase
assert_shape_equal(RubyVM::Shape.root_shape, RubyVM::Shape.of([]))
end
- def test_true_has_special_const_shape_id
- assert_equal(RubyVM::Shape::SPECIAL_CONST_SHAPE_ID, RubyVM::Shape.of(true).id)
- end
-
- def test_nil_has_special_const_shape_id
- assert_equal(RubyVM::Shape::SPECIAL_CONST_SHAPE_ID, RubyVM::Shape.of(nil).id)
+ def test_raise_on_special_consts
+ assert_raise ArgumentError do
+ RubyVM::Shape.of(true)
+ end
+ assert_raise ArgumentError do
+ RubyVM::Shape.of(false)
+ end
+ assert_raise ArgumentError do
+ RubyVM::Shape.of(nil)
+ end
+ assert_raise ArgumentError do
+ RubyVM::Shape.of(0)
+ end
+ # 32-bit platforms don't have flonums or static symbols as special
+ # constants
+ # TODO(max): Add ArgumentError tests for symbol and flonum, skipping if
+ # RUBY_PLATFORM =~ /i686/
end
def test_root_shape_transition_to_special_const_on_frozen
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index c7e4b0c1ec..1e0f31ba7c 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -3251,18 +3251,12 @@ CODE
assert_equal('"\\u3042\\u3044\\u3046"', S("\u3042\u3044\u3046".encode(e)).inspect)
assert_equal('"ab\\"c"', S("ab\"c".encode(e)).inspect, bug4081)
end
- begin
- verbose, $VERBOSE = $VERBOSE, nil
- ext = Encoding.default_external
- Encoding.default_external = "us-ascii"
- $VERBOSE = verbose
+
+ EnvUtil.with_default_external(Encoding::US_ASCII) do
i = S("abc\"\\".force_encoding("utf-8")).inspect
- ensure
- $VERBOSE = nil
- Encoding.default_external = ext
- $VERBOSE = verbose
+
+ assert_equal('"abc\\"\\\\"', i, bug4081)
end
- assert_equal('"abc\\"\\\\"', i, bug4081)
end
def test_dummy_inspect
diff --git a/test/ruby/test_zjit.rb b/test/ruby/test_zjit.rb
index d30af737c3..b5b5a69847 100644
--- a/test/ruby/test_zjit.rb
+++ b/test/ruby/test_zjit.rb
@@ -509,6 +509,116 @@ class TestZJIT < Test::Unit::TestCase
}, insns: [:opt_ge], call_threshold: 2
end
+ def test_new_hash_empty
+ assert_compiles '{}', %q{
+ def test = {}
+ test
+ }, insns: [:newhash]
+ end
+
+ def test_new_hash_nonempty
+ assert_compiles '{"key" => "value", 42 => 100}', %q{
+ def test
+ key = "key"
+ value = "value"
+ num = 42
+ result = 100
+ {key => value, num => result}
+ end
+ test
+ }, insns: [:newhash]
+ end
+
+ def test_new_hash_single_key_value
+ assert_compiles '{"key" => "value"}', %q{
+ def test = {"key" => "value"}
+ test
+ }, insns: [:newhash]
+ end
+
+ def test_new_hash_with_computation
+ assert_compiles '{"sum" => 5, "product" => 6}', %q{
+ def test(a, b)
+ {"sum" => a + b, "product" => a * b}
+ end
+ test(2, 3)
+ }, insns: [:newhash]
+ end
+
+ def test_new_hash_with_user_defined_hash_method
+ assert_runs 'true', %q{
+ class CustomKey
+ attr_reader :val
+
+ def initialize(val)
+ @val = val
+ end
+
+ def hash
+ @val.hash
+ end
+
+ def eql?(other)
+ other.is_a?(CustomKey) && @val == other.val
+ end
+ end
+
+ def test
+ key = CustomKey.new("key")
+ hash = {key => "value"}
+ hash[key] == "value"
+ end
+ test
+ }
+ end
+
+ def test_new_hash_with_user_hash_method_exception
+ assert_runs 'RuntimeError', %q{
+ class BadKey
+ def hash
+ raise "Hash method failed!"
+ end
+ end
+
+ def test
+ key = BadKey.new
+ {key => "value"}
+ end
+
+ begin
+ test
+ rescue => e
+ e.class
+ end
+ }
+ end
+
+ def test_new_hash_with_user_eql_method_exception
+ assert_runs 'RuntimeError', %q{
+ class BadKey
+ def hash
+ 42
+ end
+
+ def eql?(other)
+ raise "Eql method failed!"
+ end
+ end
+
+ def test
+ key1 = BadKey.new
+ key2 = BadKey.new
+ {key1 => "value1", key2 => "value2"}
+ end
+
+ begin
+ test
+ rescue => e
+ e.class
+ end
+ }
+ end
+
def test_opt_hash_freeze
assert_compiles '{}', <<~RUBY, insns: [:opt_hash_freeze]
def test = {}.freeze
@@ -1135,6 +1245,14 @@ class TestZJIT < Test::Unit::TestCase
}, insns: [:defined]
end
+ def test_defined_with_method_call
+ assert_compiles '["method", nil]', %q{
+ def test = return defined?("x".reverse(1)), defined?("x".reverse(1).reverse)
+
+ test
+ }, insns: [:defined]
+ end
+
def test_defined_yield
assert_compiles "nil", "defined?(yield)"
assert_compiles '[nil, nil, "yield"]', %q{
@@ -1729,6 +1847,29 @@ class TestZJIT < Test::Unit::TestCase
}, insns: [:concatstrings]
end
+ def test_regexp_interpolation
+ assert_compiles '/123/', %q{
+ def test = /#{1}#{2}#{3}/
+
+ test
+ }, insns: [:toregexp]
+ end
+
+ def test_new_range_non_leaf
+ assert_compiles '(0/1)..1', %q{
+ def jit_entry(v) = make_range_then_exit(v)
+
+ def make_range_then_exit(v)
+ range = (v..1)
+ super rescue range # TODO(alan): replace super with side-exit intrinsic
+ end
+
+ jit_entry(0) # profile
+ jit_entry(0) # compile
+ jit_entry(0/1r) # run without stub
+ }, call_threshold: 2
+ end
+
private
# Assert that every method call in `test_script` can be compiled by ZJIT
diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb
index 2f4abff1e8..51c99a1bc5 100644
--- a/test/rubygems/helper.rb
+++ b/test/rubygems/helper.rb
@@ -724,7 +724,7 @@ class Gem::TestCase < Test::Unit::TestCase
#
# Use this with #write_file to build an installed gem.
- def quick_gem(name, version="2")
+ def quick_gem(name, version = "2")
require "rubygems/specification"
spec = Gem::Specification.new do |s|
@@ -1033,7 +1033,7 @@ Also, a list:
# Add +spec+ to +@fetcher+ serving the data in the file +path+.
# +repo+ indicates which repo to make +spec+ appear to be in.
- def add_to_fetcher(spec, path=nil, repo=@gem_repo)
+ def add_to_fetcher(spec, path = nil, repo = @gem_repo)
path ||= spec.cache_file
@fetcher.data["#{@gem_repo}gems/#{spec.file_name}"] = read_binary(path)
end
@@ -1206,7 +1206,7 @@ Also, a list:
##
# Allows the proper version of +rake+ to be used for the test.
- def build_rake_in(good=true)
+ def build_rake_in(good = true)
gem_ruby = Gem.ruby
Gem.ruby = self.class.rubybin
env_rake = ENV["rake"]
diff --git a/test/rubygems/installer_test_case.rb b/test/rubygems/installer_test_case.rb
index 7a71984320..ded205c5f5 100644
--- a/test/rubygems/installer_test_case.rb
+++ b/test/rubygems/installer_test_case.rb
@@ -215,7 +215,7 @@ class Gem::InstallerTestCase < Gem::TestCase
##
# Creates an installer for +spec+ that will install into +gem_home+.
- def util_installer(spec, gem_home, force=true)
+ def util_installer(spec, gem_home, force = true)
Gem::Installer.at(spec.cache_file,
install_dir: gem_home,
force: force)
diff --git a/test/rubygems/mock_gem_ui.rb b/test/rubygems/mock_gem_ui.rb
index 218d4b6965..fb804c5555 100644
--- a/test/rubygems/mock_gem_ui.rb
+++ b/test/rubygems/mock_gem_ui.rb
@@ -77,7 +77,7 @@ class Gem::MockGemUi < Gem::StreamUI
@terminated
end
- def terminate_interaction(status=0)
+ def terminate_interaction(status = 0)
@terminated = true
raise TermError, status if status != 0
diff --git a/test/rubygems/test_gem_ext_ext_conf_builder.rb b/test/rubygems/test_gem_ext_ext_conf_builder.rb
index 218c6f3d5e..bc383e5540 100644
--- a/test/rubygems/test_gem_ext_ext_conf_builder.rb
+++ b/test/rubygems/test_gem_ext_ext_conf_builder.rb
@@ -15,15 +15,12 @@ class TestGemExtExtConfBuilder < Gem::TestCase
end
def test_class_build
- if Gem.java_platform?
- pend("failing on jruby")
- end
-
if vc_windows? && !nmake_found?
pend("test_class_build skipped - nmake not found")
end
File.open File.join(@ext, "extconf.rb"), "w" do |extconf|
+ extconf.puts "return if Gem.java_platform?"
extconf.puts "require 'mkmf'\ncreate_makefile 'foo'"
end
@@ -35,20 +32,22 @@ class TestGemExtExtConfBuilder < Gem::TestCase
assert_match(/^current directory:/, output[0])
assert_match(/^#{Regexp.quote(Gem.ruby)}.* extconf.rb/, output[1])
- assert_equal "creating Makefile\n", output[2]
- assert_match(/^current directory:/, output[3])
- assert_contains_make_command "clean", output[4]
- assert_contains_make_command "", output[7]
- assert_contains_make_command "install", output[10]
+
+ if Gem.java_platform?
+ assert_includes(output, "Skipping make for extconf.rb as no Makefile was found.")
+ else
+ assert_equal "creating Makefile\n", output[2]
+ assert_match(/^current directory:/, output[3])
+ assert_contains_make_command "clean", output[4]
+ assert_contains_make_command "", output[7]
+ assert_contains_make_command "install", output[10]
+ end
+
assert_empty Dir.glob(File.join(@ext, "siteconf*.rb"))
assert_empty Dir.glob(File.join(@ext, ".gem.*"))
end
def test_class_build_rbconfig_make_prog
- if Gem.java_platform?
- pend("failing on jruby")
- end
-
configure_args do
File.open File.join(@ext, "extconf.rb"), "w" do |extconf|
extconf.puts "require 'mkmf'\ncreate_makefile 'foo'"
@@ -72,10 +71,6 @@ class TestGemExtExtConfBuilder < Gem::TestCase
env_large_make = ENV.delete "MAKE"
ENV["MAKE"] = "anothermake"
- if Gem.java_platform?
- pend("failing on jruby")
- end
-
configure_args "" do
File.open File.join(@ext, "extconf.rb"), "w" do |extconf|
extconf.puts "require 'mkmf'\ncreate_makefile 'foo'"
@@ -206,11 +201,11 @@ end
end
def test_class_make_no_Makefile
- error = assert_raise Gem::InstallError do
+ error = assert_raise Gem::Ext::Builder::NoMakefileError do
Gem::Ext::ExtConfBuilder.make @ext, ["output"], @ext
end
- assert_equal "Makefile not found", error.message
+ assert_match(/No Makefile found/, error.message)
end
def configure_args(args = nil)
diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb
index ca858cfda5..5c1d89fad6 100644
--- a/test/rubygems/test_gem_remote_fetcher.rb
+++ b/test/rubygems/test_gem_remote_fetcher.rb
@@ -592,7 +592,7 @@ class TestGemRemoteFetcher < Gem::TestCase
end
end
- def assert_error(exception_class=Exception)
+ def assert_error(exception_class = Exception)
got_exception = false
begin
diff --git a/tool/make-snapshot b/tool/make-snapshot
index c7ccc468d4..2b9a5006e0 100755
--- a/tool/make-snapshot
+++ b/tool/make-snapshot
@@ -334,7 +334,7 @@ def package(vcs, rev, destdir, tmp = nil)
FileUtils.rm(file, verbose: $VERBOSE)
end
- status = IO.read(File.dirname(__FILE__) + "/prereq.status")
+ status = File.read(File.dirname(__FILE__) + "/prereq.status")
Dir.chdir(tmp) if tmp
if !File.directory?(v)
@@ -346,10 +346,10 @@ def package(vcs, rev, destdir, tmp = nil)
File.open("#{v}/revision.h", "wb") {|f|
f.puts vcs.revision_header(revision, modified)
}
- version ||= (versionhdr = IO.read("#{v}/version.h"))[RUBY_VERSION_PATTERN, 1]
+ version ||= (versionhdr = File.read("#{v}/version.h"))[RUBY_VERSION_PATTERN, 1]
version ||=
begin
- include_ruby_versionhdr = IO.read("#{v}/include/ruby/version.h")
+ include_ruby_versionhdr = File.read("#{v}/include/ruby/version.h")
api_major_version = include_ruby_versionhdr[/^\#define\s+RUBY_API_VERSION_MAJOR\s+([\d.]+)/, 1]
api_minor_version = include_ruby_versionhdr[/^\#define\s+RUBY_API_VERSION_MINOR\s+([\d.]+)/, 1]
version_teeny = versionhdr[/^\#define\s+RUBY_VERSION_TEENY\s+(\d+)/, 1]
@@ -358,14 +358,14 @@ def package(vcs, rev, destdir, tmp = nil)
version or return
if patchlevel
unless tag.empty?
- versionhdr ||= IO.read("#{v}/version.h")
+ versionhdr ||= File.read("#{v}/version.h")
patchlevel = versionhdr[/^\#define\s+RUBY_PATCHLEVEL\s+(\d+)/, 1]
tag = (patchlevel ? "p#{patchlevel}" : vcs.revision_name(revision))
end
elsif prerelease
- versionhdr ||= IO.read("#{v}/version.h")
+ versionhdr ||= File.read("#{v}/version.h")
versionhdr.sub!(/^\#\s*define\s+RUBY_PATCHLEVEL_STR\s+"\K.+?(?=")/, tag) or raise "no match of RUBY_PATCHLEVEL_STR to replace"
- IO.write("#{v}/version.h", versionhdr)
+ File.write("#{v}/version.h", versionhdr)
else
tag ||= vcs.revision_name(revision)
end
@@ -430,7 +430,7 @@ def package(vcs, rev, destdir, tmp = nil)
puts "cross.rb:", File.read("cross.rb").gsub(/^/, "> "), "" if $VERBOSE
unless File.exist?("configure")
print "creating configure..."
- unless system([ENV["AUTOCONF"]]*2)
+ unless system(File.exist?(gen = "./autogen.sh") ? gen : [ENV["AUTOCONF"]]*2)
puts $colorize.fail(" failed")
return
end
@@ -439,11 +439,11 @@ def package(vcs, rev, destdir, tmp = nil)
clean.add("autom4te.cache")
clean.add("enc/unicode/data")
print "creating prerequisites..."
- if File.file?("common.mk") && /^prereq/ =~ commonmk = IO.read("common.mk")
+ if File.file?("common.mk") && /^prereq/ =~ commonmk = File.read("common.mk")
puts
extout = clean.add('tmp')
begin
- status = IO.read("tool/prereq.status")
+ status = File.read("tool/prereq.status")
rescue Errno::ENOENT
# use fallback file
end
@@ -456,7 +456,7 @@ def package(vcs, rev, destdir, tmp = nil)
File.binwrite("#{defaults}/ruby.rb", "")
miniruby = ENV['MINIRUBY'] + " -I. -I#{extout} -rcross"
baseruby = ENV["BASERUBY"]
- mk = (IO.read("template/Makefile.in") rescue IO.read("Makefile.in")).
+ mk = (File.read("template/Makefile.in") rescue File.read("Makefile.in")).
gsub(/^@.*\n/, '')
vars = {
"EXTOUT"=>extout,
@@ -480,6 +480,13 @@ def package(vcs, rev, destdir, tmp = nil)
vars["UNICODE_VERSION"] = $unicode_version if $unicode_version
args = vars.dup
mk.gsub!(/@([A-Za-z_]\w*)@/) {args.delete($1); vars[$1] || ENV[$1]}
+ commonmk.gsub!(/^!(?:include \$\(srcdir\)\/(.*))?/) do
+ if inc = $1 and File.exist?(inc)
+ File.binread(inc).gsub(/^!/, '# !')
+ else
+ "#"
+ end
+ end
mk << commonmk.gsub(/\{\$([^(){}]*)[^{}]*\}/, "").sub(/^revision\.tmp::$/, '\& Makefile')
mk << <<-'APPEND'
diff --git a/tool/prereq.status b/tool/prereq.status
index 6de00c8a92..6aca615e90 100644
--- a/tool/prereq.status
+++ b/tool/prereq.status
@@ -41,4 +41,5 @@ s,@rubylibprefix@,,g
s,@srcdir@,.,g
s/@[A-Za-z][A-Za-z0-9_]*@//g
-s/{\$([A-Za-z]*)}//g
+s/{\$([^(){}]*)}//g
+s/^!/#!/
diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb
index 5794edaa83..cb4e0af50b 100755
--- a/tool/sync_default_gems.rb
+++ b/tool/sync_default_gems.rb
@@ -330,6 +330,7 @@ module SyncDefaultGems
rm_rf("test/prism/snapshots")
rm("prism/extconf.rb")
+ `git checkout prism/srcs.mk*`
when "resolv"
rm_rf(%w[lib/resolv.* ext/win32/resolv test/resolv ext/win32/lib/win32/resolv.rb])
cp_r("#{upstream}/lib/resolv.rb", "lib")
diff --git a/tool/update-deps b/tool/update-deps
index 375986a915..c927d2483e 100755
--- a/tool/update-deps
+++ b/tool/update-deps
@@ -96,6 +96,15 @@ result.each {|k,v|
# They can be referenced as $(top_srcdir)/filename.
# % ruby -e 'def g(d) Dir.chdir(d) { Dir["**/*.{c,h,inc,dmyh}"] } end; puts((g("repo_source_dir_after_build") - g("repo_source_dir_original")).sort)'
FILES_IN_SOURCE_DIRECTORY = %w[
+ prism/api_node.c
+ prism/ast.h
+ prism/diagnostic.c
+ prism/diagnostic.h
+ prism/node.c
+ prism/prettyprint.c
+ prism/serialize.c
+ prism/token_type.c
+ prism/version.h
]
# Files built in the build directory (except extconf.h).
@@ -157,16 +166,6 @@ FILES_NEED_VPATH = %w[
enc/trans/single_byte.c
enc/trans/utf8_mac.c
enc/trans/utf_16_32.c
-
- prism/api_node.c
- prism/ast.h
- prism/diagnostic.c
- prism/diagnostic.h
- prism/node.c
- prism/prettyprint.c
- prism/serialize.c
- prism/token_type.c
- prism/version.h
]
# Multiple files with same filename.
diff --git a/vcpkg.json b/vcpkg.json
index 16415dece1..efd356e814 100644
--- a/vcpkg.json
+++ b/vcpkg.json
@@ -7,5 +7,5 @@
"openssl",
"zlib"
],
- "builtin-baseline": "65be7019941e1401e02daaba0738cab2c8a4a355"
-}
+ "builtin-baseline": "dd3097e305afa53f7b4312371f62058d2e665320"
+} \ No newline at end of file
diff --git a/vm_callinfo.h b/vm_callinfo.h
index 79ccbfa7ab..e52b2f9b1a 100644
--- a/vm_callinfo.h
+++ b/vm_callinfo.h
@@ -613,7 +613,7 @@ static inline bool
vm_cc_check_cme(const struct rb_callcache *cc, const rb_callable_method_entry_t *cme)
{
bool valid;
- RB_VM_LOCKING() {
+ RB_VM_LOCKING_NO_BARRIER() {
valid = vm_cc_cme(cc) == cme ||
(cme->def->iseq_overload && vm_cc_cme(cc) == rb_vm_lookup_overloaded_cme(cme));
}
diff --git a/vm_method.c b/vm_method.c
index c1793c102c..73a431ce93 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -428,6 +428,8 @@ clear_method_cache_by_id_in_class(VALUE klass, ID mid)
if (rb_objspace_garbage_object_p(klass)) return;
RB_VM_LOCKING() {
+ rb_vm_barrier();
+
if (LIKELY(RCLASS_SUBCLASSES_FIRST(klass) == NULL)) {
// no subclasses
// check only current class
@@ -510,7 +512,7 @@ clear_method_cache_by_id_in_class(VALUE klass, ID mid)
}
rb_gccct_clear_table(Qnil);
-}
+ }
}
static void
@@ -1752,6 +1754,8 @@ cached_callable_method_entry(VALUE klass, ID mid)
return ccs->cme;
}
else {
+ rb_vm_barrier();
+
rb_managed_id_table_delete(cc_tbl, mid);
rb_vm_ccs_invalidate_and_free(ccs);
}
diff --git a/win32/Makefile.sub b/win32/Makefile.sub
index 664d54e5ff..1bdef106b3 100644
--- a/win32/Makefile.sub
+++ b/win32/Makefile.sub
@@ -570,7 +570,6 @@ ACTIONS_ENDGROUP = @::
ABI_VERSION_HDR = $(hdrdir)/ruby/internal/abi.h
!include $(srcdir)/common.mk
-!include $(srcdir)/depend
!ifdef SCRIPTPROGRAMS
!else if [echo>scriptbin.mk SCRIPTPROGRAMS = \]
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index 9644b948d7..9c06010527 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -3104,7 +3104,7 @@ fn gen_set_ivar(
// Get the iv index
let shape_too_complex = comptime_receiver.shape_too_complex();
- let ivar_index = if !shape_too_complex {
+ let ivar_index = if !comptime_receiver.special_const_p() && !shape_too_complex {
let shape_id = comptime_receiver.shape_id_of();
let mut ivar_index: u16 = 0;
if unsafe { rb_shape_get_iv_index(shape_id, ivar_name, &mut ivar_index) } {
@@ -3369,7 +3369,7 @@ fn gen_definedivar(
// Specialize base on compile time values
let comptime_receiver = jit.peek_at_self();
- if comptime_receiver.shape_too_complex() || asm.ctx.get_chain_depth() >= GET_IVAR_MAX_DEPTH {
+ if comptime_receiver.special_const_p() || comptime_receiver.shape_too_complex() || asm.ctx.get_chain_depth() >= GET_IVAR_MAX_DEPTH {
// Fall back to calling rb_ivar_defined
// Save the PC and SP because the callee may allocate
@@ -4315,11 +4315,11 @@ fn gen_opt_ary_freeze(
return None;
}
- let str = jit.get_arg(0);
+ let ary = jit.get_arg(0);
// Push the return value onto the stack
let stack_ret = asm.stack_push(Type::CArray);
- asm.mov(stack_ret, str.into());
+ asm.mov(stack_ret, ary.into());
Some(KeepCompiling)
}
@@ -4332,11 +4332,11 @@ fn gen_opt_hash_freeze(
return None;
}
- let str = jit.get_arg(0);
+ let hash = jit.get_arg(0);
// Push the return value onto the stack
let stack_ret = asm.stack_push(Type::CHash);
- asm.mov(stack_ret, str.into());
+ asm.mov(stack_ret, hash.into());
Some(KeepCompiling)
}
diff --git a/zjit/bindgen/src/main.rs b/zjit/bindgen/src/main.rs
index 77299c2657..59b7f9737e 100644
--- a/zjit/bindgen/src/main.rs
+++ b/zjit/bindgen/src/main.rs
@@ -259,6 +259,13 @@ fn main() {
// From internal/re.h
.allowlist_function("rb_reg_new_ary")
+ .allowlist_var("ARG_ENCODING_FIXED")
+ .allowlist_var("ARG_ENCODING_NONE")
+
+ // From include/ruby/onigmo.h
+ .allowlist_var("ONIG_OPTION_IGNORECASE")
+ .allowlist_var("ONIG_OPTION_EXTEND")
+ .allowlist_var("ONIG_OPTION_MULTILINE")
// `ruby_value_type` is a C enum and this stops it from
// prefixing all the members with the name of the type
diff --git a/zjit/src/backend/lir.rs b/zjit/src/backend/lir.rs
index 54bef9d925..be5bda052d 100644
--- a/zjit/src/backend/lir.rs
+++ b/zjit/src/backend/lir.rs
@@ -147,26 +147,15 @@ impl Opnd
}
}
- /// Return Some(Opnd) with a given num_bits if self has num_bits.
- /// None if self doesn't have a num_bits field.
- pub fn try_num_bits(&self, num_bits: u8) -> Option<Opnd> {
- assert!(num_bits == 8 || num_bits == 16 || num_bits == 32 || num_bits == 64);
- match *self {
- Opnd::Reg(reg) => Some(Opnd::Reg(reg.with_num_bits(num_bits))),
- Opnd::Mem(Mem { base, disp, .. }) => Some(Opnd::Mem(Mem { base, disp, num_bits })),
- Opnd::VReg { idx, .. } => Some(Opnd::VReg { idx, num_bits }),
- _ => None,
- }
- }
-
- /// Return Opnd with a given num_bits if self has num_bits.
- /// Panic otherwise. This should be used only when you know which Opnd self is.
+ /// Return Opnd with a given num_bits if self has num_bits. Panic otherwise.
#[track_caller]
pub fn with_num_bits(&self, num_bits: u8) -> Opnd {
- if let Some(opnd) = self.try_num_bits(num_bits) {
- opnd
- } else {
- unreachable!("with_num_bits should not be used on: {self:?}");
+ assert!(num_bits == 8 || num_bits == 16 || num_bits == 32 || num_bits == 64);
+ match *self {
+ Opnd::Reg(reg) => Opnd::Reg(reg.with_num_bits(num_bits)),
+ Opnd::Mem(Mem { base, disp, .. }) => Opnd::Mem(Mem { base, disp, num_bits }),
+ Opnd::VReg { idx, .. } => Opnd::VReg { idx, num_bits },
+ _ => unreachable!("with_num_bits should not be used for: {self:?}"),
}
}
@@ -1684,6 +1673,7 @@ impl Assembler {
}
pub fn cpop_into(&mut self, opnd: Opnd) {
+ assert!(matches!(opnd, Opnd::Reg(_)), "Destination of cpop_into must be a register, got: {opnd:?}");
self.push_insn(Insn::CPopInto(opnd));
}
@@ -1831,6 +1821,7 @@ impl Assembler {
}
pub fn lea_into(&mut self, out: Opnd, opnd: Opnd) {
+ assert!(matches!(out, Opnd::Reg(_)), "Destination of lea_into must be a register, got: {out:?}");
self.push_insn(Insn::Lea { opnd, out });
}
@@ -1856,7 +1847,7 @@ impl Assembler {
}
pub fn load_into(&mut self, dest: Opnd, opnd: Opnd) {
- assert!(matches!(dest, Opnd::Reg(_) | Opnd::VReg{..}), "Destination of load_into must be a register");
+ assert!(matches!(dest, Opnd::Reg(_)), "Destination of load_into must be a register, got: {dest:?}");
match (dest, opnd) {
(Opnd::Reg(dest), Opnd::Reg(opnd)) if dest == opnd => {}, // skip if noop
_ => self.push_insn(Insn::LoadInto { dest, opnd }),
@@ -1882,6 +1873,7 @@ impl Assembler {
}
pub fn mov(&mut self, dest: Opnd, src: Opnd) {
+ assert!(!matches!(dest, Opnd::VReg { .. }), "Destination of mov must not be Opnd::VReg, got: {dest:?}");
self.push_insn(Insn::Mov { dest, src });
}
@@ -1919,6 +1911,7 @@ impl Assembler {
}
pub fn store(&mut self, dest: Opnd, src: Opnd) {
+ assert!(!matches!(dest, Opnd::VReg { .. }), "Destination of store must not be Opnd::VReg, got: {dest:?}");
self.push_insn(Insn::Store { dest, src });
}
diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs
index a58950ab9a..db56db0927 100644
--- a/zjit/src/codegen.rs
+++ b/zjit/src/codegen.rs
@@ -1,6 +1,6 @@
-use std::cell::Cell;
+use std::cell::{Cell, RefCell};
use std::rc::Rc;
-use std::ffi::{c_int, c_void};
+use std::ffi::{c_int, c_long, c_void};
use crate::asm::Label;
use crate::backend::current::{Reg, ALLOC_REGS};
@@ -27,7 +27,7 @@ struct JITState {
labels: Vec<Option<Target>>,
/// ISEQ calls that need to be compiled later
- iseq_calls: Vec<Rc<IseqCall>>,
+ iseq_calls: Vec<Rc<RefCell<IseqCall>>>,
/// The number of bytes allocated for basic block arguments spilled onto the C stack
c_stack_slots: usize,
@@ -46,12 +46,8 @@ impl JITState {
}
/// Retrieve the output of a given instruction that has been compiled
- fn get_opnd(&self, insn_id: InsnId) -> Option<lir::Opnd> {
- let opnd = self.opnds[insn_id.0];
- if opnd.is_none() {
- debug!("Failed to get_opnd({insn_id})");
- }
- opnd
+ fn get_opnd(&self, insn_id: InsnId) -> lir::Opnd {
+ self.opnds[insn_id.0].expect(&format!("Failed to get_opnd({insn_id})"))
}
/// Find or create a label for a given BlockId
@@ -130,13 +126,14 @@ fn gen_iseq_entry_point_body(cb: &mut CodeBlock, iseq: IseqPtr) -> Option<CodePt
};
// Stub callee ISEQs for JIT-to-JIT calls
- for iseq_call in jit.iseq_calls.into_iter() {
+ for iseq_call in jit.iseq_calls.iter() {
gen_iseq_call(cb, iseq, iseq_call)?;
}
// Remember the block address to reuse it later
let payload = get_or_create_iseq_payload(iseq);
payload.status = IseqStatus::Compiled(start_ptr);
+ payload.iseq_calls.extend(jit.iseq_calls);
append_gc_offsets(iseq, &gc_offsets);
// Return a JIT code address
@@ -144,19 +141,20 @@ fn gen_iseq_entry_point_body(cb: &mut CodeBlock, iseq: IseqPtr) -> Option<CodePt
}
/// Stub a branch for a JIT-to-JIT call
-fn gen_iseq_call(cb: &mut CodeBlock, caller_iseq: IseqPtr, iseq_call: Rc<IseqCall>) -> Option<()> {
+fn gen_iseq_call(cb: &mut CodeBlock, caller_iseq: IseqPtr, iseq_call: &Rc<RefCell<IseqCall>>) -> Option<()> {
// Compile a function stub
let Some(stub_ptr) = gen_function_stub(cb, iseq_call.clone()) else {
// Failed to compile the stub. Bail out of compiling the caller ISEQ.
debug!("Failed to compile iseq: could not compile stub: {} -> {}",
- iseq_get_location(caller_iseq, 0), iseq_get_location(iseq_call.iseq, 0));
+ iseq_get_location(caller_iseq, 0), iseq_get_location(iseq_call.borrow().iseq, 0));
return None;
};
// Update the JIT-to-JIT call to call the stub
let stub_addr = stub_ptr.raw_ptr(cb);
- iseq_call.regenerate(cb, |asm| {
- asm_comment!(asm, "call function stub: {}", iseq_get_location(iseq_call.iseq, 0));
+ let iseq = iseq_call.borrow().iseq;
+ iseq_call.borrow_mut().regenerate(cb, |asm| {
+ asm_comment!(asm, "call function stub: {}", iseq_get_location(iseq, 0));
asm.ccall(stub_addr, vec![]);
});
Some(())
@@ -209,7 +207,7 @@ fn gen_entry(cb: &mut CodeBlock, iseq: IseqPtr, function: &Function, function_pt
}
/// Compile an ISEQ into machine code
-fn gen_iseq(cb: &mut CodeBlock, iseq: IseqPtr) -> Option<(CodePtr, Vec<Rc<IseqCall>>)> {
+fn gen_iseq(cb: &mut CodeBlock, iseq: IseqPtr) -> Option<(CodePtr, Vec<Rc<RefCell<IseqCall>>>)> {
// Return an existing pointer if it's already compiled
let payload = get_or_create_iseq_payload(iseq);
match payload.status {
@@ -231,6 +229,7 @@ fn gen_iseq(cb: &mut CodeBlock, iseq: IseqPtr) -> Option<(CodePtr, Vec<Rc<IseqCa
let result = gen_function(cb, iseq, &function);
if let Some((start_ptr, gc_offsets, jit)) = result {
payload.status = IseqStatus::Compiled(start_ptr);
+ payload.iseq_calls.extend(jit.iseq_calls.clone());
append_gc_offsets(iseq, &gc_offsets);
Some((start_ptr, jit.iseq_calls))
} else {
@@ -313,18 +312,24 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
// Convert InsnId to lir::Opnd
macro_rules! opnd {
($insn_id:ident) => {
- jit.get_opnd($insn_id.clone())?
+ jit.get_opnd($insn_id.clone())
};
}
macro_rules! opnds {
($insn_ids:ident) => {
{
- Option::from_iter($insn_ids.iter().map(|insn_id| jit.get_opnd(*insn_id)))?
+ $insn_ids.iter().map(|insn_id| jit.get_opnd(*insn_id)).collect::<Vec<_>>()
}
};
}
+ macro_rules! no_output {
+ ($call:expr) => {
+ { let () = $call; return Some(()); }
+ };
+ }
+
if !matches!(*insn, Insn::Snapshot { .. }) {
asm_comment!(asm, "Insn: {insn_id} {insn}");
}
@@ -332,55 +337,63 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
let out_opnd = match insn {
Insn::Const { val: Const::Value(val) } => gen_const(*val),
Insn::NewArray { elements, state } => gen_new_array(asm, opnds!(elements), &function.frame_state(*state)),
- Insn::NewRange { low, high, flag, state } => gen_new_range(asm, opnd!(low), opnd!(high), *flag, &function.frame_state(*state)),
+ Insn::NewHash { elements, state } => gen_new_hash(jit, asm, elements, &function.frame_state(*state)),
+ Insn::NewRange { low, high, flag, state } => gen_new_range(jit, asm, opnd!(low), opnd!(high), *flag, &function.frame_state(*state)),
Insn::ArrayDup { val, state } => gen_array_dup(asm, opnd!(val), &function.frame_state(*state)),
Insn::StringCopy { val, chilled, state } => gen_string_copy(asm, opnd!(val), *chilled, &function.frame_state(*state)),
- Insn::StringConcat { strings, state } => gen_string_concat(jit, asm, opnds!(strings), &function.frame_state(*state))?,
- Insn::StringIntern { val, state } => gen_intern(asm, opnd!(val), &function.frame_state(*state))?,
+ // concatstrings shouldn't have 0 strings
+ // If it happens we abort the compilation for now
+ Insn::StringConcat { strings, .. } if strings.is_empty() => return None,
+ Insn::StringConcat { strings, state } => gen_string_concat(jit, asm, opnds!(strings), &function.frame_state(*state)),
+ Insn::StringIntern { val, state } => gen_intern(asm, opnd!(val), &function.frame_state(*state)),
+ Insn::ToRegexp { opt, values, state } => gen_toregexp(jit, asm, *opt, opnds!(values), &function.frame_state(*state)),
Insn::Param { idx } => unreachable!("block.insns should not have Insn::Param({idx})"),
Insn::Snapshot { .. } => return Some(()), // we don't need to do anything for this instruction at the moment
- Insn::Jump(branch) => return gen_jump(jit, asm, branch),
- Insn::IfTrue { val, target } => return gen_if_true(jit, asm, opnd!(val), target),
- Insn::IfFalse { val, target } => return gen_if_false(jit, asm, opnd!(val), target),
- Insn::SendWithoutBlock { cd, state, self_val, args, .. } => gen_send_without_block(jit, asm, *cd, &function.frame_state(*state), opnd!(self_val), opnds!(args))?,
+ Insn::Jump(branch) => no_output!(gen_jump(jit, asm, branch)),
+ Insn::IfTrue { val, target } => no_output!(gen_if_true(jit, asm, opnd!(val), target)),
+ Insn::IfFalse { val, target } => no_output!(gen_if_false(jit, asm, opnd!(val), target)),
+ Insn::SendWithoutBlock { cd, state, self_val, args, .. } => gen_send_without_block(jit, asm, *cd, &function.frame_state(*state), opnd!(self_val), opnds!(args)),
// Give up SendWithoutBlockDirect for 6+ args since asm.ccall() doesn't support it.
Insn::SendWithoutBlockDirect { cd, state, self_val, args, .. } if args.len() + 1 > C_ARG_OPNDS.len() => // +1 for self
- gen_send_without_block(jit, asm, *cd, &function.frame_state(*state), opnd!(self_val), opnds!(args))?,
- Insn::SendWithoutBlockDirect { cme, iseq, self_val, args, state, .. } => gen_send_without_block_direct(cb, jit, asm, *cme, *iseq, opnd!(self_val), opnds!(args), &function.frame_state(*state))?,
- Insn::InvokeBuiltin { bf, args, state, .. } => gen_invokebuiltin(jit, asm, &function.frame_state(*state), bf, opnds!(args))?,
- Insn::Return { val } => return Some(gen_return(asm, opnd!(val))?),
- Insn::FixnumAdd { left, right, state } => gen_fixnum_add(jit, asm, opnd!(left), opnd!(right), &function.frame_state(*state))?,
- Insn::FixnumSub { left, right, state } => gen_fixnum_sub(jit, asm, opnd!(left), opnd!(right), &function.frame_state(*state))?,
- Insn::FixnumMult { left, right, state } => gen_fixnum_mult(jit, asm, opnd!(left), opnd!(right), &function.frame_state(*state))?,
- Insn::FixnumEq { left, right } => gen_fixnum_eq(asm, opnd!(left), opnd!(right))?,
- Insn::FixnumNeq { left, right } => gen_fixnum_neq(asm, opnd!(left), opnd!(right))?,
- Insn::FixnumLt { left, right } => gen_fixnum_lt(asm, opnd!(left), opnd!(right))?,
- Insn::FixnumLe { left, right } => gen_fixnum_le(asm, opnd!(left), opnd!(right))?,
- Insn::FixnumGt { left, right } => gen_fixnum_gt(asm, opnd!(left), opnd!(right))?,
- Insn::FixnumGe { left, right } => gen_fixnum_ge(asm, opnd!(left), opnd!(right))?,
- Insn::FixnumAnd { left, right } => gen_fixnum_and(asm, opnd!(left), opnd!(right))?,
- Insn::FixnumOr { left, right } => gen_fixnum_or(asm, opnd!(left), opnd!(right))?,
- Insn::IsNil { val } => gen_isnil(asm, opnd!(val))?,
- Insn::Test { val } => gen_test(asm, opnd!(val))?,
- Insn::GuardType { val, guard_type, state } => gen_guard_type(jit, asm, opnd!(val), *guard_type, &function.frame_state(*state))?,
- Insn::GuardBitEquals { val, expected, state } => gen_guard_bit_equals(jit, asm, opnd!(val), *expected, &function.frame_state(*state))?,
- Insn::PatchPoint { invariant, state } => return gen_patch_point(jit, asm, invariant, &function.frame_state(*state)),
- Insn::CCall { cfun, args, name: _, return_type: _, elidable: _ } => gen_ccall(asm, *cfun, opnds!(args))?,
+ gen_send_without_block(jit, asm, *cd, &function.frame_state(*state), opnd!(self_val), opnds!(args)),
+ Insn::SendWithoutBlockDirect { cme, iseq, self_val, args, state, .. } => gen_send_without_block_direct(cb, jit, asm, *cme, *iseq, opnd!(self_val), opnds!(args), &function.frame_state(*state)),
+ // Ensure we have enough room fit ec, self, and arguments
+ // TODO remove this check when we have stack args (we can use Time.new to test it)
+ Insn::InvokeBuiltin { bf, .. } if bf.argc + 2 > (C_ARG_OPNDS.len() as i32) => return None,
+ Insn::InvokeBuiltin { bf, args, state, .. } => gen_invokebuiltin(jit, asm, &function.frame_state(*state), bf, opnds!(args)),
+ Insn::Return { val } => no_output!(gen_return(asm, opnd!(val))),
+ Insn::FixnumAdd { left, right, state } => gen_fixnum_add(jit, asm, opnd!(left), opnd!(right), &function.frame_state(*state)),
+ Insn::FixnumSub { left, right, state } => gen_fixnum_sub(jit, asm, opnd!(left), opnd!(right), &function.frame_state(*state)),
+ Insn::FixnumMult { left, right, state } => gen_fixnum_mult(jit, asm, opnd!(left), opnd!(right), &function.frame_state(*state)),
+ Insn::FixnumEq { left, right } => gen_fixnum_eq(asm, opnd!(left), opnd!(right)),
+ Insn::FixnumNeq { left, right } => gen_fixnum_neq(asm, opnd!(left), opnd!(right)),
+ Insn::FixnumLt { left, right } => gen_fixnum_lt(asm, opnd!(left), opnd!(right)),
+ Insn::FixnumLe { left, right } => gen_fixnum_le(asm, opnd!(left), opnd!(right)),
+ Insn::FixnumGt { left, right } => gen_fixnum_gt(asm, opnd!(left), opnd!(right)),
+ Insn::FixnumGe { left, right } => gen_fixnum_ge(asm, opnd!(left), opnd!(right)),
+ Insn::FixnumAnd { left, right } => gen_fixnum_and(asm, opnd!(left), opnd!(right)),
+ Insn::FixnumOr { left, right } => gen_fixnum_or(asm, opnd!(left), opnd!(right)),
+ Insn::IsNil { val } => gen_isnil(asm, opnd!(val)),
+ Insn::Test { val } => gen_test(asm, opnd!(val)),
+ Insn::GuardType { val, guard_type, state } => gen_guard_type(jit, asm, opnd!(val), *guard_type, &function.frame_state(*state)),
+ Insn::GuardBitEquals { val, expected, state } => gen_guard_bit_equals(jit, asm, opnd!(val), *expected, &function.frame_state(*state)),
+ Insn::PatchPoint { invariant, state } => no_output!(gen_patch_point(jit, asm, invariant, &function.frame_state(*state))),
+ Insn::CCall { cfun, args, name: _, return_type: _, elidable: _ } => gen_ccall(asm, *cfun, opnds!(args)),
Insn::GetIvar { self_val, id, state: _ } => gen_getivar(asm, opnd!(self_val), *id),
- Insn::SetGlobal { id, val, state } => return gen_setglobal(jit, asm, *id, opnd!(val), &function.frame_state(*state)),
+ Insn::SetGlobal { id, val, state } => no_output!(gen_setglobal(jit, asm, *id, opnd!(val), &function.frame_state(*state))),
Insn::GetGlobal { id, state: _ } => gen_getglobal(asm, *id),
- &Insn::GetLocal { ep_offset, level } => gen_getlocal_with_ep(asm, ep_offset, level)?,
- &Insn::SetLocal { val, ep_offset, level } => return gen_setlocal_with_ep(asm, jit, function, val, ep_offset, level),
- Insn::GetConstantPath { ic, state } => gen_get_constant_path(jit, asm, *ic, &function.frame_state(*state))?,
- Insn::SetIvar { self_val, id, val, state: _ } => return gen_setivar(asm, opnd!(self_val), *id, opnd!(val)),
- Insn::SideExit { state, reason } => return gen_side_exit(jit, asm, reason, &function.frame_state(*state)),
+ &Insn::GetLocal { ep_offset, level } => gen_getlocal_with_ep(asm, ep_offset, level),
+ &Insn::SetLocal { val, ep_offset, level } => no_output!(gen_setlocal_with_ep(asm, opnd!(val), function.type_of(val), ep_offset, level)),
+ Insn::GetConstantPath { ic, state } => gen_get_constant_path(jit, asm, *ic, &function.frame_state(*state)),
+ Insn::SetIvar { self_val, id, val, state: _ } => no_output!(gen_setivar(asm, opnd!(self_val), *id, opnd!(val))),
+ Insn::SideExit { state, reason } => no_output!(gen_side_exit(jit, asm, reason, &function.frame_state(*state))),
Insn::PutSpecialObject { value_type } => gen_putspecialobject(asm, *value_type),
- Insn::AnyToString { val, str, state } => gen_anytostring(asm, opnd!(val), opnd!(str), &function.frame_state(*state))?,
- Insn::Defined { op_type, obj, pushval, v, state } => gen_defined(jit, asm, *op_type, *obj, *pushval, opnd!(v), &function.frame_state(*state))?,
+ Insn::AnyToString { val, str, state } => gen_anytostring(asm, opnd!(val), opnd!(str), &function.frame_state(*state)),
+ Insn::Defined { op_type, obj, pushval, v, state } => gen_defined(jit, asm, *op_type, *obj, *pushval, opnd!(v), &function.frame_state(*state)),
Insn::GetSpecialSymbol { symbol_type, state: _ } => gen_getspecial_symbol(asm, *symbol_type),
Insn::GetSpecialNumber { nth, state } => gen_getspecial_number(asm, *nth, &function.frame_state(*state)),
- &Insn::IncrCounter(counter) => return Some(gen_incr_counter(asm, counter)),
- Insn::ObjToString { val, cd, state, .. } => gen_objtostring(jit, asm, opnd!(val), *cd, &function.frame_state(*state))?,
+ &Insn::IncrCounter(counter) => no_output!(gen_incr_counter(asm, counter)),
+ Insn::ObjToString { val, cd, state, .. } => gen_objtostring(jit, asm, opnd!(val), *cd, &function.frame_state(*state)),
Insn::ArrayExtend { .. }
| Insn::ArrayMax { .. }
| Insn::ArrayPush { .. }
@@ -388,7 +401,6 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
| Insn::FixnumDiv { .. }
| Insn::FixnumMod { .. }
| Insn::HashDup { .. }
- | Insn::NewHash { .. }
| Insn::Send { .. }
| Insn::Throw { .. }
| Insn::ToArray { .. }
@@ -446,8 +458,8 @@ fn gen_get_ep(asm: &mut Assembler, level: u32) -> Opnd {
ep_opnd
}
-fn gen_objtostring(jit: &mut JITState, asm: &mut Assembler, val: Opnd, cd: *const rb_call_data, state: &FrameState) -> Option<Opnd> {
- gen_prepare_non_leaf_call(jit, asm, state)?;
+fn gen_objtostring(jit: &mut JITState, asm: &mut Assembler, val: Opnd, cd: *const rb_call_data, state: &FrameState) -> Opnd {
+ gen_prepare_non_leaf_call(jit, asm, state);
let iseq_opnd = Opnd::Value(jit.iseq.into());
@@ -459,12 +471,12 @@ fn gen_objtostring(jit: &mut JITState, asm: &mut Assembler, val: Opnd, cd: *cons
// Need to replicate what CALL_SIMPLE_METHOD does
asm_comment!(asm, "side-exit if rb_vm_objtostring returns Qundef");
asm.cmp(ret, Qundef.into());
- asm.je(side_exit(jit, state, ObjToStringFallback)?);
+ asm.je(side_exit(jit, state, ObjToStringFallback));
- Some(ret)
+ ret
}
-fn gen_defined(jit: &JITState, asm: &mut Assembler, op_type: usize, obj: VALUE, pushval: VALUE, tested_value: Opnd, state: &FrameState) -> Option<Opnd> {
+fn gen_defined(jit: &JITState, asm: &mut Assembler, op_type: usize, obj: VALUE, pushval: VALUE, tested_value: Opnd, state: &FrameState) -> Opnd {
match op_type as defined_type {
DEFINED_YIELD => {
// `yield` goes to the block handler stowed in the "local" iseq which is
@@ -476,21 +488,21 @@ fn gen_defined(jit: &JITState, asm: &mut Assembler, op_type: usize, obj: VALUE,
let block_handler = asm.load(Opnd::mem(64, lep, SIZEOF_VALUE_I32 * VM_ENV_DATA_INDEX_SPECVAL));
let pushval = asm.load(pushval.into());
asm.cmp(block_handler, VM_BLOCK_HANDLER_NONE.into());
- Some(asm.csel_e(Qnil.into(), pushval.into()))
+ asm.csel_e(Qnil.into(), pushval.into())
} else {
- Some(Qnil.into())
+ Qnil.into()
}
}
_ => {
// Save the PC and SP because the callee may allocate or call #respond_to?
- gen_prepare_non_leaf_call(jit, asm, state)?;
+ gen_prepare_non_leaf_call(jit, asm, state);
// TODO: Inline the cases for each op_type
// Call vm_defined(ec, reg_cfp, op_type, obj, v)
let def_result = asm_ccall!(asm, rb_vm_defined, EC, CFP, op_type.into(), obj.into(), tested_value);
asm.cmp(def_result.with_num_bits(8), 0.into());
- Some(asm.csel_ne(pushval.into(), Qnil.into()))
+ asm.csel_ne(pushval.into(), Qnil.into())
}
}
}
@@ -498,69 +510,64 @@ fn gen_defined(jit: &JITState, asm: &mut Assembler, op_type: usize, obj: VALUE,
/// Get a local variable from a higher scope or the heap. `local_ep_offset` is in number of VALUEs.
/// We generate this instruction with level=0 only when the local variable is on the heap, so we
/// can't optimize the level=0 case using the SP register.
-fn gen_getlocal_with_ep(asm: &mut Assembler, local_ep_offset: u32, level: u32) -> Option<lir::Opnd> {
+fn gen_getlocal_with_ep(asm: &mut Assembler, local_ep_offset: u32, level: u32) -> lir::Opnd {
let ep = gen_get_ep(asm, level);
- let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).ok()?);
- Some(asm.load(Opnd::mem(64, ep, offset)))
+ let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).expect(&format!("Could not convert local_ep_offset {local_ep_offset} to i32")));
+ asm.load(Opnd::mem(64, ep, offset))
}
/// Set a local variable from a higher scope or the heap. `local_ep_offset` is in number of VALUEs.
/// We generate this instruction with level=0 only when the local variable is on the heap, so we
/// can't optimize the level=0 case using the SP register.
-fn gen_setlocal_with_ep(asm: &mut Assembler, jit: &JITState, function: &Function, val: InsnId, local_ep_offset: u32, level: u32) -> Option<()> {
+fn gen_setlocal_with_ep(asm: &mut Assembler, val: Opnd, val_type: Type, local_ep_offset: u32, level: u32) {
let ep = gen_get_ep(asm, level);
// When we've proved that we're writing an immediate,
// we can skip the write barrier.
- if function.type_of(val).is_immediate() {
- let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).ok()?);
- asm.mov(Opnd::mem(64, ep, offset), jit.get_opnd(val)?);
+ if val_type.is_immediate() {
+ let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).expect(&format!("Could not convert local_ep_offset {local_ep_offset} to i32")));
+ asm.mov(Opnd::mem(64, ep, offset), val);
} else {
// We're potentially writing a reference to an IMEMO/env object,
// so take care of the write barrier with a function.
- let local_index = c_int::try_from(local_ep_offset).ok().and_then(|idx| idx.checked_mul(-1))?;
- asm_ccall!(asm, rb_vm_env_write, ep, local_index.into(), jit.get_opnd(val)?);
+ let local_index = c_int::try_from(local_ep_offset).ok().and_then(|idx| idx.checked_mul(-1)).expect(&format!("Could not turn {local_ep_offset} into a negative c_int"));
+ asm_ccall!(asm, rb_vm_env_write, ep, local_index.into(), val);
}
- Some(())
}
-fn gen_get_constant_path(jit: &JITState, asm: &mut Assembler, ic: *const iseq_inline_constant_cache, state: &FrameState) -> Option<Opnd> {
+fn gen_get_constant_path(jit: &JITState, asm: &mut Assembler, ic: *const iseq_inline_constant_cache, state: &FrameState) -> Opnd {
unsafe extern "C" {
fn rb_vm_opt_getconstant_path(ec: EcPtr, cfp: CfpPtr, ic: *const iseq_inline_constant_cache) -> VALUE;
}
// Anything could be called on const_missing
- gen_prepare_non_leaf_call(jit, asm, state)?;
+ gen_prepare_non_leaf_call(jit, asm, state);
- Some(asm_ccall!(asm, rb_vm_opt_getconstant_path, EC, CFP, Opnd::const_ptr(ic)))
+ asm_ccall!(asm, rb_vm_opt_getconstant_path, EC, CFP, Opnd::const_ptr(ic))
}
-fn gen_invokebuiltin(jit: &JITState, asm: &mut Assembler, state: &FrameState, bf: &rb_builtin_function, args: Vec<Opnd>) -> Option<lir::Opnd> {
- // Ensure we have enough room fit ec, self, and arguments
- // TODO remove this check when we have stack args (we can use Time.new to test it)
- if bf.argc + 2 > (C_ARG_OPNDS.len() as i32) {
- return None;
- }
-
+fn gen_invokebuiltin(jit: &JITState, asm: &mut Assembler, state: &FrameState, bf: &rb_builtin_function, args: Vec<Opnd>) -> lir::Opnd {
+ assert!(bf.argc + 2 <= C_ARG_OPNDS.len() as i32,
+ "gen_invokebuiltin should not be called for builtin function {} with too many arguments: {}",
+ unsafe { std::ffi::CStr::from_ptr(bf.name).to_str().unwrap() },
+ bf.argc);
// Anything can happen inside builtin functions
- gen_prepare_non_leaf_call(jit, asm, state)?;
+ gen_prepare_non_leaf_call(jit, asm, state);
let mut cargs = vec![EC];
cargs.extend(args);
- let val = asm.ccall(bf.func_ptr as *const u8, cargs);
-
- Some(val)
+ asm.ccall(bf.func_ptr as *const u8, cargs)
}
/// Record a patch point that should be invalidated on a given invariant
-fn gen_patch_point(jit: &mut JITState, asm: &mut Assembler, invariant: &Invariant, state: &FrameState) -> Option<()> {
+fn gen_patch_point(jit: &mut JITState, asm: &mut Assembler, invariant: &Invariant, state: &FrameState) {
let payload_ptr = get_or_create_iseq_payload_ptr(jit.iseq);
let label = asm.new_label("patch_point").unwrap_label();
let invariant = invariant.clone();
// Compile a side exit. Fill nop instructions if the last patch point is too close.
- asm.patch_point(build_side_exit(jit, state, PatchPoint(invariant), Some(label))?);
+ asm.patch_point(build_side_exit(jit, state, PatchPoint(invariant), Some(label)));
// Remember the current address as a patch point
asm.pos_marker(move |code_ptr, cb| {
@@ -583,13 +590,12 @@ fn gen_patch_point(jit: &mut JITState, asm: &mut Assembler, invariant: &Invarian
}
}
});
- Some(())
}
/// Lowering for [`Insn::CCall`]. This is a low-level raw call that doesn't know
/// anything about the callee, so handling for e.g. GC safety is dealt with elsewhere.
-fn gen_ccall(asm: &mut Assembler, cfun: *const u8, args: Vec<Opnd>) -> Option<lir::Opnd> {
- Some(asm.ccall(cfun, args))
+fn gen_ccall(asm: &mut Assembler, cfun: *const u8, args: Vec<Opnd>) -> lir::Opnd {
+ asm.ccall(cfun, args)
}
/// Emit an uncached instance variable lookup
@@ -598,9 +604,8 @@ fn gen_getivar(asm: &mut Assembler, recv: Opnd, id: ID) -> Opnd {
}
/// Emit an uncached instance variable store
-fn gen_setivar(asm: &mut Assembler, recv: Opnd, id: ID, val: Opnd) -> Option<()> {
+fn gen_setivar(asm: &mut Assembler, recv: Opnd, id: ID, val: Opnd) {
asm_ccall!(asm, rb_ivar_set, recv, id.0.into(), val);
- Some(())
}
/// Look up global variables
@@ -609,25 +614,23 @@ fn gen_getglobal(asm: &mut Assembler, id: ID) -> Opnd {
}
/// Intern a string
-fn gen_intern(asm: &mut Assembler, val: Opnd, state: &FrameState) -> Option<Opnd> {
+fn gen_intern(asm: &mut Assembler, val: Opnd, state: &FrameState) -> Opnd {
gen_prepare_call_with_gc(asm, state);
- Some(asm_ccall!(asm, rb_str_intern, val))
+ asm_ccall!(asm, rb_str_intern, val)
}
/// Set global variables
-fn gen_setglobal(jit: &mut JITState, asm: &mut Assembler, id: ID, val: Opnd, state: &FrameState) -> Option<()> {
+fn gen_setglobal(jit: &mut JITState, asm: &mut Assembler, id: ID, val: Opnd, state: &FrameState) {
// When trace_var is used, setting a global variable can cause exceptions
- gen_prepare_non_leaf_call(jit, asm, state)?;
+ gen_prepare_non_leaf_call(jit, asm, state);
asm_ccall!(asm, rb_gvar_set, id.0.into(), val);
- Some(())
}
/// Side-exit into the interpreter
-fn gen_side_exit(jit: &mut JITState, asm: &mut Assembler, reason: &SideExitReason, state: &FrameState) -> Option<()> {
- asm.jmp(side_exit(jit, state, *reason)?);
- Some(())
+fn gen_side_exit(jit: &mut JITState, asm: &mut Assembler, reason: &SideExitReason, state: &FrameState) {
+ asm.jmp(side_exit(jit, state, *reason));
}
/// Emit a special object lookup
@@ -734,25 +737,26 @@ fn gen_entry_params(asm: &mut Assembler, iseq: IseqPtr, entry_block: &Block) {
}
/// Set branch params to basic block arguments
-fn gen_branch_params(jit: &mut JITState, asm: &mut Assembler, branch: &BranchEdge) -> Option<()> {
- if !branch.args.is_empty() {
- asm_comment!(asm, "set branch params: {}", branch.args.len());
- let mut moves: Vec<(Reg, Opnd)> = vec![];
- for (idx, &arg) in branch.args.iter().enumerate() {
- match param_opnd(idx) {
- Opnd::Reg(reg) => {
- // If a parameter is a register, we need to parallel-move it
- moves.push((reg, jit.get_opnd(arg)?));
- },
- param => {
- // If a parameter is memory, we set it beforehand
- asm.mov(param, jit.get_opnd(arg)?);
- }
+fn gen_branch_params(jit: &mut JITState, asm: &mut Assembler, branch: &BranchEdge) {
+ if branch.args.is_empty() {
+ return;
+ }
+
+ asm_comment!(asm, "set branch params: {}", branch.args.len());
+ let mut moves: Vec<(Reg, Opnd)> = vec![];
+ for (idx, &arg) in branch.args.iter().enumerate() {
+ match param_opnd(idx) {
+ Opnd::Reg(reg) => {
+ // If a parameter is a register, we need to parallel-move it
+ moves.push((reg, jit.get_opnd(arg)));
+ },
+ param => {
+ // If a parameter is memory, we set it beforehand
+ asm.mov(param, jit.get_opnd(arg));
}
}
- asm.parallel_mov(moves);
}
- Some(())
+ asm.parallel_mov(moves);
}
/// Get a method parameter on JIT entry. As of entry, whether EP is escaped or not solely
@@ -795,18 +799,17 @@ fn gen_param(asm: &mut Assembler, idx: usize) -> lir::Opnd {
}
/// Compile a jump to a basic block
-fn gen_jump(jit: &mut JITState, asm: &mut Assembler, branch: &BranchEdge) -> Option<()> {
+fn gen_jump(jit: &mut JITState, asm: &mut Assembler, branch: &BranchEdge) {
// Set basic block arguments
gen_branch_params(jit, asm, branch);
// Jump to the basic block
let target = jit.get_label(asm, branch.target);
asm.jmp(target);
- Some(())
}
/// Compile a conditional branch to a basic block
-fn gen_if_true(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, branch: &BranchEdge) -> Option<()> {
+fn gen_if_true(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, branch: &BranchEdge) {
// If val is zero, move on to the next instruction.
let if_false = asm.new_label("if_false");
asm.test(val, val);
@@ -819,12 +822,10 @@ fn gen_if_true(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, branch:
asm.jmp(if_true);
asm.write_label(if_false);
-
- Some(())
}
/// Compile a conditional branch to a basic block
-fn gen_if_false(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, branch: &BranchEdge) -> Option<()> {
+fn gen_if_false(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, branch: &BranchEdge) {
// If val is not zero, move on to the next instruction.
let if_true = asm.new_label("if_true");
asm.test(val, val);
@@ -837,8 +838,6 @@ fn gen_if_false(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, branch:
asm.jmp(if_false);
asm.write_label(if_true);
-
- Some(())
}
/// Compile a dynamic dispatch without block
@@ -849,8 +848,8 @@ fn gen_send_without_block(
state: &FrameState,
self_val: Opnd,
args: Vec<Opnd>,
-) -> Option<lir::Opnd> {
- gen_spill_locals(jit, asm, state)?;
+) -> lir::Opnd {
+ gen_spill_locals(jit, asm, state);
// Spill the receiver and the arguments onto the stack.
// They need to be on the interpreter stack to let the interpreter access them.
// TODO: Avoid spilling operands that have been spilled before.
@@ -879,7 +878,7 @@ fn gen_send_without_block(
// TODO(max): Add a PatchPoint here that can side-exit the function if the callee messed with
// the frame's locals
- Some(ret)
+ ret
}
/// Compile a direct jump to an ISEQ call without block
@@ -892,13 +891,13 @@ fn gen_send_without_block_direct(
recv: Opnd,
args: Vec<Opnd>,
state: &FrameState,
-) -> Option<lir::Opnd> {
+) -> lir::Opnd {
// Save cfp->pc and cfp->sp for the caller frame
gen_save_pc(asm, state);
gen_save_sp(asm, state.stack().len() - args.len() - 1); // -1 for receiver
- gen_spill_locals(jit, asm, state)?;
- gen_spill_stack(jit, asm, state)?;
+ gen_spill_locals(jit, asm, state);
+ gen_spill_stack(jit, asm, state);
// Set up the new frame
// TODO: Lazily materialize caller frames on side exits or when needed
@@ -944,7 +943,7 @@ fn gen_send_without_block_direct(
let new_sp = asm.sub(SP, sp_offset.into());
asm.mov(SP, new_sp);
- Some(ret)
+ ret
}
/// Compile a string resurrection
@@ -974,7 +973,7 @@ fn gen_new_array(
) -> lir::Opnd {
gen_prepare_call_with_gc(asm, state);
- let length: ::std::os::raw::c_long = elements.len().try_into().expect("Unable to fit length of elements into c_long");
+ let length: c_long = elements.len().try_into().expect("Unable to fit length of elements into c_long");
let new_array = asm_ccall!(asm, rb_ary_new_capa, length.into());
@@ -985,22 +984,79 @@ fn gen_new_array(
new_array
}
+/// Compile a new hash instruction
+fn gen_new_hash(
+ jit: &mut JITState,
+ asm: &mut Assembler,
+ elements: &Vec<(InsnId, InsnId)>,
+ state: &FrameState,
+) -> lir::Opnd {
+ gen_prepare_non_leaf_call(jit, asm, state);
+
+ let cap: c_long = elements.len().try_into().expect("Unable to fit length of elements into c_long");
+ let new_hash = asm_ccall!(asm, rb_hash_new_with_size, lir::Opnd::Imm(cap));
+
+ if !elements.is_empty() {
+ let mut pairs = Vec::new();
+ for (key_id, val_id) in elements.iter() {
+ let key = jit.get_opnd(*key_id);
+ let val = jit.get_opnd(*val_id);
+ pairs.push(key);
+ pairs.push(val);
+ }
+
+ let n = pairs.len();
+
+ // Calculate the compile-time NATIVE_STACK_PTR offset from NATIVE_BASE_PTR
+ // At this point, frame_setup(&[], jit.c_stack_slots) has been called,
+ // which allocated aligned_stack_bytes(jit.c_stack_slots) on the stack
+ let frame_size = aligned_stack_bytes(jit.c_stack_slots);
+ let allocation_size = aligned_stack_bytes(n);
+
+ asm_comment!(asm, "allocate {} bytes on C stack for {} hash elements", allocation_size, n);
+ asm.sub_into(NATIVE_STACK_PTR, allocation_size.into());
+
+ // Calculate the total offset from NATIVE_BASE_PTR to our buffer
+ let total_offset_from_base = (frame_size + allocation_size) as i32;
+
+ for (idx, &pair_opnd) in pairs.iter().enumerate() {
+ let slot_offset = -total_offset_from_base + (idx as i32 * SIZEOF_VALUE_I32);
+ asm.mov(
+ Opnd::mem(VALUE_BITS, NATIVE_BASE_PTR, slot_offset),
+ pair_opnd
+ );
+ }
+
+ let argv = asm.lea(Opnd::mem(64, NATIVE_BASE_PTR, -total_offset_from_base));
+
+ let argc = (elements.len() * 2) as ::std::os::raw::c_long;
+ asm_ccall!(asm, rb_hash_bulk_insert, lir::Opnd::Imm(argc), argv, new_hash);
+
+ asm_comment!(asm, "restore C stack pointer");
+ asm.add_into(NATIVE_STACK_PTR, allocation_size.into());
+ }
+
+ new_hash
+}
+
/// Compile a new range instruction
fn gen_new_range(
+ jit: &JITState,
asm: &mut Assembler,
low: lir::Opnd,
high: lir::Opnd,
flag: RangeType,
state: &FrameState,
) -> lir::Opnd {
- gen_prepare_call_with_gc(asm, state);
+ // Sometimes calls `low.<=>(high)`
+ gen_prepare_non_leaf_call(jit, asm, state);
// Call rb_range_new(low, high, flag)
asm_ccall!(asm, rb_range_new, low, high, (flag as i64).into())
}
/// Compile code that exits from JIT code with a return value
-fn gen_return(asm: &mut Assembler, val: lir::Opnd) -> Option<()> {
+fn gen_return(asm: &mut Assembler, val: lir::Opnd) {
// Pop the current frame (ec->cfp++)
// Note: the return PC is already in the previous CFP
asm_comment!(asm, "pop stack frame");
@@ -1015,31 +1071,28 @@ fn gen_return(asm: &mut Assembler, val: lir::Opnd) -> Option<()> {
// Return from the function
asm.frame_teardown(&[]); // matching the setup in :bb0-prologue:
asm.cret(C_RET_OPND);
- Some(())
}
/// Compile Fixnum + Fixnum
-fn gen_fixnum_add(jit: &mut JITState, asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd, state: &FrameState) -> Option<lir::Opnd> {
+fn gen_fixnum_add(jit: &mut JITState, asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd, state: &FrameState) -> lir::Opnd {
// Add left + right and test for overflow
let left_untag = asm.sub(left, Opnd::Imm(1));
let out_val = asm.add(left_untag, right);
- asm.jo(side_exit(jit, state, FixnumAddOverflow)?);
+ asm.jo(side_exit(jit, state, FixnumAddOverflow));
- Some(out_val)
+ out_val
}
/// Compile Fixnum - Fixnum
-fn gen_fixnum_sub(jit: &mut JITState, asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd, state: &FrameState) -> Option<lir::Opnd> {
+fn gen_fixnum_sub(jit: &mut JITState, asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd, state: &FrameState) -> lir::Opnd {
// Subtract left - right and test for overflow
let val_untag = asm.sub(left, right);
- asm.jo(side_exit(jit, state, FixnumSubOverflow)?);
- let out_val = asm.add(val_untag, Opnd::Imm(1));
-
- Some(out_val)
+ asm.jo(side_exit(jit, state, FixnumSubOverflow));
+ asm.add(val_untag, Opnd::Imm(1))
}
/// Compile Fixnum * Fixnum
-fn gen_fixnum_mult(jit: &mut JITState, asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd, state: &FrameState) -> Option<lir::Opnd> {
+fn gen_fixnum_mult(jit: &mut JITState, asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd, state: &FrameState) -> lir::Opnd {
// Do some bitwise gymnastics to handle tag bits
// x * y is translated to (x >> 1) * (y - 1) + 1
let left_untag = asm.rshift(left, Opnd::UImm(1));
@@ -1047,107 +1100,105 @@ fn gen_fixnum_mult(jit: &mut JITState, asm: &mut Assembler, left: lir::Opnd, rig
let out_val = asm.mul(left_untag, right_untag);
// Test for overflow
- asm.jo_mul(side_exit(jit, state, FixnumMultOverflow)?);
- let out_val = asm.add(out_val, Opnd::UImm(1));
-
- Some(out_val)
+ asm.jo_mul(side_exit(jit, state, FixnumMultOverflow));
+ asm.add(out_val, Opnd::UImm(1))
}
/// Compile Fixnum == Fixnum
-fn gen_fixnum_eq(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> Option<lir::Opnd> {
+fn gen_fixnum_eq(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> lir::Opnd {
asm.cmp(left, right);
- Some(asm.csel_e(Qtrue.into(), Qfalse.into()))
+ asm.csel_e(Qtrue.into(), Qfalse.into())
}
/// Compile Fixnum != Fixnum
-fn gen_fixnum_neq(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> Option<lir::Opnd> {
+fn gen_fixnum_neq(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> lir::Opnd {
asm.cmp(left, right);
- Some(asm.csel_ne(Qtrue.into(), Qfalse.into()))
+ asm.csel_ne(Qtrue.into(), Qfalse.into())
}
/// Compile Fixnum < Fixnum
-fn gen_fixnum_lt(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> Option<lir::Opnd> {
+fn gen_fixnum_lt(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> lir::Opnd {
asm.cmp(left, right);
- Some(asm.csel_l(Qtrue.into(), Qfalse.into()))
+ asm.csel_l(Qtrue.into(), Qfalse.into())
}
/// Compile Fixnum <= Fixnum
-fn gen_fixnum_le(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> Option<lir::Opnd> {
+fn gen_fixnum_le(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> lir::Opnd {
asm.cmp(left, right);
- Some(asm.csel_le(Qtrue.into(), Qfalse.into()))
+ asm.csel_le(Qtrue.into(), Qfalse.into())
}
/// Compile Fixnum > Fixnum
-fn gen_fixnum_gt(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> Option<lir::Opnd> {
+fn gen_fixnum_gt(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> lir::Opnd {
asm.cmp(left, right);
- Some(asm.csel_g(Qtrue.into(), Qfalse.into()))
+ asm.csel_g(Qtrue.into(), Qfalse.into())
}
/// Compile Fixnum >= Fixnum
-fn gen_fixnum_ge(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> Option<lir::Opnd> {
+fn gen_fixnum_ge(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> lir::Opnd {
asm.cmp(left, right);
- Some(asm.csel_ge(Qtrue.into(), Qfalse.into()))
+ asm.csel_ge(Qtrue.into(), Qfalse.into())
}
/// Compile Fixnum & Fixnum
-fn gen_fixnum_and(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> Option<lir::Opnd> {
- Some(asm.and(left, right))
+fn gen_fixnum_and(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> lir::Opnd {
+ asm.and(left, right)
}
/// Compile Fixnum | Fixnum
-fn gen_fixnum_or(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> Option<lir::Opnd> {
- Some(asm.or(left, right))
+fn gen_fixnum_or(asm: &mut Assembler, left: lir::Opnd, right: lir::Opnd) -> lir::Opnd {
+ asm.or(left, right)
}
// Compile val == nil
-fn gen_isnil(asm: &mut Assembler, val: lir::Opnd) -> Option<lir::Opnd> {
+fn gen_isnil(asm: &mut Assembler, val: lir::Opnd) -> lir::Opnd {
asm.cmp(val, Qnil.into());
// TODO: Implement and use setcc
- Some(asm.csel_e(Opnd::Imm(1), Opnd::Imm(0)))
+ asm.csel_e(Opnd::Imm(1), Opnd::Imm(0))
}
-fn gen_anytostring(asm: &mut Assembler, val: lir::Opnd, str: lir::Opnd, state: &FrameState) -> Option<lir::Opnd> {
+fn gen_anytostring(asm: &mut Assembler, val: lir::Opnd, str: lir::Opnd, state: &FrameState) -> lir::Opnd {
gen_prepare_call_with_gc(asm, state);
- Some(asm_ccall!(asm, rb_obj_as_string_result, str, val))
+ asm_ccall!(asm, rb_obj_as_string_result, str, val)
}
/// Evaluate if a value is truthy
/// Produces a CBool type (0 or 1)
/// In Ruby, only nil and false are falsy
/// Everything else evaluates to true
-fn gen_test(asm: &mut Assembler, val: lir::Opnd) -> Option<lir::Opnd> {
+fn gen_test(asm: &mut Assembler, val: lir::Opnd) -> lir::Opnd {
// Test if any bit (outside of the Qnil bit) is on
// See RB_TEST(), include/ruby/internal/special_consts.h
asm.test(val, Opnd::Imm(!Qnil.as_i64()));
- Some(asm.csel_e(0.into(), 1.into()))
+ asm.csel_e(0.into(), 1.into())
}
/// Compile a type check with a side exit
-fn gen_guard_type(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, guard_type: Type, state: &FrameState) -> Option<lir::Opnd> {
+fn gen_guard_type(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, guard_type: Type, state: &FrameState) -> lir::Opnd {
if guard_type.is_subtype(types::Fixnum) {
asm.test(val, Opnd::UImm(RUBY_FIXNUM_FLAG as u64));
- asm.jz(side_exit(jit, state, GuardType(guard_type))?);
+ asm.jz(side_exit(jit, state, GuardType(guard_type)));
} else if guard_type.is_subtype(types::Flonum) {
// Flonum: (val & RUBY_FLONUM_MASK) == RUBY_FLONUM_FLAG
let masked = asm.and(val, Opnd::UImm(RUBY_FLONUM_MASK as u64));
asm.cmp(masked, Opnd::UImm(RUBY_FLONUM_FLAG as u64));
- asm.jne(side_exit(jit, state, GuardType(guard_type))?);
+ asm.jne(side_exit(jit, state, GuardType(guard_type)));
} else if guard_type.is_subtype(types::StaticSymbol) {
// Static symbols have (val & 0xff) == RUBY_SYMBOL_FLAG
- // Use 8-bit comparison like YJIT does
- debug_assert!(val.try_num_bits(8).is_some(), "GuardType should not be used for a known constant, but val was: {val:?}");
- asm.cmp(val.try_num_bits(8)?, Opnd::UImm(RUBY_SYMBOL_FLAG as u64));
- asm.jne(side_exit(jit, state, GuardType(guard_type))?);
+ // Use 8-bit comparison like YJIT does. GuardType should not be used
+ // for a known VALUE, which with_num_bits() does not support.
+ asm.cmp(val.with_num_bits(8), Opnd::UImm(RUBY_SYMBOL_FLAG as u64));
+ asm.jne(side_exit(jit, state, GuardType(guard_type)));
} else if guard_type.is_subtype(types::NilClass) {
asm.cmp(val, Qnil.into());
- asm.jne(side_exit(jit, state, GuardType(guard_type))?);
+ asm.jne(side_exit(jit, state, GuardType(guard_type)));
} else if guard_type.is_subtype(types::TrueClass) {
asm.cmp(val, Qtrue.into());
- asm.jne(side_exit(jit, state, GuardType(guard_type))?);
+ asm.jne(side_exit(jit, state, GuardType(guard_type)));
} else if guard_type.is_subtype(types::FalseClass) {
asm.cmp(val, Qfalse.into());
- asm.jne(side_exit(jit, state, GuardType(guard_type))?);
+ asm.jne(side_exit(jit, state, GuardType(guard_type)));
} else if guard_type.is_immediate() {
// All immediate types' guard should have been handled above
panic!("unexpected immediate guard type: {guard_type}");
@@ -1162,7 +1213,7 @@ fn gen_guard_type(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, guard
};
// Check if it's a special constant
- let side_exit = side_exit(jit, state, GuardType(guard_type))?;
+ let side_exit = side_exit(jit, state, GuardType(guard_type));
asm.test(val, (RUBY_IMMEDIATE_MASK as u64).into());
asm.jnz(side_exit.clone());
@@ -1178,18 +1229,18 @@ fn gen_guard_type(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, guard
} else {
unimplemented!("unsupported type: {guard_type}");
}
- Some(val)
+ val
}
/// Compile an identity check with a side exit
-fn gen_guard_bit_equals(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, expected: VALUE, state: &FrameState) -> Option<lir::Opnd> {
+fn gen_guard_bit_equals(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, expected: VALUE, state: &FrameState) -> lir::Opnd {
asm.cmp(val, Opnd::Value(expected));
- asm.jnz(side_exit(jit, state, GuardBitEquals(expected))?);
- Some(val)
+ asm.jnz(side_exit(jit, state, GuardBitEquals(expected)));
+ val
}
/// Generate code that increments a counter in ZJIT stats
-fn gen_incr_counter(asm: &mut Assembler, counter: Counter) -> () {
+fn gen_incr_counter(asm: &mut Assembler, counter: Counter) {
let ptr = counter_ptr(counter);
let ptr_reg = asm.load(Opnd::const_ptr(ptr as *const u8));
let counter_opnd = Opnd::mem(64, ptr_reg, 0);
@@ -1221,30 +1272,27 @@ fn gen_save_sp(asm: &mut Assembler, stack_size: usize) {
}
/// Spill locals onto the stack.
-fn gen_spill_locals(jit: &JITState, asm: &mut Assembler, state: &FrameState) -> Option<()> {
+fn gen_spill_locals(jit: &JITState, asm: &mut Assembler, state: &FrameState) {
// TODO: Avoid spilling locals that have been spilled before and not changed.
asm_comment!(asm, "spill locals");
for (idx, &insn_id) in state.locals().enumerate() {
- asm.mov(Opnd::mem(64, SP, (-local_idx_to_ep_offset(jit.iseq, idx) - 1) * SIZEOF_VALUE_I32), jit.get_opnd(insn_id)?);
+ asm.mov(Opnd::mem(64, SP, (-local_idx_to_ep_offset(jit.iseq, idx) - 1) * SIZEOF_VALUE_I32), jit.get_opnd(insn_id));
}
- Some(())
}
/// Spill the virtual stack onto the stack.
-fn gen_spill_stack(jit: &JITState, asm: &mut Assembler, state: &FrameState) -> Option<()> {
+fn gen_spill_stack(jit: &JITState, asm: &mut Assembler, state: &FrameState) {
// This function does not call gen_save_sp() at the moment because
// gen_send_without_block_direct() spills stack slots above SP for arguments.
asm_comment!(asm, "spill stack");
for (idx, &insn_id) in state.stack().enumerate() {
- asm.mov(Opnd::mem(64, SP, idx as i32 * SIZEOF_VALUE_I32), jit.get_opnd(insn_id)?);
+ asm.mov(Opnd::mem(64, SP, idx as i32 * SIZEOF_VALUE_I32), jit.get_opnd(insn_id));
}
- Some(())
}
/// Prepare for calling a C function that may call an arbitrary method.
/// Use gen_prepare_call_with_gc() if the method is leaf but allocates objects.
-#[must_use]
-fn gen_prepare_non_leaf_call(jit: &JITState, asm: &mut Assembler, state: &FrameState) -> Option<()> {
+fn gen_prepare_non_leaf_call(jit: &JITState, asm: &mut Assembler, state: &FrameState) {
// TODO: Lazily materialize caller frames when needed
// Save PC for backtraces and allocation tracing
gen_save_pc(asm, state);
@@ -1252,11 +1300,10 @@ fn gen_prepare_non_leaf_call(jit: &JITState, asm: &mut Assembler, state: &FrameS
// Save SP and spill the virtual stack in case it raises an exception
// and the interpreter uses the stack for handling the exception
gen_save_sp(asm, state.stack().len());
- gen_spill_stack(jit, asm, state)?;
+ gen_spill_stack(jit, asm, state);
// Spill locals in case the method looks at caller Bindings
- gen_spill_locals(jit, asm, state)?;
- Some(())
+ gen_spill_locals(jit, asm, state);
}
/// Prepare for calling a C function that may allocate objects and trigger GC.
@@ -1353,20 +1400,20 @@ fn compile_iseq(iseq: IseqPtr) -> Option<Function> {
}
/// Build a Target::SideExit for non-PatchPoint instructions
-fn side_exit(jit: &mut JITState, state: &FrameState, reason: SideExitReason) -> Option<Target> {
+fn side_exit(jit: &mut JITState, state: &FrameState, reason: SideExitReason) -> Target {
build_side_exit(jit, state, reason, None)
}
/// Build a Target::SideExit out of a FrameState
-fn build_side_exit(jit: &mut JITState, state: &FrameState, reason: SideExitReason, label: Option<Label>) -> Option<Target> {
+fn build_side_exit(jit: &mut JITState, state: &FrameState, reason: SideExitReason, label: Option<Label>) -> Target {
let mut stack = Vec::new();
for &insn_id in state.stack() {
- stack.push(jit.get_opnd(insn_id)?);
+ stack.push(jit.get_opnd(insn_id));
}
let mut locals = Vec::new();
for &insn_id in state.locals() {
- locals.push(jit.get_opnd(insn_id)?);
+ locals.push(jit.get_opnd(insn_id));
}
let target = Target::SideExit {
@@ -1376,7 +1423,7 @@ fn build_side_exit(jit: &mut JITState, state: &FrameState, reason: SideExitReaso
reason,
label,
};
- Some(target)
+ target
}
/// Return true if a given ISEQ is known to escape EP to the heap on entry.
@@ -1429,9 +1476,9 @@ c_callable! {
with_vm_lock(src_loc!(), || {
// gen_push_frame() doesn't set PC and SP, so we need to set them before exit.
// function_stub_hit_body() may allocate and call gc_validate_pc(), so we always set PC.
- let iseq_call = unsafe { Rc::from_raw(iseq_call_ptr as *const IseqCall) };
+ let iseq_call = unsafe { Rc::from_raw(iseq_call_ptr as *const RefCell<IseqCall>) };
let cfp = unsafe { get_ec_cfp(ec) };
- let pc = unsafe { rb_iseq_pc_at_idx(iseq_call.iseq, 0) }; // TODO: handle opt_pc once supported
+ let pc = unsafe { rb_iseq_pc_at_idx(iseq_call.borrow().iseq, 0) }; // TODO: handle opt_pc once supported
unsafe { rb_set_cfp_pc(cfp, pc) };
unsafe { rb_set_cfp_sp(cfp, sp) };
@@ -1439,10 +1486,10 @@ c_callable! {
// TODO: Alan thinks the payload status part of this check can happen without the VM lock, since the whole
// code path can be made read-only. But you still need the check as is while holding the VM lock in any case.
let cb = ZJITState::get_code_block();
- let payload = get_or_create_iseq_payload(iseq_call.iseq);
+ let payload = get_or_create_iseq_payload(iseq_call.borrow().iseq);
if cb.has_dropped_bytes() || payload.status == IseqStatus::CantCompile {
// We'll use this Rc again, so increment the ref count decremented by from_raw.
- unsafe { Rc::increment_strong_count(iseq_call_ptr as *const IseqCall); }
+ unsafe { Rc::increment_strong_count(iseq_call_ptr as *const RefCell<IseqCall>); }
// Exit to the interpreter
return ZJITState::get_exit_trampoline().raw_ptr(cb);
@@ -1463,22 +1510,23 @@ c_callable! {
}
/// Compile an ISEQ for a function stub
-fn function_stub_hit_body(cb: &mut CodeBlock, iseq_call: &Rc<IseqCall>) -> Option<CodePtr> {
+fn function_stub_hit_body(cb: &mut CodeBlock, iseq_call: &Rc<RefCell<IseqCall>>) -> Option<CodePtr> {
// Compile the stubbed ISEQ
- let Some((code_ptr, iseq_calls)) = gen_iseq(cb, iseq_call.iseq) else {
- debug!("Failed to compile iseq: gen_iseq failed: {}", iseq_get_location(iseq_call.iseq, 0));
+ let Some((code_ptr, iseq_calls)) = gen_iseq(cb, iseq_call.borrow().iseq) else {
+ debug!("Failed to compile iseq: gen_iseq failed: {}", iseq_get_location(iseq_call.borrow().iseq, 0));
return None;
};
// Stub callee ISEQs for JIT-to-JIT calls
- for callee_iseq_call in iseq_calls.into_iter() {
- gen_iseq_call(cb, iseq_call.iseq, callee_iseq_call)?;
+ for callee_iseq_call in iseq_calls.iter() {
+ gen_iseq_call(cb, iseq_call.borrow().iseq, callee_iseq_call)?;
}
// Update the stub to call the code pointer
let code_addr = code_ptr.raw_ptr(cb);
- iseq_call.regenerate(cb, |asm| {
- asm_comment!(asm, "call compiled function: {}", iseq_get_location(iseq_call.iseq, 0));
+ let iseq = iseq_call.borrow().iseq;
+ iseq_call.borrow_mut().regenerate(cb, |asm| {
+ asm_comment!(asm, "call compiled function: {}", iseq_get_location(iseq, 0));
asm.ccall(code_addr, vec![]);
});
@@ -1486,9 +1534,9 @@ fn function_stub_hit_body(cb: &mut CodeBlock, iseq_call: &Rc<IseqCall>) -> Optio
}
/// Compile a stub for an ISEQ called by SendWithoutBlockDirect
-fn gen_function_stub(cb: &mut CodeBlock, iseq_call: Rc<IseqCall>) -> Option<CodePtr> {
+fn gen_function_stub(cb: &mut CodeBlock, iseq_call: Rc<RefCell<IseqCall>>) -> Option<CodePtr> {
let mut asm = Assembler::new();
- asm_comment!(asm, "Stub: {}", iseq_get_location(iseq_call.iseq, 0));
+ asm_comment!(asm, "Stub: {}", iseq_get_location(iseq_call.borrow().iseq, 0));
// Call function_stub_hit using the shared trampoline. See `gen_function_stub_hit_trampoline`.
// Use load_into instead of mov, which is split on arm64, to avoid clobbering ALLOC_REGS.
@@ -1550,16 +1598,8 @@ pub fn gen_exit_trampoline(cb: &mut CodeBlock) -> Option<CodePtr> {
})
}
-fn gen_string_concat(jit: &mut JITState, asm: &mut Assembler, strings: Vec<Opnd>, state: &FrameState) -> Option<Opnd> {
- let n = strings.len();
-
- // concatstrings shouldn't have 0 strings
- // If it happens we abort the compilation for now
- if n == 0 {
- return None;
- }
-
- gen_prepare_non_leaf_call(jit, asm, state)?;
+fn gen_push_opnds(jit: &mut JITState, asm: &mut Assembler, opnds: &[Opnd]) -> lir::Opnd {
+ let n = opnds.len();
// Calculate the compile-time NATIVE_STACK_PTR offset from NATIVE_BASE_PTR
// At this point, frame_setup(&[], jit.c_stack_slots) has been called,
@@ -1567,28 +1607,51 @@ fn gen_string_concat(jit: &mut JITState, asm: &mut Assembler, strings: Vec<Opnd>
let frame_size = aligned_stack_bytes(jit.c_stack_slots);
let allocation_size = aligned_stack_bytes(n);
- asm_comment!(asm, "allocate {} bytes on C stack for {} strings", allocation_size, n);
+ asm_comment!(asm, "allocate {} bytes on C stack for {} values", allocation_size, n);
asm.sub_into(NATIVE_STACK_PTR, allocation_size.into());
// Calculate the total offset from NATIVE_BASE_PTR to our buffer
let total_offset_from_base = (frame_size + allocation_size) as i32;
- for (idx, &string_opnd) in strings.iter().enumerate() {
+ for (idx, &opnd) in opnds.iter().enumerate() {
let slot_offset = -total_offset_from_base + (idx as i32 * SIZEOF_VALUE_I32);
asm.mov(
Opnd::mem(VALUE_BITS, NATIVE_BASE_PTR, slot_offset),
- string_opnd
+ opnd
);
}
- let first_string_ptr = asm.lea(Opnd::mem(64, NATIVE_BASE_PTR, -total_offset_from_base));
-
- let result = asm_ccall!(asm, rb_str_concat_literals, n.into(), first_string_ptr);
+ asm.lea(Opnd::mem(64, NATIVE_BASE_PTR, -total_offset_from_base))
+}
+fn gen_pop_opnds(asm: &mut Assembler, opnds: &[Opnd]) {
asm_comment!(asm, "restore C stack pointer");
+ let allocation_size = aligned_stack_bytes(opnds.len());
asm.add_into(NATIVE_STACK_PTR, allocation_size.into());
+}
+
+fn gen_toregexp(jit: &mut JITState, asm: &mut Assembler, opt: usize, values: Vec<Opnd>, state: &FrameState) -> Opnd {
+ gen_prepare_non_leaf_call(jit, asm, state);
+
+ let first_opnd_ptr = gen_push_opnds(jit, asm, &values);
+
+ let tmp_ary = asm_ccall!(asm, rb_ary_tmp_new_from_values, Opnd::Imm(0), values.len().into(), first_opnd_ptr);
+ let result = asm_ccall!(asm, rb_reg_new_ary, tmp_ary, opt.into());
+ asm_ccall!(asm, rb_ary_clear, tmp_ary);
+
+ gen_pop_opnds(asm, &values);
- Some(result)
+ result
+}
+
+fn gen_string_concat(jit: &mut JITState, asm: &mut Assembler, strings: Vec<Opnd>, state: &FrameState) -> Opnd {
+ gen_prepare_non_leaf_call(jit, asm, state);
+
+ let first_string_ptr = gen_push_opnds(jit, asm, &strings);
+ let result = asm_ccall!(asm, rb_str_concat_literals, strings.len().into(), first_string_ptr);
+ gen_pop_opnds(asm, &strings);
+
+ result
}
/// Given the number of spill slots needed for a function, return the number of bytes
@@ -1602,7 +1665,7 @@ fn aligned_stack_bytes(num_slots: usize) -> usize {
impl Assembler {
/// Make a C call while marking the start and end positions for IseqCall
- fn ccall_with_iseq_call(&mut self, fptr: *const u8, opnds: Vec<Opnd>, iseq_call: &Rc<IseqCall>) -> Opnd {
+ fn ccall_with_iseq_call(&mut self, fptr: *const u8, opnds: Vec<Opnd>, iseq_call: &Rc<RefCell<IseqCall>>) -> Opnd {
// We need to create our own branch rc objects so that we can move the closure below
let start_iseq_call = iseq_call.clone();
let end_iseq_call = iseq_call.clone();
@@ -1611,10 +1674,10 @@ impl Assembler {
fptr,
opnds,
move |code_ptr, _| {
- start_iseq_call.start_addr.set(Some(code_ptr));
+ start_iseq_call.borrow_mut().start_addr.set(Some(code_ptr));
},
move |code_ptr, _| {
- end_iseq_call.end_addr.set(Some(code_ptr));
+ end_iseq_call.borrow_mut().end_addr.set(Some(code_ptr));
},
)
}
@@ -1622,9 +1685,9 @@ impl Assembler {
/// Store info about a JIT-to-JIT call
#[derive(Debug)]
-struct IseqCall {
+pub struct IseqCall {
/// Callee ISEQ that start_addr jumps to
- iseq: IseqPtr,
+ pub iseq: IseqPtr,
/// Position where the call instruction starts
start_addr: Cell<Option<CodePtr>>,
@@ -1635,12 +1698,13 @@ struct IseqCall {
impl IseqCall {
/// Allocate a new IseqCall
- fn new(iseq: IseqPtr) -> Rc<Self> {
- Rc::new(IseqCall {
+ fn new(iseq: IseqPtr) -> Rc<RefCell<Self>> {
+ let iseq_call = IseqCall {
iseq,
start_addr: Cell::new(None),
end_addr: Cell::new(None),
- })
+ };
+ Rc::new(RefCell::new(iseq_call))
}
/// Regenerate a IseqCall with a given callback
diff --git a/zjit/src/cruby_bindings.inc.rs b/zjit/src/cruby_bindings.inc.rs
index 5c939fabe7..524b06b580 100644
--- a/zjit/src/cruby_bindings.inc.rs
+++ b/zjit/src/cruby_bindings.inc.rs
@@ -30,6 +30,11 @@ impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> {
fmt.write_str("__IncompleteArrayField")
}
}
+pub const ONIG_OPTION_IGNORECASE: u32 = 1;
+pub const ONIG_OPTION_EXTEND: u32 = 2;
+pub const ONIG_OPTION_MULTILINE: u32 = 4;
+pub const ARG_ENCODING_FIXED: u32 = 16;
+pub const ARG_ENCODING_NONE: u32 = 32;
pub const INTEGER_REDEFINED_OP_FLAG: u32 = 1;
pub const FLOAT_REDEFINED_OP_FLAG: u32 = 2;
pub const STRING_REDEFINED_OP_FLAG: u32 = 4;
diff --git a/zjit/src/gc.rs b/zjit/src/gc.rs
index 52a036d49e..3462b80232 100644
--- a/zjit/src/gc.rs
+++ b/zjit/src/gc.rs
@@ -1,6 +1,9 @@
// This module is responsible for marking/moving objects on GC.
+use std::cell::RefCell;
+use std::rc::Rc;
use std::{ffi::c_void, ops::Range};
+use crate::codegen::IseqCall;
use crate::{cruby::*, profile::IseqProfile, state::ZJITState, stats::with_time_stat, virtualmem::CodePtr};
use crate::stats::Counter::gc_time_ns;
@@ -15,6 +18,9 @@ pub struct IseqPayload {
/// GC offsets of the JIT code. These are the addresses of objects that need to be marked.
pub gc_offsets: Vec<CodePtr>,
+
+ /// JIT-to-JIT calls in the ISEQ. The IseqPayload's ISEQ is the caller of it.
+ pub iseq_calls: Vec<Rc<RefCell<IseqCall>>>,
}
impl IseqPayload {
@@ -23,6 +29,7 @@ impl IseqPayload {
status: IseqStatus::NotCompiled,
profile: IseqProfile::new(iseq_size),
gc_offsets: vec![],
+ iseq_calls: vec![],
}
}
}
@@ -112,6 +119,16 @@ pub extern "C" fn rb_zjit_iseq_update_references(payload: *mut c_void) {
with_time_stat(gc_time_ns, || iseq_update_references(payload));
}
+/// GC callback for updating object references after all object moves
+#[unsafe(no_mangle)]
+pub extern "C" fn rb_zjit_root_update_references() {
+ if !ZJITState::has_instance() {
+ return;
+ }
+ let invariants = ZJITState::get_invariants();
+ invariants.update_references();
+}
+
fn iseq_mark(payload: &IseqPayload) {
// Mark objects retained by profiling instructions
payload.profile.each_object(|object| {
@@ -135,10 +152,22 @@ fn iseq_mark(payload: &IseqPayload) {
/// This is a mirror of [iseq_mark].
fn iseq_update_references(payload: &mut IseqPayload) {
// Move objects retained by profiling instructions
- payload.profile.each_object_mut(|object| {
- *object = unsafe { rb_gc_location(*object) };
+ payload.profile.each_object_mut(|old_object| {
+ let new_object = unsafe { rb_gc_location(*old_object) };
+ if *old_object != new_object {
+ *old_object = new_object;
+ }
});
+ // Move ISEQ references in IseqCall
+ for iseq_call in payload.iseq_calls.iter_mut() {
+ let old_iseq = iseq_call.borrow().iseq;
+ let new_iseq = unsafe { rb_gc_location(VALUE(old_iseq as usize)) }.0 as IseqPtr;
+ if old_iseq != new_iseq {
+ iseq_call.borrow_mut().iseq = new_iseq;
+ }
+ }
+
// Move objects baked in JIT code
let cb = ZJITState::get_code_block();
for &offset in payload.gc_offsets.iter() {
diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs
index c50c1ce985..e7aaf64f28 100644
--- a/zjit/src/hir.rs
+++ b/zjit/src/hir.rs
@@ -439,6 +439,7 @@ pub enum SideExitReason {
CalleeSideExit,
ObjToStringFallback,
UnknownSpecialVariable(u64),
+ UnhandledDefinedType(usize),
}
impl std::fmt::Display for SideExitReason {
@@ -472,6 +473,9 @@ pub enum Insn {
StringIntern { val: InsnId, state: InsnId },
StringConcat { strings: Vec<InsnId>, state: InsnId },
+ /// Combine count stack values into a regexp
+ ToRegexp { opt: usize, values: Vec<InsnId>, state: InsnId },
+
/// Put special object (VMCORE, CBASE, etc.) based on value_type
PutSpecialObject { value_type: SpecialObjectType },
@@ -634,7 +638,6 @@ impl Insn {
// NewHash's operands may be hashed and compared for equality, which could have
// side-effects.
Insn::NewHash { elements, .. } => elements.len() > 0,
- Insn::NewRange { .. } => false,
Insn::ArrayDup { .. } => false,
Insn::HashDup { .. } => false,
Insn::Test { .. } => false,
@@ -656,6 +659,9 @@ impl Insn {
Insn::GetLocal { .. } => false,
Insn::IsNil { .. } => false,
Insn::CCall { elidable, .. } => !elidable,
+ // TODO: NewRange is effects free if we can prove the two ends to be Fixnum,
+ // but we don't have type information here in `impl Insn`. See rb_range_new().
+ Insn::NewRange { .. } => true,
_ => true,
}
}
@@ -667,6 +673,14 @@ pub struct InsnPrinter<'a> {
ptr_map: &'a PtrPrintMap,
}
+static REGEXP_FLAGS: &[(u32, &str)] = &[
+ (ONIG_OPTION_MULTILINE, "MULTILINE"),
+ (ONIG_OPTION_IGNORECASE, "IGNORECASE"),
+ (ONIG_OPTION_EXTEND, "EXTENDED"),
+ (ARG_ENCODING_FIXED, "FIXEDENCODING"),
+ (ARG_ENCODING_NONE, "NOENCODING"),
+];
+
impl<'a> std::fmt::Display for InsnPrinter<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match &self.inner {
@@ -715,6 +729,28 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
Ok(())
}
+ Insn::ToRegexp { values, opt, .. } => {
+ write!(f, "ToRegexp")?;
+ let mut prefix = " ";
+ for value in values {
+ write!(f, "{prefix}{value}")?;
+ prefix = ", ";
+ }
+
+ let opt = *opt as u32;
+ if opt != 0 {
+ write!(f, ", ")?;
+ let mut sep = "";
+ for (flag, name) in REGEXP_FLAGS {
+ if opt & flag != 0 {
+ write!(f, "{sep}{name}")?;
+ sep = "|";
+ }
+ }
+ }
+
+ Ok(())
+ }
Insn::Test { val } => { write!(f, "Test {val}") }
Insn::IsNil { val } => { write!(f, "IsNil {val}") }
Insn::Jump(target) => { write!(f, "Jump {target}") }
@@ -1178,6 +1214,7 @@ impl Function {
&StringCopy { val, chilled, state } => StringCopy { val: find!(val), chilled, state },
&StringIntern { val, state } => StringIntern { val: find!(val), state: find!(state) },
&StringConcat { ref strings, state } => StringConcat { strings: find_vec!(strings), state: find!(state) },
+ &ToRegexp { opt, ref values, state } => ToRegexp { opt, values: find_vec!(values), state },
&Test { val } => Test { val: find!(val) },
&IsNil { val } => IsNil { val: find!(val) },
&Jump(ref target) => Jump(find_branch_edge!(target)),
@@ -1304,6 +1341,7 @@ impl Function {
Insn::StringCopy { .. } => types::StringExact,
Insn::StringIntern { .. } => types::Symbol,
Insn::StringConcat { .. } => types::StringExact,
+ Insn::ToRegexp { .. } => types::RegexpExact,
Insn::NewArray { .. } => types::ArrayExact,
Insn::ArrayDup { .. } => types::ArrayExact,
Insn::NewHash { .. } => types::HashExact,
@@ -1330,7 +1368,7 @@ impl Function {
Insn::SendWithoutBlockDirect { .. } => types::BasicObject,
Insn::Send { .. } => types::BasicObject,
Insn::InvokeBuiltin { return_type, .. } => return_type.unwrap_or(types::BasicObject),
- Insn::Defined { .. } => types::BasicObject,
+ Insn::Defined { pushval, .. } => Type::from_value(*pushval).union(types::NilClass),
Insn::DefinedIvar { .. } => types::BasicObject,
Insn::GetConstantPath { .. } => types::BasicObject,
Insn::ArrayMax { .. } => types::BasicObject,
@@ -1938,14 +1976,18 @@ impl Function {
worklist.extend(strings);
worklist.push_back(state);
}
+ &Insn::ToRegexp { ref values, state, .. } => {
+ worklist.extend(values);
+ worklist.push_back(state);
+ }
| &Insn::Return { val }
| &Insn::Throw { val, .. }
- | &Insn::Defined { v: val, .. }
| &Insn::Test { val }
| &Insn::SetLocal { val, .. }
| &Insn::IsNil { val } =>
worklist.push_back(val),
&Insn::SetGlobal { val, state, .. }
+ | &Insn::Defined { v: val, state, .. }
| &Insn::StringIntern { val, state }
| &Insn::StringCopy { val, state, .. }
| &Insn::GuardType { val, state, .. }
@@ -2862,6 +2904,15 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
let insn_id = fun.push_insn(block, Insn::StringConcat { strings, state: exit_id });
state.stack_push(insn_id);
}
+ YARVINSN_toregexp => {
+ // First arg contains the options (multiline, extended, ignorecase) used to create the regexp
+ let opt = get_arg(pc, 0).as_usize();
+ let count = get_arg(pc, 1).as_usize();
+ let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
+ let values = state.stack_pop_n(count)?;
+ let insn_id = fun.push_insn(block, Insn::ToRegexp { opt, values, state: exit_id });
+ state.stack_push(insn_id);
+ }
YARVINSN_newarray => {
let count = get_arg(pc, 0).as_usize();
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
@@ -2957,6 +3008,11 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
let pushval = get_arg(pc, 2);
let v = state.stack_pop()?;
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
+ if op_type == DEFINED_METHOD.try_into().unwrap() {
+ // TODO(Shopify/ruby#703): Fix codegen for defined?(method call expr)
+ fun.push_insn(block, Insn::SideExit { state: exit_id, reason: SideExitReason::UnhandledDefinedType(op_type)});
+ break; // End the block
+ }
state.stack_push(fun.push_insn(block, Insn::Defined { op_type, obj, pushval, v, state: exit_id }));
}
YARVINSN_definedivar => {
@@ -4204,10 +4260,10 @@ mod tests {
fn test@<compiled>:2:
bb0(v0:BasicObject):
v2:NilClass = Const Value(nil)
- v4:BasicObject = Defined constant, v2
- v6:BasicObject = Defined func, v0
+ v4:StringExact|NilClass = Defined constant, v2
+ v6:StringExact|NilClass = Defined func, v0
v7:NilClass = Const Value(nil)
- v9:BasicObject = Defined global-variable, v7
+ v9:StringExact|NilClass = Defined global-variable, v7
v11:ArrayExact = NewArray v4, v6, v9
Return v11
"#]]);
@@ -5325,6 +5381,47 @@ mod tests {
}
#[test]
+ fn test_toregexp() {
+ eval(r##"
+ def test = /#{1}#{2}#{3}/
+ "##);
+ assert_method_hir_with_opcode("test", YARVINSN_toregexp, expect![[r#"
+ fn test@<compiled>:2:
+ bb0(v0:BasicObject):
+ v2:Fixnum[1] = Const Value(1)
+ v4:BasicObject = ObjToString v2
+ v6:String = AnyToString v2, str: v4
+ v7:Fixnum[2] = Const Value(2)
+ v9:BasicObject = ObjToString v7
+ v11:String = AnyToString v7, str: v9
+ v12:Fixnum[3] = Const Value(3)
+ v14:BasicObject = ObjToString v12
+ v16:String = AnyToString v12, str: v14
+ v18:RegexpExact = ToRegexp v6, v11, v16
+ Return v18
+ "#]]);
+ }
+
+ #[test]
+ fn test_toregexp_with_options() {
+ eval(r##"
+ def test = /#{1}#{2}/mixn
+ "##);
+ assert_method_hir_with_opcode("test", YARVINSN_toregexp, expect![[r#"
+ fn test@<compiled>:2:
+ bb0(v0:BasicObject):
+ v2:Fixnum[1] = Const Value(1)
+ v4:BasicObject = ObjToString v2
+ v6:String = AnyToString v2, str: v4
+ v7:Fixnum[2] = Const Value(2)
+ v9:BasicObject = ObjToString v7
+ v11:String = AnyToString v7, str: v9
+ v13:RegexpExact = ToRegexp v6, v11, MULTILINE|IGNORECASE|EXTENDED|NOENCODING
+ Return v13
+ "#]]);
+ }
+
+ #[test]
fn throw() {
eval("
define_method(:throw_return) { return 1 }
@@ -6104,6 +6201,29 @@ mod opt_tests {
}
#[test]
+ fn test_do_not_eliminate_new_range_non_fixnum() {
+ eval("
+ def test()
+ _ = (-'a'..'b')
+ 0
+ end
+ test; test
+ ");
+ assert_optimized_method_hir("test", expect![[r#"
+ fn test@<compiled>:3:
+ bb0(v0:BasicObject):
+ v1:NilClass = Const Value(nil)
+ v4:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
+ PatchPoint BOPRedefined(STRING_REDEFINED_OP_FLAG, BOP_UMINUS)
+ v6:StringExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
+ v8:StringExact = StringCopy v6
+ v10:RangeExact = NewRange v4 NewRangeInclusive v8
+ v11:Fixnum[0] = Const Value(0)
+ Return v11
+ "#]]);
+ }
+
+ #[test]
fn test_eliminate_new_array_with_elements() {
eval("
def test(a)
diff --git a/zjit/src/invariants.rs b/zjit/src/invariants.rs
index 3f291415be..14fea76d1b 100644
--- a/zjit/src/invariants.rs
+++ b/zjit/src/invariants.rs
@@ -1,6 +1,6 @@
use std::{collections::{HashMap, HashSet}, mem};
-use crate::{backend::lir::{asm_comment, Assembler}, cruby::{rb_callable_method_entry_t, ruby_basic_operators, src_loc, with_vm_lock, IseqPtr, RedefinitionFlag, ID}, gc::IseqPayload, hir::Invariant, options::debug, state::{zjit_enabled_p, ZJITState}, virtualmem::CodePtr};
+use crate::{backend::lir::{asm_comment, Assembler}, cruby::{rb_callable_method_entry_t, rb_gc_location, ruby_basic_operators, src_loc, with_vm_lock, IseqPtr, RedefinitionFlag, ID, VALUE}, gc::IseqPayload, hir::Invariant, options::debug, state::{zjit_enabled_p, ZJITState}, virtualmem::CodePtr};
use crate::stats::with_time_stat;
use crate::stats::Counter::invalidation_time_ns;
use crate::gc::remove_gc_offsets;
@@ -56,6 +56,31 @@ pub struct Invariants {
single_ractor_patch_points: HashSet<PatchPoint>,
}
+impl Invariants {
+ /// Update object references in Invariants
+ pub fn update_references(&mut self) {
+ Self::update_iseq_references(&mut self.ep_escape_iseqs);
+ Self::update_iseq_references(&mut self.no_ep_escape_iseqs);
+ }
+
+ /// Update ISEQ references in a given HashSet<IseqPtr>
+ fn update_iseq_references(iseqs: &mut HashSet<IseqPtr>) {
+ let mut moved: Vec<IseqPtr> = Vec::with_capacity(iseqs.len());
+
+ iseqs.retain(|&old_iseq| {
+ let new_iseq = unsafe { rb_gc_location(VALUE(old_iseq as usize)) }.0 as IseqPtr;
+ if old_iseq != new_iseq {
+ moved.push(new_iseq);
+ }
+ old_iseq == new_iseq
+ });
+
+ for new_iseq in moved {
+ iseqs.insert(new_iseq);
+ }
+ }
+}
+
/// Called when a basic operator is redefined. Note that all the blocks assuming
/// the stability of different operators are invalidated together and we don't
/// do fine-grained tracking.
diff --git a/zjit/src/profile.rs b/zjit/src/profile.rs
index 7ffaea29dc..771d90cb0e 100644
--- a/zjit/src/profile.rs
+++ b/zjit/src/profile.rs
@@ -98,19 +98,32 @@ fn profile_operands(profiler: &mut Profiler, profile: &mut IseqProfile, n: usize
let obj = profiler.peek_at_stack((n - i - 1) as isize);
// TODO(max): Handle GC-hidden classes like Array, Hash, etc and make them look normal or
// drop them or something
- let ty = ProfiledType::new(obj.class_of(), obj.shape_id_of());
+ let ty = ProfiledType::new(obj);
unsafe { rb_gc_writebarrier(profiler.iseq.into(), ty.class()) };
types[i].observe(ty);
}
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+struct Flags(u32);
+
+impl Flags {
+ const NONE: u32 = 0;
+ const IS_IMMEDIATE: u32 = 1 << 0;
+
+ pub fn none() -> Self { Self(Self::NONE) }
+
+ pub fn immediate() -> Self { Self(Self::IS_IMMEDIATE) }
+ pub fn is_immediate(self) -> bool { (self.0 & Self::IS_IMMEDIATE) != 0 }
+}
+
/// opt_send_without_block/opt_plus/... should store:
/// * the class of the receiver, so we can do method lookup
/// * the shape of the receiver, so we can optimize ivar lookup
/// with those two, pieces of information, we can also determine when an object is an immediate:
-/// * Integer + SPECIAL_CONST_SHAPE_ID == Fixnum
-/// * Float + SPECIAL_CONST_SHAPE_ID == Flonum
-/// * Symbol + SPECIAL_CONST_SHAPE_ID == StaticSymbol
+/// * Integer + IS_IMMEDIATE == Fixnum
+/// * Float + IS_IMMEDIATE == Flonum
+/// * Symbol + IS_IMMEDIATE == StaticSymbol
/// * NilClass == Nil
/// * TrueClass == True
/// * FalseClass == False
@@ -118,6 +131,7 @@ fn profile_operands(profiler: &mut Profiler, profile: &mut IseqProfile, n: usize
pub struct ProfiledType {
class: VALUE,
shape: ShapeId,
+ flags: Flags,
}
impl Default for ProfiledType {
@@ -127,12 +141,42 @@ impl Default for ProfiledType {
}
impl ProfiledType {
- fn new(class: VALUE, shape: ShapeId) -> Self {
- Self { class, shape }
+ fn new(obj: VALUE) -> Self {
+ if obj == Qfalse {
+ return Self { class: unsafe { rb_cFalseClass },
+ shape: INVALID_SHAPE_ID,
+ flags: Flags::immediate() };
+ }
+ if obj == Qtrue {
+ return Self { class: unsafe { rb_cTrueClass },
+ shape: INVALID_SHAPE_ID,
+ flags: Flags::immediate() };
+ }
+ if obj == Qnil {
+ return Self { class: unsafe { rb_cNilClass },
+ shape: INVALID_SHAPE_ID,
+ flags: Flags::immediate() };
+ }
+ if obj.fixnum_p() {
+ return Self { class: unsafe { rb_cInteger },
+ shape: INVALID_SHAPE_ID,
+ flags: Flags::immediate() };
+ }
+ if obj.flonum_p() {
+ return Self { class: unsafe { rb_cFloat },
+ shape: INVALID_SHAPE_ID,
+ flags: Flags::immediate() };
+ }
+ if obj.static_sym_p() {
+ return Self { class: unsafe { rb_cSymbol },
+ shape: INVALID_SHAPE_ID,
+ flags: Flags::immediate() };
+ }
+ Self { class: obj.class_of(), shape: obj.shape_id_of(), flags: Flags::none() }
}
pub fn empty() -> Self {
- Self { class: VALUE(0), shape: INVALID_SHAPE_ID }
+ Self { class: VALUE(0), shape: INVALID_SHAPE_ID, flags: Flags::none() }
}
pub fn is_empty(&self) -> bool {
@@ -148,27 +192,27 @@ impl ProfiledType {
}
pub fn is_fixnum(&self) -> bool {
- self.class == unsafe { rb_cInteger } && self.shape == SPECIAL_CONST_SHAPE_ID
+ self.class == unsafe { rb_cInteger } && self.flags.is_immediate()
}
pub fn is_flonum(&self) -> bool {
- self.class == unsafe { rb_cFloat } && self.shape == SPECIAL_CONST_SHAPE_ID
+ self.class == unsafe { rb_cFloat } && self.flags.is_immediate()
}
pub fn is_static_symbol(&self) -> bool {
- self.class == unsafe { rb_cSymbol } && self.shape == SPECIAL_CONST_SHAPE_ID
+ self.class == unsafe { rb_cSymbol } && self.flags.is_immediate()
}
pub fn is_nil(&self) -> bool {
- self.class == unsafe { rb_cNilClass } && self.shape == SPECIAL_CONST_SHAPE_ID
+ self.class == unsafe { rb_cNilClass } && self.flags.is_immediate()
}
pub fn is_true(&self) -> bool {
- self.class == unsafe { rb_cTrueClass } && self.shape == SPECIAL_CONST_SHAPE_ID
+ self.class == unsafe { rb_cTrueClass } && self.flags.is_immediate()
}
pub fn is_false(&self) -> bool {
- self.class == unsafe { rb_cFalseClass } && self.shape == SPECIAL_CONST_SHAPE_ID
+ self.class == unsafe { rb_cFalseClass } && self.flags.is_immediate()
}
}