From b07e214bf1a6c55fe9b2409cc13160ca60af874f Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 29 Jul 2025 14:54:17 -0400 Subject: [PATCH 1/5] [DOC] Remove point about ASAN not working on released Ruby ASAN works on Ruby 3.4 and later, so we can remove the point about using master branch for ASAN. --- doc/contributing/building_ruby.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/doc/contributing/building_ruby.md b/doc/contributing/building_ruby.md index a0486cb931de68..eac83fc00ef978 100644 --- a/doc/contributing/building_ruby.md +++ b/doc/contributing/building_ruby.md @@ -307,9 +307,6 @@ RUBY_TEST_TIMEOUT_SCALE=5 SYNTAX_SUGGEST_TIMEOUT=600 make check Please note, however, the following caveats! -* ASAN will not work properly on any currently released version of Ruby; the - necessary support is currently only present on Ruby's master branch (and the - whole test suite passes only as of commit [Revision 9d0a5148]). * Due to [Bug #20243], Clang generates code for threadlocal variables which doesn't work with M:N threading. Thus, it's necessary to disable M:N threading support at build time for now (with the `-DUSE_MN_THREADS=0` From 039f4139f89347cacbca106a6034e4ea8e04fbc2 Mon Sep 17 00:00:00 2001 From: Max Bernstein Date: Tue, 29 Jul 2025 12:43:14 -0700 Subject: [PATCH 2/5] ZJIT: Create delta debugging script to narrow JIT failures (#14041) Add support for `--zjit-allowed-iseqs=SomeFile` and `--zjit-log-compiled-iseqs=SomeFile` so we can restrict and inspect which ISEQs get compiled. Then add `jit_bisect.rb` which we can run to try and narrow a failing script. For example: plum% ../tool/zjit_bisect.rb ../build-dev/miniruby "test.rb" I, [2025-07-29T12:41:18.657177 #96899] INFO -- : Starting with JIT list of 4 items. I, [2025-07-29T12:41:18.657229 #96899] INFO -- : Verifying items I, [2025-07-29T12:41:18.726213 #96899] INFO -- : step fixed[0] and items[4] I, [2025-07-29T12:41:18.726246 #96899] INFO -- : 4 candidates I, [2025-07-29T12:41:18.797212 #96899] INFO -- : 2 candidates Reduced JIT list: bar@test.rb:8 plum% We start with 4 compiled functions and shrink to just one. --- tool/zjit_bisect.rb | 97 +++++++++++++++++++++++++++++++++++++++++++++ zjit/src/codegen.rs | 4 ++ zjit/src/hir.rs | 4 ++ zjit/src/options.rs | 46 ++++++++++++++++++++- zjit/src/state.rs | 33 ++++++++++++++- 5 files changed, 182 insertions(+), 2 deletions(-) create mode 100755 tool/zjit_bisect.rb diff --git a/tool/zjit_bisect.rb b/tool/zjit_bisect.rb new file mode 100755 index 00000000000000..472a60e66c5df9 --- /dev/null +++ b/tool/zjit_bisect.rb @@ -0,0 +1,97 @@ +#!/usr/bin/env ruby +require 'logger' +require 'open3' +require 'tempfile' +require 'timeout' + +RUBY = ARGV[0] || raise("Usage: ruby jit_bisect.rb ") +OPTIONS = ARGV[1] || raise("Usage: ruby jit_bisect.rb ") +TIMEOUT_SEC = 5 +LOGGER = Logger.new($stdout) + +# From https://github.com/tekknolagi/omegastar +# MIT License +# Copyright (c) 2024 Maxwell Bernstein and Meta Platforms +# Attempt to reduce the `items` argument as much as possible, returning the +# shorter version. `fixed` will always be used as part of the items when +# running `command`. +# `command` should return True if the command succeeded (the failure did not +# reproduce) and False if the command failed (the failure reproduced). +def bisect_impl(command, fixed, items, indent="") + LOGGER.info("#{indent}step fixed[#{fixed.length}] and items[#{items.length}]") + while items.length > 1 + LOGGER.info("#{indent}#{fixed.length + items.length} candidates") + # Return two halves of the given list. For odd-length lists, the second + # half will be larger. + half = items.length / 2 + left = items[0...half] + right = items[half..] + if !command.call(fixed + left) + items = left + next + end + if !command.call(fixed + right) + items = right + next + end + # We need something from both halves to trigger the failure. Try + # holding each half fixed and bisecting the other half to reduce the + # candidates. + new_right = bisect_impl(command, fixed + left, right, indent + "< ") + new_left = bisect_impl(command, fixed + new_right, left, indent + "> ") + return new_left + new_right + end + items +end + +# From https://github.com/tekknolagi/omegastar +# MIT License +# Copyright (c) 2024 Maxwell Bernstein and Meta Platforms +def run_bisect(command, items) + LOGGER.info("Verifying items") + if command.call(items) + raise StandardError.new("Command succeeded with full items") + end + if !command.call([]) + raise StandardError.new("Command failed with empty items") + end + bisect_impl(command, [], items) +end + +def run_with_jit_list(ruby, options, jit_list) + # Make a new temporary file containing the JIT list + Tempfile.create("jit_list") do |temp_file| + temp_file.write(jit_list.join("\n")) + temp_file.flush + temp_file.close + # Run the JIT with the temporary file + Open3.capture3("#{ruby} --zjit-allowed-iseqs=#{temp_file.path} #{options}") + end +end + +# Try running with no JIT list to get a stable baseline +_, stderr, status = run_with_jit_list(RUBY, OPTIONS, []) +if !status.success? + raise "Command failed with empty JIT list: #{stderr}" +end +# Collect the JIT list from the failing Ruby process +jit_list = nil +Tempfile.create "jit_list" do |temp_file| + Open3.capture3("#{RUBY} --zjit-log-compiled-iseqs=#{temp_file.path} #{OPTIONS}") + jit_list = File.readlines(temp_file.path).map(&:strip).reject(&:empty?) +end +LOGGER.info("Starting with JIT list of #{jit_list.length} items.") +# Now narrow it down +command = lambda do |items| + status = Timeout.timeout(TIMEOUT_SEC) do + _, _, status = run_with_jit_list(RUBY, OPTIONS, items) + status + end + status.success? +end +result = run_bisect(command, jit_list) +File.open("jitlist.txt", "w") do |file| + file.puts(result) +end +puts "Reduced JIT list (available in jitlist.txt):" +puts result diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index 13671fb04c3c3c..f7f0e9c09f7976 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -284,6 +284,10 @@ fn gen_function(cb: &mut CodeBlock, iseq: IseqPtr, function: &Function) -> Optio let iseq_name = iseq_get_location(iseq, 0); register_with_perf(iseq_name, start_usize, code_size); } + if ZJITState::should_log_compiled_iseqs() { + let iseq_name = iseq_get_location(iseq, 0); + ZJITState::log_compile(iseq_name); + } } result } diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index 90dce2e4e45fee..06c00e3d99a10b 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -2480,6 +2480,7 @@ pub enum ParseError { UnknownParameterType(ParameterType), MalformedIseq(u32), // insn_idx into iseq_encoded Validation(ValidationError), + NotAllowed, } /// Return the number of locals in the current ISEQ (includes parameters) @@ -2545,6 +2546,9 @@ fn filter_unknown_parameter_type(iseq: *const rb_iseq_t) -> Result<(), ParseErro /// Compile ISEQ into High-level IR pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result { + if !ZJITState::can_compile_iseq(iseq) { + return Err(ParseError::NotAllowed); + } filter_unknown_parameter_type(iseq)?; let payload = get_or_create_iseq_payload(iseq); let mut profiles = ProfileOracle::new(payload); diff --git a/zjit/src/options.rs b/zjit/src/options.rs index fc8ee23e263798..bb26cc2deeb27e 100644 --- a/zjit/src/options.rs +++ b/zjit/src/options.rs @@ -1,6 +1,7 @@ use std::{ffi::{CStr, CString}, ptr::null}; use std::os::raw::{c_char, c_int, c_uint}; use crate::cruby::*; +use std::collections::HashSet; /// Number of calls to start profiling YARV instructions. /// They are profiled `rb_zjit_call_threshold - rb_zjit_profile_threshold` times, @@ -19,7 +20,7 @@ pub static mut rb_zjit_call_threshold: u64 = 2; #[allow(non_upper_case_globals)] static mut zjit_stats_enabled_p: bool = false; -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] pub struct Options { /// Number of times YARV instructions should be profiled. pub num_profiles: u8, @@ -44,6 +45,12 @@ pub struct Options { /// Dump code map to /tmp for performance profilers. pub perf: bool, + + /// List of ISEQs that can be compiled, identified by their iseq_get_location() + pub allowed_iseqs: Option>, + + /// Path to a file where compiled ISEQs will be saved. + pub log_compiled_iseqs: Option, } /// Return an Options with default values @@ -57,6 +64,8 @@ pub fn init_options() -> Options { dump_lir: false, dump_disasm: false, perf: false, + allowed_iseqs: None, + log_compiled_iseqs: None, } } @@ -67,6 +76,8 @@ pub const ZJIT_OPTIONS: &'static [(&str, &str)] = &[ ("--zjit-num-profiles=num", "Number of profiled calls before JIT (default: 1, max: 255)."), ("--zjit-stats", "Enable collecting ZJIT statistics."), ("--zjit-perf", "Dump ISEQ symbols into /tmp/perf-{}.map for Linux perf."), + ("--zjit-log-compiled-iseqs=path", + "Log compiled ISEQs to the file. The file will be truncated."), ]; #[derive(Clone, Copy, Debug)] @@ -108,6 +119,26 @@ pub extern "C" fn rb_zjit_parse_option(options: *const u8, str_ptr: *const c_cha parse_option(options, str_ptr).is_some() } +fn parse_jit_list(path_like: &str) -> HashSet { + // Read lines from the file + let mut result = HashSet::new(); + if let Ok(lines) = std::fs::read_to_string(path_like) { + for line in lines.lines() { + let trimmed = line.trim(); + if !trimmed.is_empty() { + result.insert(trimmed.to_string()); + } + } + } else { + eprintln!("Failed to read JIT list from '{}'", path_like); + } + eprintln!("JIT list:"); + for item in &result { + eprintln!(" {}", item); + } + result +} + /// Expected to receive what comes after the third dash in "--zjit-*". /// Empty string means user passed only "--zjit". C code rejects when /// they pass exact "--zjit-". @@ -165,6 +196,19 @@ fn parse_option(options: &mut Options, str_ptr: *const std::os::raw::c_char) -> ("perf", "") => options.perf = true, + ("allowed-iseqs", _) if opt_val != "" => options.allowed_iseqs = Some(parse_jit_list(opt_val)), + ("log-compiled-iseqs", _) if opt_val != "" => { + // Truncate the file if it exists + std::fs::OpenOptions::new() + .create(true) + .write(true) + .truncate(true) + .open(opt_val) + .map_err(|e| eprintln!("Failed to open file '{}': {}", opt_val, e)) + .ok(); + options.log_compiled_iseqs = Some(opt_val.into()); + } + _ => return None, // Option name not recognized } diff --git a/zjit/src/state.rs b/zjit/src/state.rs index 1878658d8fbbe6..ee7cd15d5fb9b1 100644 --- a/zjit/src/state.rs +++ b/zjit/src/state.rs @@ -136,6 +136,38 @@ impl ZJITState { pub fn get_counters() -> &'static mut Counters { &mut ZJITState::get_instance().counters } + + /// Was --zjit-save-compiled-iseqs specified? + pub fn should_log_compiled_iseqs() -> bool { + ZJITState::get_instance().options.log_compiled_iseqs.is_some() + } + + /// Log the name of a compiled ISEQ to the file specified in options.log_compiled_iseqs + pub fn log_compile(iseq_name: String) { + assert!(ZJITState::should_log_compiled_iseqs()); + let filename = ZJITState::get_instance().options.log_compiled_iseqs.as_ref().unwrap(); + use std::io::Write; + let mut file = match std::fs::OpenOptions::new().create(true).append(true).open(filename) { + Ok(f) => f, + Err(e) => { + eprintln!("ZJIT: Failed to create file '{}': {}", filename, e); + return; + } + }; + if let Err(e) = writeln!(file, "{}", iseq_name) { + eprintln!("ZJIT: Failed to write to file '{}': {}", filename, e); + } + } + + /// Check if we are allowed to compile a given ISEQ based on --zjit-allowed-iseqs + pub fn can_compile_iseq(iseq: cruby::IseqPtr) -> bool { + if let Some(ref allowed_iseqs) = ZJITState::get_instance().options.allowed_iseqs { + let name = cruby::iseq_get_location(iseq, 0); + allowed_iseqs.contains(&name) + } else { + true // If no restrictions, allow all ISEQs + } + } } /// Initialize ZJIT, given options allocated by rb_zjit_init_options() @@ -148,7 +180,6 @@ pub extern "C" fn rb_zjit_init(options: *const u8) { let options = unsafe { Box::from_raw(options as *mut Options) }; ZJITState::init(*options); - std::mem::drop(options); rb_bug_panic_hook(); From ade45586028c97fc07057d1399a102a91f6c8140 Mon Sep 17 00:00:00 2001 From: Max Bernstein Date: Tue, 29 Jul 2025 13:36:25 -0700 Subject: [PATCH 3/5] ZJIT: Catch more failed recursive compilations (#14042) Untangle the logic a bit and specifically: * catch `gen_entry` failures * don't set `start_ptr` until all recursive calls succeed Co-authored-by: Alan Wu --- zjit/src/codegen.rs | 52 ++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index f7f0e9c09f7976..23b2dc2bd4192d 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -121,39 +121,46 @@ fn gen_iseq_entry_point_body(cb: &mut CodeBlock, iseq: IseqPtr) -> *const u8 { }; // Compile the High-level IR - let (start_ptr, mut branch_iseqs) = match gen_function(cb, iseq, &function) { - Some((start_ptr, gc_offsets, jit)) => { - // Remember the block address to reuse it later - let payload = get_or_create_iseq_payload(iseq); - payload.start_ptr = Some(start_ptr); - append_gc_offsets(iseq, &gc_offsets); - - // Compile an entry point to the JIT code - (gen_entry(cb, iseq, &function, start_ptr), jit.branch_iseqs) - }, - None => (None, vec![]), + let Some((start_ptr, gc_offsets, jit)) = gen_function(cb, iseq, &function) else { + debug!("Failed to compile iseq: gen_function failed: {}", iseq_get_location(iseq, 0)); + return std::ptr::null(); }; + // Compile an entry point to the JIT code + let Some(entry_ptr) = gen_entry(cb, iseq, &function, start_ptr) else { + debug!("Failed to compile iseq: gen_entry failed: {}", iseq_get_location(iseq, 0)); + return std::ptr::null(); + }; + + let mut branch_iseqs = jit.branch_iseqs; + // Recursively compile callee ISEQs + let caller_iseq = iseq; while let Some((branch, iseq)) = branch_iseqs.pop() { // Disable profiling. This will be the last use of the profiling information for the ISEQ. unsafe { rb_zjit_profile_disable(iseq); } // Compile the ISEQ - if let Some((callee_ptr, callee_branch_iseqs)) = gen_iseq(cb, iseq) { - let callee_addr = callee_ptr.raw_ptr(cb); - branch.regenerate(cb, |asm| { - asm.ccall(callee_addr, vec![]); - }); - branch_iseqs.extend(callee_branch_iseqs); - } else { + let Some((callee_ptr, callee_branch_iseqs)) = gen_iseq(cb, iseq) else { // Failed to compile the callee. Bail out of compiling this graph of ISEQs. + debug!("Failed to compile iseq: could not compile callee: {} -> {}", + iseq_get_location(caller_iseq, 0), iseq_get_location(iseq, 0)); return std::ptr::null(); - } + }; + let callee_addr = callee_ptr.raw_ptr(cb); + branch.regenerate(cb, |asm| { + asm.ccall(callee_addr, vec![]); + }); + branch_iseqs.extend(callee_branch_iseqs); } - // Return a JIT code address or a null pointer - start_ptr.map(|start_ptr| start_ptr.raw_ptr(cb)).unwrap_or(std::ptr::null()) + // Remember the block address to reuse it later + let payload = get_or_create_iseq_payload(iseq); + payload.start_ptr = Some(start_ptr); + append_gc_offsets(iseq, &gc_offsets); + + // Return a JIT code address + entry_ptr.raw_ptr(cb) } /// Write an entry to the perf map in /tmp @@ -1177,7 +1184,8 @@ fn compile_iseq(iseq: IseqPtr) -> Option { let mut function = match iseq_to_hir(iseq) { Ok(function) => function, Err(err) => { - debug!("ZJIT: iseq_to_hir: {err:?}"); + let name = crate::cruby::iseq_get_location(iseq, 0); + debug!("ZJIT: iseq_to_hir: {err:?}: {name}"); return None; } }; From f608095b84ed31af87f1e2529f89b8b0517e281a Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 29 Jul 2025 17:03:00 -0400 Subject: [PATCH 4/5] [ruby/mmtk] Fix clippy warnings https://github.com/ruby/mmtk/commit/45f991578e --- gc/mmtk/src/api.rs | 6 ++---- gc/mmtk/src/binding.rs | 2 +- gc/mmtk/src/collection.rs | 6 ++---- gc/mmtk/src/scanning.rs | 10 +++------- gc/mmtk/src/weak_proc.rs | 17 ++++++----------- 5 files changed, 14 insertions(+), 27 deletions(-) diff --git a/gc/mmtk/src/api.rs b/gc/mmtk/src/api.rs index a1b94d520d57f4..5ec39729c39866 100644 --- a/gc/mmtk/src/api.rs +++ b/gc/mmtk/src/api.rs @@ -108,8 +108,7 @@ pub extern "C" fn mmtk_builder_default() -> *mut MMTKBuilder { if !builder.options.threads.set(threads) { // MMTk will validate it and reject 0. eprintln!( - "[FATAL] Failed to set the number of MMTk threads to {}", - threads + "[FATAL] Failed to set the number of MMTk threads to {threads}" ); std::process::exit(1); } @@ -121,8 +120,7 @@ pub extern "C" fn mmtk_builder_default() -> *mut MMTKBuilder { if heap_min >= heap_max { eprintln!( - "[FATAL] MMTK_HEAP_MIN({}) >= MMTK_HEAP_MAX({})", - heap_min, heap_max + "[FATAL] MMTK_HEAP_MIN({heap_min}) >= MMTK_HEAP_MAX({heap_max})" ); std::process::exit(1); } diff --git a/gc/mmtk/src/binding.rs b/gc/mmtk/src/binding.rs index 619b7f246ce704..811cbf8abf8b32 100644 --- a/gc/mmtk/src/binding.rs +++ b/gc/mmtk/src/binding.rs @@ -119,7 +119,7 @@ impl RubyBinding { } pub fn register_wb_unprotected_object(&self, object: ObjectReference) { - debug!("Registering WB-unprotected object: {}", object); + debug!("Registering WB-unprotected object: {object}"); let mut objects = self.wb_unprotected_objects.lock().unwrap(); objects.insert(object); } diff --git a/gc/mmtk/src/collection.rs b/gc/mmtk/src/collection.rs index 0570b64e3a6012..34d5f45696a972 100644 --- a/gc/mmtk/src/collection.rs +++ b/gc/mmtk/src/collection.rs @@ -42,8 +42,7 @@ impl Collection for VMCollection { .spawn(move || { let ordinal = worker.ordinal; debug!( - "Hello! This is MMTk Worker Thread running! ordinal: {}", - ordinal + "Hello! This is MMTk Worker Thread running! ordinal: {ordinal}" ); crate::register_gc_thread(thread::current().id()); let ptr_worker = &mut *worker as *mut GCWorker; @@ -56,8 +55,7 @@ impl Collection for VMCollection { worker, ); debug!( - "An MMTk Worker Thread is quitting. Good bye! ordinal: {}", - ordinal + "An MMTk Worker Thread is quitting. Good bye! ordinal: {ordinal}" ); crate::unregister_gc_thread(thread::current().id()); }) diff --git a/gc/mmtk/src/scanning.rs b/gc/mmtk/src/scanning.rs index 36c0f998f4a3fe..66697ea56571cc 100644 --- a/gc/mmtk/src/scanning.rs +++ b/gc/mmtk/src/scanning.rs @@ -48,9 +48,7 @@ impl Scanning for VMScanning { let forwarded_target = object_tracer.trace_object(target_object); if forwarded_target != target_object { trace!( - " Forwarded target {} -> {}", - target_object, - forwarded_target + " Forwarded target {target_object} -> {forwarded_target}" ); } forwarded_target @@ -252,14 +250,12 @@ impl> GCWork for ScanWbUnprotectedRoots { for object in self.objects.iter().copied() { if object.is_reachable() { debug!( - "[wb_unprot_roots] Visiting WB-unprotected object (parent): {}", - object + "[wb_unprot_roots] Visiting WB-unprotected object (parent): {object}" ); (upcalls().scan_object_ruby_style)(object); } else { debug!( - "[wb_unprot_roots] Skipping young WB-unprotected object (parent): {}", - object + "[wb_unprot_roots] Skipping young WB-unprotected object (parent): {object}" ); } } diff --git a/gc/mmtk/src/weak_proc.rs b/gc/mmtk/src/weak_proc.rs index 204dd203aa333f..98f8c5abead143 100644 --- a/gc/mmtk/src/weak_proc.rs +++ b/gc/mmtk/src/weak_proc.rs @@ -103,7 +103,7 @@ impl GCWork for ProcessObjFreeCandidates { let n_cands = obj_free_candidates.len(); - debug!("Total: {} candidates", n_cands); + debug!("Total: {n_cands} candidates"); // Process obj_free let mut new_candidates = Vec::new(); @@ -113,9 +113,7 @@ impl GCWork for ProcessObjFreeCandidates { // Forward and add back to the candidate list. let new_object = object.forward(); trace!( - "Forwarding obj_free candidate: {} -> {}", - object, - new_object + "Forwarding obj_free candidate: {object} -> {new_object}" ); new_candidates.push(new_object); } else { @@ -158,11 +156,10 @@ trait GlobalTableProcessingWork { let forward_object = |_worker, object: ObjectReference, _pin| { debug_assert!( mmtk::memory_manager::is_mmtk_object(object.to_raw_address()).is_some(), - "{} is not an MMTk object", - object + "{object} is not an MMTk object" ); let result = object.forward(); - trace!("Forwarding reference: {} -> {}", object, result); + trace!("Forwarding reference: {object} -> {result}"); result }; @@ -217,13 +214,11 @@ impl GCWork for UpdateWbUnprotectedObjectsList { // Forward and add back to the candidate list. let new_object = object.forward(); trace!( - "Forwarding WB-unprotected object: {} -> {}", - object, - new_object + "Forwarding WB-unprotected object: {object} -> {new_object}" ); objects.insert(new_object); } else { - trace!("Removing WB-unprotected object from list: {}", object); + trace!("Removing WB-unprotected object from list: {object}"); } } From 1a4c0a99138186a0b53174639e9819f33621092f Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 29 Jul 2025 17:05:17 -0400 Subject: [PATCH 5/5] [ruby/mmtk] Fix warnings from cargo fmt https://github.com/ruby/mmtk/commit/84975a8840 --- gc/mmtk/src/api.rs | 8 ++------ gc/mmtk/src/collection.rs | 8 ++------ gc/mmtk/src/scanning.rs | 8 ++------ gc/mmtk/src/weak_proc.rs | 8 ++------ 4 files changed, 8 insertions(+), 24 deletions(-) diff --git a/gc/mmtk/src/api.rs b/gc/mmtk/src/api.rs index 5ec39729c39866..5217eb4a758da1 100644 --- a/gc/mmtk/src/api.rs +++ b/gc/mmtk/src/api.rs @@ -107,9 +107,7 @@ pub extern "C" fn mmtk_builder_default() -> *mut MMTKBuilder { if let Some(threads) = mmtk_builder_default_parse_threads() { if !builder.options.threads.set(threads) { // MMTk will validate it and reject 0. - eprintln!( - "[FATAL] Failed to set the number of MMTk threads to {threads}" - ); + eprintln!("[FATAL] Failed to set the number of MMTk threads to {threads}"); std::process::exit(1); } } @@ -119,9 +117,7 @@ pub extern "C" fn mmtk_builder_default() -> *mut MMTKBuilder { let heap_max = mmtk_builder_default_parse_heap_max(); if heap_min >= heap_max { - eprintln!( - "[FATAL] MMTK_HEAP_MIN({heap_min}) >= MMTK_HEAP_MAX({heap_max})" - ); + eprintln!("[FATAL] MMTK_HEAP_MIN({heap_min}) >= MMTK_HEAP_MAX({heap_max})"); std::process::exit(1); } diff --git a/gc/mmtk/src/collection.rs b/gc/mmtk/src/collection.rs index 34d5f45696a972..41c508afd9115d 100644 --- a/gc/mmtk/src/collection.rs +++ b/gc/mmtk/src/collection.rs @@ -41,9 +41,7 @@ impl Collection for VMCollection { .name("MMTk Worker Thread".to_string()) .spawn(move || { let ordinal = worker.ordinal; - debug!( - "Hello! This is MMTk Worker Thread running! ordinal: {ordinal}" - ); + debug!("Hello! This is MMTk Worker Thread running! ordinal: {ordinal}"); crate::register_gc_thread(thread::current().id()); let ptr_worker = &mut *worker as *mut GCWorker; let gc_thread_tls = @@ -54,9 +52,7 @@ impl Collection for VMCollection { GCThreadTLS::to_vwt(gc_thread_tls), worker, ); - debug!( - "An MMTk Worker Thread is quitting. Good bye! ordinal: {ordinal}" - ); + debug!("An MMTk Worker Thread is quitting. Good bye! ordinal: {ordinal}"); crate::unregister_gc_thread(thread::current().id()); }) .unwrap(), diff --git a/gc/mmtk/src/scanning.rs b/gc/mmtk/src/scanning.rs index 66697ea56571cc..af435813770a8a 100644 --- a/gc/mmtk/src/scanning.rs +++ b/gc/mmtk/src/scanning.rs @@ -47,9 +47,7 @@ impl Scanning for VMScanning { ); let forwarded_target = object_tracer.trace_object(target_object); if forwarded_target != target_object { - trace!( - " Forwarded target {target_object} -> {forwarded_target}" - ); + trace!(" Forwarded target {target_object} -> {forwarded_target}"); } forwarded_target }; @@ -249,9 +247,7 @@ impl> GCWork for ScanWbUnprotectedRoots { VMScanning::collect_object_roots_in("wb_unprot_roots", gc_tls, &mut self.factory, || { for object in self.objects.iter().copied() { if object.is_reachable() { - debug!( - "[wb_unprot_roots] Visiting WB-unprotected object (parent): {object}" - ); + debug!("[wb_unprot_roots] Visiting WB-unprotected object (parent): {object}"); (upcalls().scan_object_ruby_style)(object); } else { debug!( diff --git a/gc/mmtk/src/weak_proc.rs b/gc/mmtk/src/weak_proc.rs index 98f8c5abead143..0217673e36b842 100644 --- a/gc/mmtk/src/weak_proc.rs +++ b/gc/mmtk/src/weak_proc.rs @@ -112,9 +112,7 @@ impl GCWork for ProcessObjFreeCandidates { if object.is_reachable() { // Forward and add back to the candidate list. let new_object = object.forward(); - trace!( - "Forwarding obj_free candidate: {object} -> {new_object}" - ); + trace!("Forwarding obj_free candidate: {object} -> {new_object}"); new_candidates.push(new_object); } else { (upcalls().call_obj_free)(object); @@ -213,9 +211,7 @@ impl GCWork for UpdateWbUnprotectedObjectsList { if object.is_reachable() { // Forward and add back to the candidate list. let new_object = object.forward(); - trace!( - "Forwarding WB-unprotected object: {object} -> {new_object}" - ); + trace!("Forwarding WB-unprotected object: {object} -> {new_object}"); objects.insert(new_object); } else { trace!("Removing WB-unprotected object from list: {object}");