From 24d0b458cd6ccde1e052c1db15af120def349693 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 6 Aug 2025 11:09:51 -0400 Subject: [PATCH 1/2] Make Random write-barrier protected --- random.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/random.c b/random.c index 1611c3db978bd9..85d72057cd6997 100644 --- a/random.c +++ b/random.c @@ -263,7 +263,7 @@ const rb_data_type_t rb_random_data_type = { random_free, random_memsize, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED }; #define random_mt_mark rb_random_mark @@ -284,7 +284,7 @@ static const rb_data_type_t random_mt_type = { }, &rb_random_data_type, (void *)&random_mt_if, - RUBY_TYPED_FREE_IMMEDIATELY + RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED }; static rb_random_t * @@ -422,10 +422,10 @@ random_init(int argc, VALUE *argv, VALUE obj) argc = rb_check_arity(argc, 0, 1); rb_check_frozen(obj); if (argc == 0) { - rnd->seed = rand_init_default(rng, rnd); + RB_OBJ_WRITE(obj, &rnd->seed, rand_init_default(rng, rnd)); } else { - rnd->seed = rand_init(rng, rnd, rb_to_int(argv[0])); + RB_OBJ_WRITE(obj, &rnd->seed, rand_init(rng, rnd, rb_to_int(argv[0]))); } return obj; } From a260bbc550adf2a685e40ea492334a1d1f3a0222 Mon Sep 17 00:00:00 2001 From: Max Bernstein Date: Thu, 7 Aug 2025 11:28:10 -0700 Subject: [PATCH 2/2] ZJIT: Set PC before StringCopy (#14141) ZJIT: Set PC before StringCopy This function allocates. --- zjit/src/codegen.rs | 5 ++-- zjit/src/hir.rs | 64 +++++++++++++++++++++++---------------------- 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index b05aaca68222ae..a5439bf2ca1723 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -329,7 +329,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio 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::ArrayDup { val, state } => gen_array_dup(asm, opnd!(val), &function.frame_state(*state)), - Insn::StringCopy { val, chilled } => gen_string_copy(asm, opnd!(val), *chilled), + Insn::StringCopy { val, chilled, state } => gen_string_copy(asm, opnd!(val), *chilled, &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), @@ -871,8 +871,9 @@ fn gen_send_without_block_direct( } /// Compile a string resurrection -fn gen_string_copy(asm: &mut Assembler, recv: Opnd, chilled: bool) -> Opnd { +fn gen_string_copy(asm: &mut Assembler, recv: Opnd, chilled: bool, state: &FrameState) -> Opnd { // TODO: split rb_ec_str_resurrect into separate functions + gen_prepare_call_with_gc(asm, state); let chilled = if chilled { Opnd::Imm(1) } else { Opnd::Imm(0) }; asm_ccall!(asm, rb_ec_str_resurrect, EC, recv, chilled) } diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index 7e92f5932922a8..f4dae3f0ec1352 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -443,7 +443,7 @@ pub enum Insn { /// SSA block parameter. Also used for function parameters in the function's entry block. Param { idx: usize }, - StringCopy { val: InsnId, chilled: bool }, + StringCopy { val: InsnId, chilled: bool, state: InsnId }, StringIntern { val: InsnId }, /// Put special object (VMCORE, CBASE, etc.) based on value_type @@ -1116,7 +1116,7 @@ impl Function { }, &Return { val } => Return { val: find!(val) }, &Throw { throw_state, val } => Throw { throw_state, val: find!(val) }, - &StringCopy { val, chilled } => StringCopy { val: find!(val), chilled }, + &StringCopy { val, chilled, state } => StringCopy { val: find!(val), chilled, state }, &StringIntern { val } => StringIntern { val: find!(val) }, &Test { val } => Test { val: find!(val) }, &IsNil { val } => IsNil { val: find!(val) }, @@ -1870,7 +1870,6 @@ impl Function { worklist.push_back(high); worklist.push_back(state); } - &Insn::StringCopy { val, .. } | &Insn::StringIntern { val } | &Insn::Return { val } | &Insn::Throw { val, .. } @@ -1880,6 +1879,7 @@ impl Function { | &Insn::IsNil { val } => worklist.push_back(val), &Insn::SetGlobal { val, state, .. } + | &Insn::StringCopy { val, state, .. } | &Insn::GuardType { val, state, .. } | &Insn::GuardBitEquals { val, state, .. } | &Insn::ToArray { val, state } @@ -2667,12 +2667,14 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result { } YARVINSN_putstring => { let val = fun.push_insn(block, Insn::Const { val: Const::Value(get_arg(pc, 0)) }); - let insn_id = fun.push_insn(block, Insn::StringCopy { val, chilled: false }); + let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state }); + let insn_id = fun.push_insn(block, Insn::StringCopy { val, chilled: false, state: exit_id }); state.stack_push(insn_id); } YARVINSN_putchilledstring => { let val = fun.push_insn(block, Insn::Const { val: Const::Value(get_arg(pc, 0)) }); - let insn_id = fun.push_insn(block, Insn::StringCopy { val, chilled: true }); + let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state }); + let insn_id = fun.push_insn(block, Insn::StringCopy { val, chilled: true, state: exit_id }); state.stack_push(insn_id); } YARVINSN_putself => { state.stack_push(self_param); } @@ -3862,8 +3864,8 @@ mod tests { fn test@:1: bb0(v0:BasicObject): v2:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000)) - v3:StringExact = StringCopy v2 - Return v3 + v4:StringExact = StringCopy v2 + Return v4 "#]]); } @@ -4390,11 +4392,11 @@ mod tests { v5:ArrayExact[VALUE(0x1008)] = Const Value(VALUE(0x1008)) v7:ArrayExact = ArrayDup v5 v8:StringExact[VALUE(0x1010)] = Const Value(VALUE(0x1010)) - v9:StringExact = StringCopy v8 - v10:StringExact[VALUE(0x1010)] = Const Value(VALUE(0x1010)) - v11:StringExact = StringCopy v10 - v13:BasicObject = SendWithoutBlock v0, :unknown_method, v4, v7, v9, v11 - Return v13 + v10:StringExact = StringCopy v8 + v11:StringExact[VALUE(0x1010)] = Const Value(VALUE(0x1010)) + v13:StringExact = StringCopy v11 + v15:BasicObject = SendWithoutBlock v0, :unknown_method, v4, v7, v10, v13 + Return v15 "#]]); } @@ -4640,7 +4642,7 @@ mod tests { v4:NilClass = Const Value(nil) v7:BasicObject = SendWithoutBlock v1, :+, v2 v8:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000)) - v9:StringExact = StringCopy v8 + v10:StringExact = StringCopy v8 SideExit UnknownNewarraySend(PACK) "#]]); } @@ -5943,8 +5945,8 @@ mod opt_tests { assert_optimized_method_hir("test", expect![[r#" fn test@:3: bb0(v0:BasicObject): - v5:Fixnum[5] = Const Value(5) - Return v5 + v6:Fixnum[5] = Const Value(5) + Return v6 "#]]); } @@ -6572,10 +6574,10 @@ mod opt_tests { fn test@:2: bb0(v0:BasicObject): v2:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000)) - v3:StringExact = StringCopy v2 + v4:StringExact = StringCopy v2 PatchPoint MethodRedefined(String@0x1008, bytesize@0x1010, cme:0x1018) - v8:Fixnum = CCall bytesize@0x1040, v3 - Return v8 + v9:Fixnum = CCall bytesize@0x1040, v4 + Return v9 "#]]); } @@ -6918,10 +6920,10 @@ mod opt_tests { fn test@:2: bb0(v0:BasicObject): v2:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000)) - v3:StringExact = StringCopy v2 - v5:BasicObject = SendWithoutBlock v3, :dup - v7:BasicObject = SendWithoutBlock v5, :freeze - Return v7 + v4:StringExact = StringCopy v2 + v6:BasicObject = SendWithoutBlock v4, :dup + v8:BasicObject = SendWithoutBlock v6, :freeze + Return v8 "#]]); } @@ -6934,10 +6936,10 @@ mod opt_tests { fn test@:2: bb0(v0:BasicObject): v2:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000)) - v3:StringExact = StringCopy v2 - v4:NilClass = Const Value(nil) - v6:BasicObject = SendWithoutBlock v3, :freeze, v4 - Return v6 + v4:StringExact = StringCopy v2 + v5:NilClass = Const Value(nil) + v7:BasicObject = SendWithoutBlock v4, :freeze, v5 + Return v7 "#]]); } @@ -6979,10 +6981,10 @@ mod opt_tests { fn test@:2: bb0(v0:BasicObject): v2:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000)) - v3:StringExact = StringCopy v2 - v5:BasicObject = SendWithoutBlock v3, :dup - v7:BasicObject = SendWithoutBlock v5, :-@ - Return v7 + v4:StringExact = StringCopy v2 + v6:BasicObject = SendWithoutBlock v4, :dup + v8:BasicObject = SendWithoutBlock v6, :-@ + Return v8 "#]]); } @@ -6996,7 +6998,7 @@ mod opt_tests { bb0(v0:BasicObject): v2:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000)) v3:StringExact[VALUE(0x1008)] = Const Value(VALUE(0x1008)) - v4:StringExact = StringCopy v3 + v5:StringExact = StringCopy v3 SideExit UnknownOpcode(concatstrings) "#]]); }