diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index f52c76c8eaa6c4..3dce96def3e92e 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -81,7 +81,7 @@ jobs:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
iwr -useb get.scoop.sh | iex
Join-Path (Resolve-Path ~).Path "scoop\shims" >> $Env:GITHUB_PATH
- scoop install vcpkg uutils-coreutils cmake@3.31.6
+ scoop install vcpkg uutils-coreutils
shell: pwsh
- name: Restore vcpkg artifact
diff --git a/gc.c b/gc.c
index c9fa18f42b8e8e..26afb4e71817bc 100644
--- a/gc.c
+++ b/gc.c
@@ -180,13 +180,13 @@ rb_gc_vm_barrier(void)
rb_vm_barrier();
}
-#if USE_MODULAR_GC
void *
rb_gc_get_ractor_newobj_cache(void)
{
return GET_RACTOR()->newobj_cache;
}
+#if USE_MODULAR_GC
void
rb_gc_initialize_vm_context(struct rb_gc_vm_context *context)
{
diff --git a/gc/default/default.c b/gc/default/default.c
index 42561543d1a7c7..3d40b3dddfdbf8 100644
--- a/gc/default/default.c
+++ b/gc/default/default.c
@@ -2216,6 +2216,17 @@ rb_gc_impl_size_allocatable_p(size_t size)
}
static const size_t ALLOCATED_COUNT_STEP = 1024;
+static void
+ractor_cache_flush_count(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache)
+{
+ for (int heap_idx = 0; heap_idx < HEAP_COUNT; heap_idx++) {
+ rb_ractor_newobj_heap_cache_t *heap_cache = &cache->heap_caches[heap_idx];
+
+ rb_heap_t *heap = &heaps[heap_idx];
+ RUBY_ATOMIC_SIZE_ADD(heap->total_allocated_objects, heap_cache->allocated_objects_count);
+ heap_cache->allocated_objects_count = 0;
+ }
+}
static inline VALUE
ractor_cache_allocate_slot(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache,
@@ -2240,19 +2251,11 @@ ractor_cache_allocate_slot(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *ca
rb_asan_unpoison_object(obj, true);
heap_cache->freelist = p->next;
- if (rb_gc_multi_ractor_p()) {
- heap_cache->allocated_objects_count++;
- rb_heap_t *heap = &heaps[heap_idx];
- if (heap_cache->allocated_objects_count >= ALLOCATED_COUNT_STEP) {
- RUBY_ATOMIC_SIZE_ADD(heap->total_allocated_objects, heap_cache->allocated_objects_count);
- heap_cache->allocated_objects_count = 0;
- }
- }
- else {
- rb_heap_t *heap = &heaps[heap_idx];
- heap->total_allocated_objects++;
- GC_ASSERT(heap->total_slots >=
- (heap->total_allocated_objects - heap->total_freed_objects - heap->final_slots_count));
+ heap_cache->allocated_objects_count++;
+ rb_heap_t *heap = &heaps[heap_idx];
+ if (heap_cache->allocated_objects_count >= ALLOCATED_COUNT_STEP) {
+ RUBY_ATOMIC_SIZE_ADD(heap->total_allocated_objects, heap_cache->allocated_objects_count);
+ heap_cache->allocated_objects_count = 0;
}
#if RGENGC_CHECK_MODE
@@ -5172,6 +5175,8 @@ gc_verify_internal_consistency_(rb_objspace_t *objspace)
/* check counters */
+ ractor_cache_flush_count(objspace, rb_gc_get_ractor_newobj_cache());
+
if (!is_lazy_sweeping(objspace) &&
!finalizing &&
!rb_gc_multi_ractor_p()) {
@@ -7510,6 +7515,8 @@ rb_gc_impl_stat(void *objspace_ptr, VALUE hash_or_sym)
setup_gc_stat_symbols();
+ ractor_cache_flush_count(objspace, rb_gc_get_ractor_newobj_cache());
+
if (RB_TYPE_P(hash_or_sym, T_HASH)) {
hash = hash_or_sym;
}
@@ -7662,6 +7669,8 @@ rb_gc_impl_stat_heap(void *objspace_ptr, VALUE heap_name, VALUE hash_or_sym)
{
rb_objspace_t *objspace = objspace_ptr;
+ ractor_cache_flush_count(objspace, rb_gc_get_ractor_newobj_cache());
+
setup_gc_stat_heap_symbols();
if (NIL_P(heap_name)) {
diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb
index 9b2416402bb74c..5eb827dcb2a8ed 100644
--- a/lib/bundler/runtime.rb
+++ b/lib/bundler/runtime.rb
@@ -240,7 +240,11 @@ def prune_gem_cache(resolve, cache_path)
cached.each do |path|
Bundler.ui.info " * #{File.basename(path)}"
- File.delete(path)
+
+ begin
+ File.delete(path)
+ rescue Errno::ENOENT
+ end
end
end
end
diff --git a/lib/bundler/templates/newgem/Rakefile.tt b/lib/bundler/templates/newgem/Rakefile.tt
index 172183d4b410d8..83f10009c7042e 100644
--- a/lib/bundler/templates/newgem/Rakefile.tt
+++ b/lib/bundler/templates/newgem/Rakefile.tt
@@ -59,6 +59,11 @@ Rake::ExtensionTask.new("<%= config[:underscored_name] %>", GEMSPEC) do |ext|
end
<% end -%>
+<% if config[:ext] == "go" -%>
+require "go_gem/rake_task"
+
+GoGem::RakeTask.new("<%= config[:underscored_name] %>")
+<% end -%>
<% end -%>
<% if default_task_names.size == 1 -%>
task default: <%= default_task_names.first.inspect %>
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index c398c985f58556..8530a2a893cb5d 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -287,7 +287,7 @@ def self.activate_and_load_bin_path(name, exec_name = nil, *requirements)
# RubyGems now uses this new `Gem.activate_and_load_bin_path` helper in
# binstubs, which is of course not overridden in Bundler since it didn't
# exist at the time. So, include the override here to workaround that.
- load ENV["BUNDLE_BIN_PATH"] if ENV["BUNDLE_BIN_PATH"] && spec.version <= "2.5.22"
+ load ENV["BUNDLE_BIN_PATH"] if ENV["BUNDLE_BIN_PATH"] && spec.version <= Gem::Version.create("2.5.22")
# Make sure there's no version of Bundler in `$LOAD_PATH` that's different
# from the version we just activated. If that was the case (it happens
@@ -666,7 +666,7 @@ def self.load_safe_marshal
# warnings in platform constants
def self.load_bundler_extensions(version)
- return unless version <= "2.6.9"
+ return unless version <= Gem::Version.create("2.6.9")
previous_platforms = {}
diff --git a/lib/rubygems/bundler_version_finder.rb b/lib/rubygems/bundler_version_finder.rb
index 602e00c1d866fb..c930c2e19c264f 100644
--- a/lib/rubygems/bundler_version_finder.rb
+++ b/lib/rubygems/bundler_version_finder.rb
@@ -2,6 +2,8 @@
module Gem::BundlerVersionFinder
def self.bundler_version
+ return if bundle_config_version == "system"
+
v = ENV["BUNDLER_VERSION"]
v = nil if v&.empty?
@@ -78,4 +80,33 @@ def self.lockfile_contents
File.read(lockfile)
end
private_class_method :lockfile_contents
+
+ def self.bundle_config_version
+ config_file = bundler_config_file
+ return unless config_file && File.file?(config_file)
+
+ contents = File.read(config_file)
+ contents =~ /^BUNDLE_VERSION:\s*["']?([^"'\s]+)["']?\s*$/
+
+ $1
+ end
+ private_class_method :bundle_config_version
+
+ def self.bundler_config_file
+ # see Bundler::Settings#global_config_file and local_config_file
+ # global
+ if ENV["BUNDLE_CONFIG"] && !ENV["BUNDLE_CONFIG"].empty?
+ ENV["BUNDLE_CONFIG"]
+ elsif ENV["BUNDLE_USER_CONFIG"] && !ENV["BUNDLE_USER_CONFIG"].empty?
+ ENV["BUNDLE_USER_CONFIG"]
+ elsif ENV["BUNDLE_USER_HOME"] && !ENV["BUNDLE_USER_HOME"].empty?
+ ENV["BUNDLE_USER_HOME"] + "config"
+ elsif Gem.user_home && !Gem.user_home.empty?
+ Gem.user_home + ".bundle/config"
+ else
+ # local
+ "config"
+ end
+ end
+ private_class_method :bundler_config_file
end
diff --git a/lib/rubygems/version.rb b/lib/rubygems/version.rb
index c9fffc1cb7ca93..43a0e4e78375d5 100644
--- a/lib/rubygems/version.rb
+++ b/lib/rubygems/version.rb
@@ -339,11 +339,17 @@ def approximate_recommendation
##
# Compares this version with +other+ returning -1, 0, or 1 if the
# other version is larger, the same, or smaller than this
- # one. Attempts to compare to something that's not a
- # Gem::Version or a valid version String return +nil+.
+ # one. +other+ must be an instance of Gem::Version, comparing with
+ # other types may raise an exception.
def <=>(other)
- return self <=> self.class.new(other) if (String === other) && self.class.correct?(other)
+ if String === other
+ unless Gem::Deprecate.skip
+ warn "comparing version objects with strings is deprecated and will be removed"
+ end
+ return unless self.class.correct?(other)
+ return self <=> self.class.new(other)
+ end
return unless Gem::Version === other
return 0 if @version == other.version || canonical_segments == other.canonical_segments
diff --git a/spec/bundler/commands/newgem_spec.rb b/spec/bundler/commands/newgem_spec.rb
index 7a837bd08f0112..1d158726bed6a0 100644
--- a/spec/bundler/commands/newgem_spec.rb
+++ b/spec/bundler/commands/newgem_spec.rb
@@ -1829,6 +1829,14 @@ def create_temporary_dir(dir)
expect(bundled_app("#{gem_name}/ext/#{gem_name}/go.mod").read).to include("module github.com/bundleuser/#{gem_name}")
end
+ it "includes go_gem extension in Rakefile" do
+ expect(bundled_app("#{gem_name}/Rakefile").read).to include(<<~RUBY)
+ require "go_gem/rake_task"
+
+ GoGem::RakeTask.new("#{gem_name}")
+ RUBY
+ end
+
context "with --no-ci" do
let(:flags) { "--ext=go --no-ci" }
diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb
index 53bed0b4151b97..6e0be10ef53044 100644
--- a/test/rubygems/helper.rb
+++ b/test/rubygems/helper.rb
@@ -335,6 +335,9 @@ def setup
ENV["XDG_STATE_HOME"] = nil
ENV["SOURCE_DATE_EPOCH"] = nil
ENV["BUNDLER_VERSION"] = nil
+ ENV["BUNDLE_CONFIG"] = nil
+ ENV["BUNDLE_USER_CONFIG"] = nil
+ ENV["BUNDLE_USER_HOME"] = nil
ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"] = "true"
@current_dir = Dir.pwd
diff --git a/test/rubygems/test_gem_bundler_version_finder.rb b/test/rubygems/test_gem_bundler_version_finder.rb
index 908f9278323c09..a773d6249b5967 100644
--- a/test/rubygems/test_gem_bundler_version_finder.rb
+++ b/test/rubygems/test_gem_bundler_version_finder.rb
@@ -2,6 +2,7 @@
require_relative "helper"
require "rubygems/bundler_version_finder"
+require "tempfile"
class TestGemBundlerVersionFinder < Gem::TestCase
def setup
@@ -56,6 +57,75 @@ def test_bundler_version_with_bundle_update_bundler
assert_nil bvf.bundler_version
end
+ def test_bundler_version_with_bundle_config
+ config_content = <<~CONFIG
+ BUNDLE_VERSION: "system"
+ CONFIG
+
+ Tempfile.create("bundle_config") do |f|
+ f.write(config_content)
+ f.flush
+
+ bvf.stub(:bundler_config_file, f.path) do
+ assert_nil bvf.bundler_version
+ end
+ end
+ end
+
+ def test_bundler_version_with_bundle_config_single_quoted
+ config_with_single_quoted_version = <<~CONFIG
+ BUNDLE_VERSION: 'system'
+ CONFIG
+
+ Tempfile.create("bundle_config") do |f|
+ f.write(config_with_single_quoted_version)
+ f.flush
+
+ bvf.stub(:bundler_config_file, f.path) do
+ assert_nil bvf.bundler_version
+ end
+ end
+ end
+
+ def test_bundler_version_with_bundle_config_version
+ ENV["BUNDLER_VERSION"] = "1.1.1.1"
+
+ config_content = <<~CONFIG
+ BUNDLE_VERSION: "1.2.3"
+ CONFIG
+
+ Tempfile.create("bundle_config") do |f|
+ f.write(config_content)
+ f.flush
+
+ bvf.stub(:bundler_config_file, f.path) do
+ assert_equal v("1.1.1.1"), bvf.bundler_version
+ end
+ end
+ end
+
+ def test_bundler_version_with_bundle_config_non_existent_file
+ bvf.stub(:bundler_config_file, "/non/existent/path") do
+ assert_nil bvf.bundler_version
+ end
+ end
+
+ def test_bundler_version_with_bundle_config_without_version
+ config_without_version = <<~CONFIG
+ BUNDLE_JOBS: "8"
+ BUNDLE_GEM__TEST: "minitest"
+ CONFIG
+
+ Tempfile.create("bundle_config") do |f|
+ f.write(config_without_version)
+ f.flush
+
+ bvf.stub(:bundler_config_file, f.path) do
+ assert_nil bvf.bundler_version
+ end
+ end
+ end
+
def test_bundler_version_with_lockfile
bvf.stub(:lockfile_contents, "") do
assert_nil bvf.bundler_version
diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb
index 1d963daa65bac6..ad2a11c631803f 100644
--- a/test/rubygems/test_gem_version.rb
+++ b/test/rubygems/test_gem_version.rb
@@ -154,11 +154,20 @@ def test_spaceship
assert_equal(-1, v("5.a") <=> v("5.0.0.rc2"))
assert_equal(1, v("5.x") <=> v("5.0.0.rc2"))
- assert_equal(0, v("1.9.3") <=> "1.9.3")
- assert_equal(1, v("1.9.3") <=> "1.9.2.99")
- assert_equal(-1, v("1.9.3") <=> "1.9.3.1")
-
- assert_nil v("1.0") <=> "whatever"
+ [
+ [0, "1.9.3"],
+ [1, "1.9.2.99"],
+ [-1, "1.9.3.1"],
+ [nil, "whatever"],
+ ].each do |cmp, string_ver|
+ expected = "comparing version objects with strings is deprecated and will be removed\n"
+
+ actual_stdout, actual_stderr = capture_output do
+ assert_equal(cmp, v("1.9.3") <=> string_ver)
+ end
+ assert_empty actual_stdout
+ assert_equal expected, actual_stderr
+ end
end
def test_approximate_recommendation
diff --git a/vm_core.h b/vm_core.h
index 0f83f2b2e9e015..28d585deb2ab01 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -431,7 +431,7 @@ struct rb_iseq_constant_body {
* size = M+N+O+(*1)+K+(&1)+(**1) // parameter size.
*/
- struct {
+ struct rb_iseq_parameters {
struct {
unsigned int has_lead : 1;
unsigned int has_opt : 1;
diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs
index a6aef48313ad71..66d4e5111d7bbd 100644
--- a/yjit/src/cruby_bindings.inc.rs
+++ b/yjit/src/cruby_bindings.inc.rs
@@ -490,7 +490,7 @@ pub const BUILTIN_ATTR_C_TRACE: rb_builtin_attr = 8;
pub type rb_builtin_attr = u32;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct rb_iseq_constant_body__bindgen_ty_1_rb_iseq_param_keyword {
+pub struct rb_iseq_constant_body_rb_iseq_parameters_rb_iseq_param_keyword {
pub num: ::std::os::raw::c_int,
pub required_num: ::std::os::raw::c_int,
pub bits_start: ::std::os::raw::c_int,
@@ -942,12 +942,14 @@ pub const DEFINED_REF: defined_type = 15;
pub const DEFINED_FUNC: defined_type = 16;
pub const DEFINED_CONST_FROM: defined_type = 17;
pub type defined_type = u32;
-pub type rb_seq_param_keyword_struct = rb_iseq_constant_body__bindgen_ty_1_rb_iseq_param_keyword;
+pub type rb_seq_param_keyword_struct =
+ rb_iseq_constant_body_rb_iseq_parameters_rb_iseq_param_keyword;
pub const ROBJECT_OFFSET_AS_HEAP_FIELDS: jit_bindgen_constants = 16;
pub const ROBJECT_OFFSET_AS_ARY: jit_bindgen_constants = 16;
pub const RUBY_OFFSET_RSTRING_LEN: jit_bindgen_constants = 16;
pub type jit_bindgen_constants = u32;
-pub type rb_iseq_param_keyword_struct = rb_iseq_constant_body__bindgen_ty_1_rb_iseq_param_keyword;
+pub type rb_iseq_param_keyword_struct =
+ rb_iseq_constant_body_rb_iseq_parameters_rb_iseq_param_keyword;
extern "C" {
pub fn ruby_xfree(ptr: *mut ::std::os::raw::c_void);
pub fn rb_class_attached_object(klass: VALUE) -> VALUE;
diff --git a/zjit/bindgen/src/main.rs b/zjit/bindgen/src/main.rs
index 7873a209777605..bac17f4a6d4452 100644
--- a/zjit/bindgen/src/main.rs
+++ b/zjit/bindgen/src/main.rs
@@ -424,8 +424,12 @@ fn main() {
.blocklist_type("VALUE")
.blocklist_type("ID")
- .opaque_type("rb_iseq_t")
- .blocklist_type("rb_iseq_t")
+ // Avoid binding to stuff we don't use
+ .blocklist_item("rb_thread_struct.*")
+ .opaque_type("rb_thread_struct.*")
+ .blocklist_item("iseq_inline_storage_entry_.*")
+ .opaque_type("iseq_inline_storage_entry")
+ .opaque_type("iseq_compile_data")
// Finish the builder and generate the bindings.
.generate()
diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs
index 082db3fae44108..d00ab500d72796 100644
--- a/zjit/src/codegen.rs
+++ b/zjit/src/codegen.rs
@@ -1293,10 +1293,11 @@ fn gen_send_without_block_direct(
let mut c_args = vec![recv];
c_args.extend(&args);
- let num_optionals_passed = if unsafe { get_iseq_flags_has_opt(iseq) } {
+ let params = unsafe { iseq.params() };
+ let num_optionals_passed = if params.flags.has_opt() != 0 {
// See vm_call_iseq_setup_normal_opt_start in vm_inshelper.c
- let lead_num = unsafe { get_iseq_body_param_lead_num(iseq) } as u32;
- let opt_num = unsafe { get_iseq_body_param_opt_num(iseq) } as u32;
+ let lead_num = params.lead_num as u32;
+ let opt_num = params.opt_num as u32;
assert!(args.len() as u32 <= lead_num + opt_num);
let num_optionals_passed = args.len() as u32 - lead_num;
num_optionals_passed
@@ -2212,7 +2213,7 @@ c_callable! {
// Fill nils to uninitialized (non-argument) locals
let local_size = get_iseq_body_local_table_size(iseq).to_usize();
- let num_params = get_iseq_body_param_size(iseq).to_usize();
+ let num_params = iseq.params().size.to_usize();
let base = sp.offset(-local_size_and_idx_to_bp_offset(local_size, num_params) as isize);
slice::from_raw_parts_mut(base, local_size - num_params).fill(Qnil);
}
diff --git a/zjit/src/cruby.rs b/zjit/src/cruby.rs
index a854f2e07c0667..443ed0d86e3a99 100644
--- a/zjit/src/cruby.rs
+++ b/zjit/src/cruby.rs
@@ -104,6 +104,7 @@ pub type RedefinitionFlag = u32;
#[allow(unsafe_op_in_unsafe_fn)]
#[allow(dead_code)]
+#[allow(unnecessary_transmutes)] // https://github.com/rust-lang/rust-bindgen/issues/2807
#[allow(clippy::all)] // warning meant to help with reading; not useful for generated code
mod autogened {
use super::*;
@@ -191,21 +192,7 @@ pub use rb_get_iseq_body_local_iseq as get_iseq_body_local_iseq;
pub use rb_get_iseq_body_iseq_encoded as get_iseq_body_iseq_encoded;
pub use rb_get_iseq_body_stack_max as get_iseq_body_stack_max;
pub use rb_get_iseq_body_type as get_iseq_body_type;
-pub use rb_get_iseq_flags_has_lead as get_iseq_flags_has_lead;
-pub use rb_get_iseq_flags_has_opt as get_iseq_flags_has_opt;
-pub use rb_get_iseq_flags_has_kw as get_iseq_flags_has_kw;
-pub use rb_get_iseq_flags_has_rest as get_iseq_flags_has_rest;
-pub use rb_get_iseq_flags_has_post as get_iseq_flags_has_post;
-pub use rb_get_iseq_flags_has_kwrest as get_iseq_flags_has_kwrest;
-pub use rb_get_iseq_flags_has_block as get_iseq_flags_has_block;
-pub use rb_get_iseq_flags_ambiguous_param0 as get_iseq_flags_ambiguous_param0;
-pub use rb_get_iseq_flags_accepts_no_kwarg as get_iseq_flags_accepts_no_kwarg;
pub use rb_get_iseq_body_local_table_size as get_iseq_body_local_table_size;
-pub use rb_get_iseq_body_param_keyword as get_iseq_body_param_keyword;
-pub use rb_get_iseq_body_param_size as get_iseq_body_param_size;
-pub use rb_get_iseq_body_param_lead_num as get_iseq_body_param_lead_num;
-pub use rb_get_iseq_body_param_opt_num as get_iseq_body_param_opt_num;
-pub use rb_get_iseq_body_param_opt_table as get_iseq_body_param_opt_table;
pub use rb_get_cikw_keyword_len as get_cikw_keyword_len;
pub use rb_get_cikw_keywords_idx as get_cikw_keywords_idx;
pub use rb_get_call_data_ci as get_call_data_ci;
@@ -246,14 +233,6 @@ pub fn insn_len(opcode: usize) -> u32 {
}
}
-/// Opaque iseq type for opaque iseq pointers from vm_core.h
-/// See:
-#[repr(C)]
-pub struct rb_iseq_t {
- _data: [u8; 0],
- _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
-}
-
/// An object handle similar to VALUE in the C code. Our methods assume
/// that this is a handle. Sometimes the C code briefly uses VALUE as
/// an unsigned integer type and don't necessarily store valid handles but
@@ -313,11 +292,10 @@ pub fn iseq_escapes_ep(iseq: IseqPtr) -> bool {
}
/// Index of the local variable that has a rest parameter if any
-pub fn iseq_rest_param_idx(iseq: IseqPtr) -> Option {
- if !iseq.is_null() && unsafe { get_iseq_flags_has_rest(iseq) } {
- let opt_num = unsafe { get_iseq_body_param_opt_num(iseq) };
- let lead_num = unsafe { get_iseq_body_param_lead_num(iseq) };
- Some(opt_num + lead_num)
+pub fn iseq_rest_param_idx(params: &IseqParameters) -> Option {
+ // TODO(alan): replace with `params.rest_start`
+ if params.flags.has_rest() != 0 {
+ Some(params.opt_num + params.lead_num)
} else {
None
}
@@ -693,6 +671,20 @@ impl VALUE {
}
}
+pub type IseqParameters = rb_iseq_constant_body_rb_iseq_parameters;
+
+/// Extension trait to enable method calls on [`IseqPtr`]
+pub trait IseqAccess {
+ unsafe fn params<'a>(self) -> &'a IseqParameters;
+}
+
+impl IseqAccess for IseqPtr {
+ /// Get a description of the ISEQ's signature. Analogous to `ISEQ_BODY(iseq)->param` in C.
+ unsafe fn params<'a>(self) -> &'a IseqParameters {
+ unsafe { &(*(*self).body).param }
+ }
+}
+
impl From for VALUE {
/// For `.into()` convenience
fn from(iseq: IseqPtr) -> Self {
diff --git a/zjit/src/cruby_bindings.inc.rs b/zjit/src/cruby_bindings.inc.rs
index 0fde4e3ab70a93..66126b627c0fd3 100644
--- a/zjit/src/cruby_bindings.inc.rs
+++ b/zjit/src/cruby_bindings.inc.rs
@@ -410,6 +410,11 @@ pub const BOP_INCLUDE_P: ruby_basic_operators = 33;
pub const BOP_LAST_: ruby_basic_operators = 34;
pub type ruby_basic_operators = u32;
pub type rb_serial_t = ::std::os::raw::c_ulonglong;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct rb_id_table {
+ _unused: [u8; 0],
+}
pub const imemo_env: imemo_type = 0;
pub const imemo_cref: imemo_type = 1;
pub const imemo_svar: imemo_type = 2;
@@ -475,6 +480,7 @@ pub const VM_METHOD_TYPE_OPTIMIZED: rb_method_type_t = 9;
pub const VM_METHOD_TYPE_MISSING: rb_method_type_t = 10;
pub const VM_METHOD_TYPE_REFINED: rb_method_type_t = 11;
pub type rb_method_type_t = u32;
+pub type rb_iseq_t = rb_iseq_struct;
pub type rb_cfunc_t = ::std::option::Option VALUE>;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
@@ -497,7 +503,22 @@ pub const OPTIMIZED_METHOD_TYPE_STRUCT_AREF: method_optimized_type = 3;
pub const OPTIMIZED_METHOD_TYPE_STRUCT_ASET: method_optimized_type = 4;
pub const OPTIMIZED_METHOD_TYPE__MAX: method_optimized_type = 5;
pub type method_optimized_type = u32;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct rb_code_position_struct {
+ pub lineno: ::std::os::raw::c_int,
+ pub column: ::std::os::raw::c_int,
+}
+pub type rb_code_position_t = rb_code_position_struct;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct rb_code_location_struct {
+ pub beg_pos: rb_code_position_t,
+ pub end_pos: rb_code_position_t,
+}
+pub type rb_code_location_t = rb_code_location_struct;
pub type rb_num_t = ::std::os::raw::c_ulong;
+pub type rb_snum_t = ::std::os::raw::c_long;
pub const RUBY_TAG_NONE: ruby_tag_type = 0;
pub const RUBY_TAG_RETURN: ruby_tag_type = 1;
pub const RUBY_TAG_BREAK: ruby_tag_type = 2;
@@ -534,6 +555,23 @@ pub struct iseq_inline_iv_cache_entry {
pub struct iseq_inline_cvar_cache_entry {
pub entry: *mut rb_cvar_class_tbl_entry,
}
+#[repr(C)]
+#[repr(align(8))]
+#[derive(Copy, Clone)]
+pub struct iseq_inline_storage_entry {
+ pub _bindgen_opaque_blob: [u64; 2usize],
+}
+#[repr(C)]
+pub struct rb_iseq_location_struct {
+ pub pathobj: VALUE,
+ pub base_label: VALUE,
+ pub label: VALUE,
+ pub first_lineno: ::std::os::raw::c_int,
+ pub node_id: ::std::os::raw::c_int,
+ pub code_location: rb_code_location_t,
+}
+pub type rb_iseq_location_t = rb_iseq_location_struct;
+pub type iseq_bits_t = usize;
pub const ISEQ_TYPE_TOP: rb_iseq_type = 0;
pub const ISEQ_TYPE_METHOD: rb_iseq_type = 1;
pub const ISEQ_TYPE_BLOCK: rb_iseq_type = 2;
@@ -549,9 +587,611 @@ pub const BUILTIN_ATTR_SINGLE_NOARG_LEAF: rb_builtin_attr = 2;
pub const BUILTIN_ATTR_INLINE_BLOCK: rb_builtin_attr = 4;
pub const BUILTIN_ATTR_C_TRACE: rb_builtin_attr = 8;
pub type rb_builtin_attr = u32;
+pub type rb_jit_func_t = ::std::option::Option<
+ unsafe extern "C" fn(
+ arg1: *mut rb_execution_context_struct,
+ arg2: *mut rb_control_frame_struct,
+ ) -> VALUE,
+>;
+#[repr(C)]
+pub struct rb_iseq_constant_body {
+ pub type_: rb_iseq_type,
+ pub iseq_size: ::std::os::raw::c_uint,
+ pub iseq_encoded: *mut VALUE,
+ pub param: rb_iseq_constant_body_rb_iseq_parameters,
+ pub location: rb_iseq_location_t,
+ pub insns_info: rb_iseq_constant_body_iseq_insn_info,
+ pub local_table: *const ID,
+ pub lvar_states: *mut rb_iseq_constant_body_lvar_state,
+ pub catch_table: *mut iseq_catch_table,
+ pub parent_iseq: *const rb_iseq_struct,
+ pub local_iseq: *mut rb_iseq_struct,
+ pub is_entries: *mut iseq_inline_storage_entry,
+ pub call_data: *mut rb_call_data,
+ pub variable: rb_iseq_constant_body__bindgen_ty_1,
+ pub local_table_size: ::std::os::raw::c_uint,
+ pub ic_size: ::std::os::raw::c_uint,
+ pub ise_size: ::std::os::raw::c_uint,
+ pub ivc_size: ::std::os::raw::c_uint,
+ pub icvarc_size: ::std::os::raw::c_uint,
+ pub ci_size: ::std::os::raw::c_uint,
+ pub stack_max: ::std::os::raw::c_uint,
+ pub builtin_attrs: ::std::os::raw::c_uint,
+ pub prism: bool,
+ pub mark_bits: rb_iseq_constant_body__bindgen_ty_2,
+ pub outer_variables: *mut rb_id_table,
+ pub mandatory_only_iseq: *const rb_iseq_t,
+ pub jit_entry: rb_jit_func_t,
+ pub jit_entry_calls: ::std::os::raw::c_ulong,
+ pub jit_exception: rb_jit_func_t,
+ pub jit_exception_calls: ::std::os::raw::c_ulong,
+ pub zjit_payload: *mut ::std::os::raw::c_void,
+}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
-pub struct rb_iseq_constant_body__bindgen_ty_1_rb_iseq_param_keyword {
+pub struct rb_iseq_constant_body_rb_iseq_parameters {
+ pub flags: rb_iseq_constant_body_rb_iseq_parameters__bindgen_ty_1,
+ pub size: ::std::os::raw::c_uint,
+ pub lead_num: ::std::os::raw::c_int,
+ pub opt_num: ::std::os::raw::c_int,
+ pub rest_start: ::std::os::raw::c_int,
+ pub post_start: ::std::os::raw::c_int,
+ pub post_num: ::std::os::raw::c_int,
+ pub block_start: ::std::os::raw::c_int,
+ pub opt_table: *const VALUE,
+ pub keyword: *const rb_iseq_constant_body_rb_iseq_parameters_rb_iseq_param_keyword,
+}
+#[repr(C)]
+#[repr(align(4))]
+#[derive(Debug, Copy, Clone)]
+pub struct rb_iseq_constant_body_rb_iseq_parameters__bindgen_ty_1 {
+ pub _bitfield_align_1: [u8; 0],
+ pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>,
+ pub __bindgen_padding_0: u16,
+}
+impl rb_iseq_constant_body_rb_iseq_parameters__bindgen_ty_1 {
+ #[inline]
+ pub fn has_lead(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_has_lead(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(0usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub unsafe fn has_lead_raw(this: *const Self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 2usize]>>::raw_get(
+ ::std::ptr::addr_of!((*this)._bitfield_1),
+ 0usize,
+ 1u8,
+ ) as u32)
+ }
+ }
+ #[inline]
+ pub unsafe fn set_has_lead_raw(this: *mut Self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ <__BindgenBitfieldUnit<[u8; 2usize]>>::raw_set(
+ ::std::ptr::addr_of_mut!((*this)._bitfield_1),
+ 0usize,
+ 1u8,
+ val as u64,
+ )
+ }
+ }
+ #[inline]
+ pub fn has_opt(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_has_opt(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(1usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub unsafe fn has_opt_raw(this: *const Self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 2usize]>>::raw_get(
+ ::std::ptr::addr_of!((*this)._bitfield_1),
+ 1usize,
+ 1u8,
+ ) as u32)
+ }
+ }
+ #[inline]
+ pub unsafe fn set_has_opt_raw(this: *mut Self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ <__BindgenBitfieldUnit<[u8; 2usize]>>::raw_set(
+ ::std::ptr::addr_of_mut!((*this)._bitfield_1),
+ 1usize,
+ 1u8,
+ val as u64,
+ )
+ }
+ }
+ #[inline]
+ pub fn has_rest(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_has_rest(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(2usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub unsafe fn has_rest_raw(this: *const Self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 2usize]>>::raw_get(
+ ::std::ptr::addr_of!((*this)._bitfield_1),
+ 2usize,
+ 1u8,
+ ) as u32)
+ }
+ }
+ #[inline]
+ pub unsafe fn set_has_rest_raw(this: *mut Self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ <__BindgenBitfieldUnit<[u8; 2usize]>>::raw_set(
+ ::std::ptr::addr_of_mut!((*this)._bitfield_1),
+ 2usize,
+ 1u8,
+ val as u64,
+ )
+ }
+ }
+ #[inline]
+ pub fn has_post(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_has_post(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(3usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub unsafe fn has_post_raw(this: *const Self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 2usize]>>::raw_get(
+ ::std::ptr::addr_of!((*this)._bitfield_1),
+ 3usize,
+ 1u8,
+ ) as u32)
+ }
+ }
+ #[inline]
+ pub unsafe fn set_has_post_raw(this: *mut Self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ <__BindgenBitfieldUnit<[u8; 2usize]>>::raw_set(
+ ::std::ptr::addr_of_mut!((*this)._bitfield_1),
+ 3usize,
+ 1u8,
+ val as u64,
+ )
+ }
+ }
+ #[inline]
+ pub fn has_kw(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_has_kw(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(4usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub unsafe fn has_kw_raw(this: *const Self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 2usize]>>::raw_get(
+ ::std::ptr::addr_of!((*this)._bitfield_1),
+ 4usize,
+ 1u8,
+ ) as u32)
+ }
+ }
+ #[inline]
+ pub unsafe fn set_has_kw_raw(this: *mut Self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ <__BindgenBitfieldUnit<[u8; 2usize]>>::raw_set(
+ ::std::ptr::addr_of_mut!((*this)._bitfield_1),
+ 4usize,
+ 1u8,
+ val as u64,
+ )
+ }
+ }
+ #[inline]
+ pub fn has_kwrest(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_has_kwrest(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(5usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub unsafe fn has_kwrest_raw(this: *const Self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 2usize]>>::raw_get(
+ ::std::ptr::addr_of!((*this)._bitfield_1),
+ 5usize,
+ 1u8,
+ ) as u32)
+ }
+ }
+ #[inline]
+ pub unsafe fn set_has_kwrest_raw(this: *mut Self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ <__BindgenBitfieldUnit<[u8; 2usize]>>::raw_set(
+ ::std::ptr::addr_of_mut!((*this)._bitfield_1),
+ 5usize,
+ 1u8,
+ val as u64,
+ )
+ }
+ }
+ #[inline]
+ pub fn has_block(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_has_block(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(6usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub unsafe fn has_block_raw(this: *const Self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 2usize]>>::raw_get(
+ ::std::ptr::addr_of!((*this)._bitfield_1),
+ 6usize,
+ 1u8,
+ ) as u32)
+ }
+ }
+ #[inline]
+ pub unsafe fn set_has_block_raw(this: *mut Self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ <__BindgenBitfieldUnit<[u8; 2usize]>>::raw_set(
+ ::std::ptr::addr_of_mut!((*this)._bitfield_1),
+ 6usize,
+ 1u8,
+ val as u64,
+ )
+ }
+ }
+ #[inline]
+ pub fn ambiguous_param0(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_ambiguous_param0(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(7usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub unsafe fn ambiguous_param0_raw(this: *const Self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 2usize]>>::raw_get(
+ ::std::ptr::addr_of!((*this)._bitfield_1),
+ 7usize,
+ 1u8,
+ ) as u32)
+ }
+ }
+ #[inline]
+ pub unsafe fn set_ambiguous_param0_raw(this: *mut Self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ <__BindgenBitfieldUnit<[u8; 2usize]>>::raw_set(
+ ::std::ptr::addr_of_mut!((*this)._bitfield_1),
+ 7usize,
+ 1u8,
+ val as u64,
+ )
+ }
+ }
+ #[inline]
+ pub fn accepts_no_kwarg(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_accepts_no_kwarg(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(8usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub unsafe fn accepts_no_kwarg_raw(this: *const Self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 2usize]>>::raw_get(
+ ::std::ptr::addr_of!((*this)._bitfield_1),
+ 8usize,
+ 1u8,
+ ) as u32)
+ }
+ }
+ #[inline]
+ pub unsafe fn set_accepts_no_kwarg_raw(this: *mut Self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ <__BindgenBitfieldUnit<[u8; 2usize]>>::raw_set(
+ ::std::ptr::addr_of_mut!((*this)._bitfield_1),
+ 8usize,
+ 1u8,
+ val as u64,
+ )
+ }
+ }
+ #[inline]
+ pub fn ruby2_keywords(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_ruby2_keywords(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(9usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub unsafe fn ruby2_keywords_raw(this: *const Self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 2usize]>>::raw_get(
+ ::std::ptr::addr_of!((*this)._bitfield_1),
+ 9usize,
+ 1u8,
+ ) as u32)
+ }
+ }
+ #[inline]
+ pub unsafe fn set_ruby2_keywords_raw(this: *mut Self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ <__BindgenBitfieldUnit<[u8; 2usize]>>::raw_set(
+ ::std::ptr::addr_of_mut!((*this)._bitfield_1),
+ 9usize,
+ 1u8,
+ val as u64,
+ )
+ }
+ }
+ #[inline]
+ pub fn anon_rest(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(10usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_anon_rest(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(10usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub unsafe fn anon_rest_raw(this: *const Self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 2usize]>>::raw_get(
+ ::std::ptr::addr_of!((*this)._bitfield_1),
+ 10usize,
+ 1u8,
+ ) as u32)
+ }
+ }
+ #[inline]
+ pub unsafe fn set_anon_rest_raw(this: *mut Self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ <__BindgenBitfieldUnit<[u8; 2usize]>>::raw_set(
+ ::std::ptr::addr_of_mut!((*this)._bitfield_1),
+ 10usize,
+ 1u8,
+ val as u64,
+ )
+ }
+ }
+ #[inline]
+ pub fn anon_kwrest(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(11usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_anon_kwrest(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(11usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub unsafe fn anon_kwrest_raw(this: *const Self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 2usize]>>::raw_get(
+ ::std::ptr::addr_of!((*this)._bitfield_1),
+ 11usize,
+ 1u8,
+ ) as u32)
+ }
+ }
+ #[inline]
+ pub unsafe fn set_anon_kwrest_raw(this: *mut Self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ <__BindgenBitfieldUnit<[u8; 2usize]>>::raw_set(
+ ::std::ptr::addr_of_mut!((*this)._bitfield_1),
+ 11usize,
+ 1u8,
+ val as u64,
+ )
+ }
+ }
+ #[inline]
+ pub fn use_block(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_use_block(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(12usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub unsafe fn use_block_raw(this: *const Self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 2usize]>>::raw_get(
+ ::std::ptr::addr_of!((*this)._bitfield_1),
+ 12usize,
+ 1u8,
+ ) as u32)
+ }
+ }
+ #[inline]
+ pub unsafe fn set_use_block_raw(this: *mut Self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ <__BindgenBitfieldUnit<[u8; 2usize]>>::raw_set(
+ ::std::ptr::addr_of_mut!((*this)._bitfield_1),
+ 12usize,
+ 1u8,
+ val as u64,
+ )
+ }
+ }
+ #[inline]
+ pub fn forwardable(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(13usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_forwardable(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(13usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub unsafe fn forwardable_raw(this: *const Self) -> ::std::os::raw::c_uint {
+ unsafe {
+ ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 2usize]>>::raw_get(
+ ::std::ptr::addr_of!((*this)._bitfield_1),
+ 13usize,
+ 1u8,
+ ) as u32)
+ }
+ }
+ #[inline]
+ pub unsafe fn set_forwardable_raw(this: *mut Self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ <__BindgenBitfieldUnit<[u8; 2usize]>>::raw_set(
+ ::std::ptr::addr_of_mut!((*this)._bitfield_1),
+ 13usize,
+ 1u8,
+ val as u64,
+ )
+ }
+ }
+ #[inline]
+ pub fn new_bitfield_1(
+ has_lead: ::std::os::raw::c_uint,
+ has_opt: ::std::os::raw::c_uint,
+ has_rest: ::std::os::raw::c_uint,
+ has_post: ::std::os::raw::c_uint,
+ has_kw: ::std::os::raw::c_uint,
+ has_kwrest: ::std::os::raw::c_uint,
+ has_block: ::std::os::raw::c_uint,
+ ambiguous_param0: ::std::os::raw::c_uint,
+ accepts_no_kwarg: ::std::os::raw::c_uint,
+ ruby2_keywords: ::std::os::raw::c_uint,
+ anon_rest: ::std::os::raw::c_uint,
+ anon_kwrest: ::std::os::raw::c_uint,
+ use_block: ::std::os::raw::c_uint,
+ forwardable: ::std::os::raw::c_uint,
+ ) -> __BindgenBitfieldUnit<[u8; 2usize]> {
+ let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize]> = Default::default();
+ __bindgen_bitfield_unit.set(0usize, 1u8, {
+ let has_lead: u32 = unsafe { ::std::mem::transmute(has_lead) };
+ has_lead as u64
+ });
+ __bindgen_bitfield_unit.set(1usize, 1u8, {
+ let has_opt: u32 = unsafe { ::std::mem::transmute(has_opt) };
+ has_opt as u64
+ });
+ __bindgen_bitfield_unit.set(2usize, 1u8, {
+ let has_rest: u32 = unsafe { ::std::mem::transmute(has_rest) };
+ has_rest as u64
+ });
+ __bindgen_bitfield_unit.set(3usize, 1u8, {
+ let has_post: u32 = unsafe { ::std::mem::transmute(has_post) };
+ has_post as u64
+ });
+ __bindgen_bitfield_unit.set(4usize, 1u8, {
+ let has_kw: u32 = unsafe { ::std::mem::transmute(has_kw) };
+ has_kw as u64
+ });
+ __bindgen_bitfield_unit.set(5usize, 1u8, {
+ let has_kwrest: u32 = unsafe { ::std::mem::transmute(has_kwrest) };
+ has_kwrest as u64
+ });
+ __bindgen_bitfield_unit.set(6usize, 1u8, {
+ let has_block: u32 = unsafe { ::std::mem::transmute(has_block) };
+ has_block as u64
+ });
+ __bindgen_bitfield_unit.set(7usize, 1u8, {
+ let ambiguous_param0: u32 = unsafe { ::std::mem::transmute(ambiguous_param0) };
+ ambiguous_param0 as u64
+ });
+ __bindgen_bitfield_unit.set(8usize, 1u8, {
+ let accepts_no_kwarg: u32 = unsafe { ::std::mem::transmute(accepts_no_kwarg) };
+ accepts_no_kwarg as u64
+ });
+ __bindgen_bitfield_unit.set(9usize, 1u8, {
+ let ruby2_keywords: u32 = unsafe { ::std::mem::transmute(ruby2_keywords) };
+ ruby2_keywords as u64
+ });
+ __bindgen_bitfield_unit.set(10usize, 1u8, {
+ let anon_rest: u32 = unsafe { ::std::mem::transmute(anon_rest) };
+ anon_rest as u64
+ });
+ __bindgen_bitfield_unit.set(11usize, 1u8, {
+ let anon_kwrest: u32 = unsafe { ::std::mem::transmute(anon_kwrest) };
+ anon_kwrest as u64
+ });
+ __bindgen_bitfield_unit.set(12usize, 1u8, {
+ let use_block: u32 = unsafe { ::std::mem::transmute(use_block) };
+ use_block as u64
+ });
+ __bindgen_bitfield_unit.set(13usize, 1u8, {
+ let forwardable: u32 = unsafe { ::std::mem::transmute(forwardable) };
+ forwardable as u64
+ });
+ __bindgen_bitfield_unit
+ }
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct rb_iseq_constant_body_rb_iseq_parameters_rb_iseq_param_keyword {
pub num: ::std::os::raw::c_int,
pub required_num: ::std::os::raw::c_int,
pub bits_start: ::std::os::raw::c_int,
@@ -560,6 +1200,66 @@ pub struct rb_iseq_constant_body__bindgen_ty_1_rb_iseq_param_keyword {
pub default_values: *mut VALUE,
}
#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct rb_iseq_constant_body_iseq_insn_info {
+ pub body: *const iseq_insn_info_entry,
+ pub positions: *mut ::std::os::raw::c_uint,
+ pub size: ::std::os::raw::c_uint,
+ pub succ_index_table: *mut succ_index_table,
+}
+pub const lvar_uninitialized: rb_iseq_constant_body_lvar_state = 0;
+pub const lvar_initialized: rb_iseq_constant_body_lvar_state = 1;
+pub const lvar_reassigned: rb_iseq_constant_body_lvar_state = 2;
+pub type rb_iseq_constant_body_lvar_state = u32;
+#[repr(C)]
+pub struct rb_iseq_constant_body__bindgen_ty_1 {
+ pub flip_count: rb_snum_t,
+ pub script_lines: VALUE,
+ pub coverage: VALUE,
+ pub pc2branchindex: VALUE,
+ pub original_iseq: *mut VALUE,
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union rb_iseq_constant_body__bindgen_ty_2 {
+ pub list: *mut iseq_bits_t,
+ pub single: iseq_bits_t,
+}
+#[repr(C)]
+pub struct rb_iseq_struct {
+ pub flags: VALUE,
+ pub wrapper: VALUE,
+ pub body: *mut rb_iseq_constant_body,
+ pub aux: rb_iseq_struct__bindgen_ty_1,
+}
+#[repr(C)]
+pub struct rb_iseq_struct__bindgen_ty_1 {
+ pub compile_data: __BindgenUnionField<*mut iseq_compile_data>,
+ pub loader: __BindgenUnionField,
+ pub exec: __BindgenUnionField,
+ pub bindgen_union_field: [u64; 2usize],
+}
+#[repr(C)]
+pub struct rb_iseq_struct__bindgen_ty_1__bindgen_ty_1 {
+ pub obj: VALUE,
+ pub index: ::std::os::raw::c_int,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct rb_iseq_struct__bindgen_ty_1__bindgen_ty_2 {
+ pub local_hooks: *mut rb_hook_list_struct,
+ pub global_trace_events: rb_event_flag_t,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct rb_hook_list_struct {
+ pub hooks: *mut rb_event_hook_struct,
+ pub events: rb_event_flag_t,
+ pub running: ::std::os::raw::c_uint,
+ pub need_clean: bool,
+ pub is_local: bool,
+}
+#[repr(C)]
pub struct rb_captured_block {
pub self_: VALUE,
pub ep: *const VALUE,
@@ -1076,6 +1776,67 @@ pub type ruby_vminsn_type = u32;
pub type rb_iseq_callback = ::std::option::Option<
unsafe extern "C" fn(arg1: *const rb_iseq_t, arg2: *mut ::std::os::raw::c_void),
>;
+#[repr(C)]
+#[repr(align(8))]
+#[derive(Debug, Copy, Clone)]
+pub struct iseq_compile_data {
+ pub _bindgen_opaque_blob: [u64; 24usize],
+}
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub union iseq_compile_data__bindgen_ty_1 {
+ pub list: *mut iseq_bits_t,
+ pub single: iseq_bits_t,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct iseq_compile_data__bindgen_ty_2 {
+ pub storage_head: *mut iseq_compile_data_storage,
+ pub storage_current: *mut iseq_compile_data_storage,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct iseq_compile_data__bindgen_ty_3 {
+ pub storage_head: *mut iseq_compile_data_storage,
+ pub storage_current: *mut iseq_compile_data_storage,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct iseq_insn_info_entry {
+ pub line_no: ::std::os::raw::c_int,
+ pub node_id: ::std::os::raw::c_int,
+ pub events: rb_event_flag_t,
+}
+pub const CATCH_TYPE_RESCUE: rb_catch_type = 3;
+pub const CATCH_TYPE_ENSURE: rb_catch_type = 5;
+pub const CATCH_TYPE_RETRY: rb_catch_type = 7;
+pub const CATCH_TYPE_BREAK: rb_catch_type = 9;
+pub const CATCH_TYPE_REDO: rb_catch_type = 11;
+pub const CATCH_TYPE_NEXT: rb_catch_type = 13;
+pub type rb_catch_type = u32;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct iseq_catch_table_entry {
+ pub type_: rb_catch_type,
+ pub iseq: *mut rb_iseq_t,
+ pub start: ::std::os::raw::c_uint,
+ pub end: ::std::os::raw::c_uint,
+ pub cont: ::std::os::raw::c_uint,
+ pub sp: ::std::os::raw::c_uint,
+}
+#[repr(C, packed)]
+pub struct iseq_catch_table {
+ pub size: ::std::os::raw::c_uint,
+ pub entries: __IncompleteArrayField,
+}
+#[repr(C)]
+#[derive(Debug)]
+pub struct iseq_compile_data_storage {
+ pub next: *mut iseq_compile_data_storage,
+ pub pos: ::std::os::raw::c_uint,
+ pub size: ::std::os::raw::c_uint,
+ pub buff: __IncompleteArrayField<::std::os::raw::c_char>,
+}
pub const DEFINED_NOT_DEFINED: defined_type = 0;
pub const DEFINED_NIL: defined_type = 1;
pub const DEFINED_IVAR: defined_type = 2;
@@ -1100,7 +1861,18 @@ pub const ROBJECT_OFFSET_AS_ARY: jit_bindgen_constants = 16;
pub const RUBY_OFFSET_RSTRING_LEN: jit_bindgen_constants = 16;
pub type jit_bindgen_constants = u32;
pub const rb_invalid_shape_id: shape_id_t = 4294967295;
-pub type rb_iseq_param_keyword_struct = rb_iseq_constant_body__bindgen_ty_1_rb_iseq_param_keyword;
+pub type rb_iseq_param_keyword_struct =
+ rb_iseq_constant_body_rb_iseq_parameters_rb_iseq_param_keyword;
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct succ_index_table {
+ pub _address: u8,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct rb_event_hook_struct {
+ pub _address: u8,
+}
unsafe extern "C" {
pub fn ruby_xfree(ptr: *mut ::std::os::raw::c_void);
pub fn rb_class_attached_object(klass: VALUE) -> VALUE;
diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs
index 172b177c456f3b..961fe1c1428825 100644
--- a/zjit/src/hir.rs
+++ b/zjit/src/hir.rs
@@ -1497,14 +1497,15 @@ fn can_direct_send(function: &mut Function, block: BlockId, iseq: *const rb_iseq
can_send = false;
function.push_insn(block, Insn::IncrCounter(counter));
};
+ let params = unsafe { iseq.params() };
use Counter::*;
- if unsafe { rb_get_iseq_flags_has_rest(iseq) } { count_failure(complex_arg_pass_param_rest) }
- if unsafe { rb_get_iseq_flags_has_post(iseq) } { count_failure(complex_arg_pass_param_post) }
- if unsafe { rb_get_iseq_flags_has_kw(iseq) } { count_failure(complex_arg_pass_param_kw) }
- if unsafe { rb_get_iseq_flags_has_kwrest(iseq) } { count_failure(complex_arg_pass_param_kwrest) }
- if unsafe { rb_get_iseq_flags_has_block(iseq) } { count_failure(complex_arg_pass_param_block) }
- if unsafe { rb_get_iseq_flags_forwardable(iseq) } { count_failure(complex_arg_pass_param_forwardable) }
+ if 0 != params.flags.has_rest() { count_failure(complex_arg_pass_param_rest) }
+ if 0 != params.flags.has_post() { count_failure(complex_arg_pass_param_post) }
+ if 0 != params.flags.has_kw() { count_failure(complex_arg_pass_param_kw) }
+ if 0 != params.flags.has_kwrest() { count_failure(complex_arg_pass_param_kwrest) }
+ if 0 != params.flags.has_block() { count_failure(complex_arg_pass_param_block) }
+ if 0 != params.flags.forwardable() { count_failure(complex_arg_pass_param_forwardable) }
if !can_send {
function.set_dynamic_send_reason(send_insn, ComplexArgPass);
@@ -1512,8 +1513,8 @@ fn can_direct_send(function: &mut Function, block: BlockId, iseq: *const rb_iseq
}
// Because we exclude e.g. post parameters above, they are also excluded from the sum below.
- let lead_num = unsafe { get_iseq_body_param_lead_num(iseq) };
- let opt_num = unsafe { get_iseq_body_param_opt_num(iseq) };
+ let lead_num = params.lead_num;
+ let opt_num = params.opt_num;
can_send = c_int::try_from(args.len())
.as_ref()
.map(|argc| (lead_num..=lead_num + opt_num).contains(argc))
@@ -2086,8 +2087,9 @@ impl Function {
/// Set self.param_types. They are copied to the param types of jit_entry_blocks.
fn set_param_types(&mut self) {
let iseq = self.iseq;
- let param_size = unsafe { get_iseq_body_param_size(iseq) }.to_usize();
- let rest_param_idx = iseq_rest_param_idx(iseq);
+ let params = unsafe { iseq.params() };
+ let param_size = params.size.to_usize();
+ let rest_param_idx = iseq_rest_param_idx(params);
self.param_types.push(types::BasicObject); // self
for local_idx in 0..param_size {
@@ -4596,11 +4598,12 @@ fn insn_idx_at_offset(idx: u32, offset: i64) -> u32 {
/// List of insn_idx that starts a JIT entry block
pub fn jit_entry_insns(iseq: IseqPtr) -> Vec {
// TODO(alan): Make an iterator type for this instead of copying all of the opt_table each call
- let opt_num = unsafe { get_iseq_body_param_opt_num(iseq) };
+ let params = unsafe { iseq.params() };
+ let opt_num = params.opt_num;
if opt_num > 0 {
let mut result = vec![];
- let opt_table = unsafe { get_iseq_body_param_opt_table(iseq) }; // `opt_num + 1` entries
+ let opt_table = params.opt_table; // `opt_num + 1` entries
for opt_idx in 0..=opt_num as isize {
let insn_idx = unsafe { opt_table.offset(opt_idx).read().as_u32() };
result.push(insn_idx);
@@ -5715,8 +5718,9 @@ fn compile_entry_state(fun: &mut Function) -> (InsnId, FrameState) {
fun.push_insn(entry_block, Insn::EntryPoint { jit_entry_idx: None });
let iseq = fun.iseq;
- let param_size = unsafe { get_iseq_body_param_size(iseq) }.to_usize();
- let rest_param_idx = iseq_rest_param_idx(iseq);
+ let params = unsafe { iseq.params() };
+ let param_size = params.size.to_usize();
+ let rest_param_idx = iseq_rest_param_idx(params);
let self_param = fun.push_insn(entry_block, Insn::LoadSelf);
let mut entry_state = FrameState::new(iseq);
@@ -5748,9 +5752,10 @@ fn compile_jit_entry_block(fun: &mut Function, jit_entry_idx: usize, target_bloc
/// Compile params and initial locals for a jit_entry_block
fn compile_jit_entry_state(fun: &mut Function, jit_entry_block: BlockId, jit_entry_idx: usize) -> (InsnId, FrameState) {
let iseq = fun.iseq;
- let param_size = unsafe { get_iseq_body_param_size(iseq) }.to_usize();
- let opt_num: usize = unsafe { get_iseq_body_param_opt_num(iseq) }.try_into().expect("iseq param opt_num >= 0");
- let lead_num: usize = unsafe { get_iseq_body_param_lead_num(iseq) }.try_into().expect("iseq param lead_num >= 0");
+ let params = unsafe { iseq.params() };
+ let param_size = params.size.to_usize();
+ let opt_num: usize = params.opt_num.try_into().expect("iseq param opt_num >= 0");
+ let lead_num: usize = params.lead_num.try_into().expect("iseq param lead_num >= 0");
let passed_opt_num = jit_entry_idx;
let self_param = fun.push_insn(jit_entry_block, Insn::Param);