From 7ca3b38a952c4972f1ee3892836d4848047db606 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Tue, 22 Jul 2025 13:58:14 -0500 Subject: [PATCH 1/3] [DOC] Tweak for String#dump --- doc/string.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/string.rb b/doc/string.rb index d68b40743b9d77..ad1abf29b7f55b 100644 --- a/doc/string.rb +++ b/doc/string.rb @@ -460,8 +460,7 @@ # # _Substitution_ # -# - #dump: Returns a copy of +self+ with all non-printing characters replaced by \xHH notation -# and all special characters escaped. +# - #dump: Returns a printable version of +self+, enclosed in double-quotes. # - #undump: Returns a copy of +self+ with all \xNN notations replaced by \uNNNN notations # and all escaped characters unescaped. # - #sub: Returns a copy of +self+ with the first substring matching a given pattern From 465b1696adb0a9e6af8623ca6caaae69b71831be Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Tue, 22 Jul 2025 13:53:27 -0500 Subject: [PATCH 2/3] [DOC] Tweaks for String#each_byte --- doc/string/each_byte.rdoc | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/doc/string/each_byte.rdoc b/doc/string/each_byte.rdoc index 643118fea3e47e..1f1069863b264b 100644 --- a/doc/string/each_byte.rdoc +++ b/doc/string/each_byte.rdoc @@ -1,17 +1,18 @@ -Calls the given block with each successive byte from +self+; +With a block given, calls the block with each successive byte from +self+; returns +self+: - 'hello'.each_byte {|byte| print byte, ' ' } - print "\n" - 'тест'.each_byte {|byte| print byte, ' ' } - print "\n" - 'こんにちは'.each_byte {|byte| print byte, ' ' } - print "\n" + a = [] + 'hello'.each_byte {|byte| a.push(byte) } # Five 1-byte characters. + a # => [104, 101, 108, 108, 111] + a = [] + 'тест'.each_byte {|byte| a.push(byte) } # Four 2-byte characters. + a # => [209, 130, 208, 181, 209, 129, 209, 130] + a = [] + 'こんにちは'.each_byte {|byte| a.push(byte) } # Five 3-byte characters. + a # => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175] -Output: +With no block given, returns an enumerator. + +Related: see {Iterating}[rdoc-ref:String@Iterating]. - 104 101 108 108 111 - 209 130 208 181 209 129 209 130 - 227 129 147 227 130 147 227 129 171 227 129 161 227 129 175 -Returns an enumerator if no block is given. From 33363030e1846c9f2cdbdcc9b77c11efbda3d522 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Tue, 22 Jul 2025 15:49:36 -0400 Subject: [PATCH 3/3] ZJIT: Use rb_vm_env_write() for `hir::Insn::SetLocal` We weren't firing write barriers before when writing to imemo/env objects. Wbcheck caught this with test/ruby/test_refinement.rb: ruby -v: ruby 3.5.0dev (2025-07-22T17:05:58Z wbcheck 2569a80954) +ZJIT dev +PRISM +GC[wbcheck] [x86_64-linux] WBCHECK ERROR: Missed write barrier detected! Parent object: 0x558de9f4e6e0 (wb_protected: true) rb_obj_info_dump: 0x0000558de9f4e6e0 T_IMEMO/ Reference counts - snapshot: 3, writebarrier: 0, current: 4, missed: 1 Missing reference to: 0x558decf37c30 rb_obj_info_dump: 0x0000558decf37c30 method/UnboundMethod method WBCHECK SUMMARY: Found 1 objects with missed write barriers (1 total violations) --- zjit/src/codegen.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index 54346e077806c4..fee6537c375d49 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -1,5 +1,6 @@ use std::cell::Cell; use std::rc::Rc; +use std::ffi::{c_int}; use crate::asm::Label; use crate::backend::current::{Reg, ALLOC_REGS}; @@ -446,8 +447,20 @@ fn gen_getlocal_with_ep(asm: &mut Assembler, local_ep_offset: u32, level: u32) - /// can't optimize the level=0 case using the SP register. fn gen_setlocal_with_ep(asm: &mut Assembler, val: Opnd, local_ep_offset: u32, level: u32) -> Option<()> { let ep = gen_get_ep(asm, level); - let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).ok()?); - asm.mov(Opnd::mem(64, ep, offset), val); + match val { + // If we're writing a constant, non-heap VALUE, do a raw memory write without + // running write barrier. + lir::Opnd::Value(const_val) if const_val.special_const_p() => { + let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).ok()?); + asm.mov(Opnd::mem(64, ep, offset), val); + } + // 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(), val); + } + } Some(()) }