@@ -668,7 +668,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
668668 Insn :: LoadSelf => gen_load_self ( ) ,
669669 & Insn :: LoadField { recv, id, offset, return_type } => gen_load_field ( asm, opnd ! ( recv) , id, offset, return_type) ,
670670 & Insn :: StoreField { recv, id, offset, val } => no_output ! ( gen_store_field( asm, opnd!( recv) , id, offset, opnd!( val) , function. type_of( val) ) ) ,
671- & Insn :: WriteBarrier { recv, val } => no_output ! ( gen_write_barrier( asm, opnd!( recv) , opnd!( val) , function. type_of( val) ) ) ,
671+ & Insn :: WriteBarrier { recv, val } => no_output ! ( gen_write_barrier( jit , asm, opnd!( recv) , opnd!( val) , function. type_of( val) ) ) ,
672672 & Insn :: IsBlockGiven { lep } => gen_is_block_given ( asm, opnd ! ( lep) ) ,
673673 Insn :: ArrayInclude { elements, target, state } => gen_array_include ( jit, asm, opnds ! ( elements) , opnd ! ( target) , & function. frame_state ( * state) ) ,
674674 Insn :: ArrayPackBuffer { elements, fmt, buffer, state } => gen_array_pack_buffer ( jit, asm, opnds ! ( elements) , opnd ! ( fmt) , opnd ! ( buffer) , & function. frame_state ( * state) ) ,
@@ -1286,13 +1286,35 @@ fn gen_store_field(asm: &mut Assembler, recv: Opnd, id: ID, offset: i32, val: Op
12861286 asm. store ( Opnd :: mem ( val_type. num_bits ( ) , recv, offset) , val) ;
12871287}
12881288
1289- fn gen_write_barrier ( asm : & mut Assembler , recv : Opnd , val : Opnd , val_type : Type ) {
1289+ fn gen_write_barrier ( jit : & mut JITState , asm : & mut Assembler , recv : Opnd , val : Opnd , val_type : Type ) {
12901290 // See RB_OBJ_WRITE/rb_obj_write: it's just assignment and rb_obj_written().
12911291 // rb_obj_written() does: if (!RB_SPECIAL_CONST_P(val)) { rb_gc_writebarrier(recv, val); }
12921292 if !val_type. is_immediate ( ) {
12931293 asm_comment ! ( asm, "Write barrier" ) ;
12941294 let recv = asm. load ( recv) ;
1295+
1296+ // Create a result block that all paths converge to
1297+ let hir_block_id = asm. current_block ( ) . hir_block_id ;
1298+ let rpo_idx = asm. current_block ( ) . rpo_index ;
1299+ let result_block = asm. new_block ( hir_block_id, false , rpo_idx) ;
1300+ let result_edge = Target :: Block ( lir:: BranchEdge { target : result_block, args : vec ! [ ] } ) ;
1301+
1302+ // If non-false immediate, don't fire write barrier
1303+ asm. test ( val, Opnd :: UImm ( RUBY_IMMEDIATE_MASK as u64 ) ) ;
1304+ asm. jnz ( jit, result_edge. clone ( ) ) ;
1305+
1306+ // If false, don't fire write barrier
1307+ asm. cmp ( val, Qfalse . into ( ) ) ;
1308+ asm. je ( jit, result_edge. clone ( ) ) ;
1309+
1310+ // Heap object; fire the write barrier
12951311 asm_ccall ! ( asm, rb_zjit_writebarrier_check_immediate, recv, val) ;
1312+ asm. jmp ( result_edge) ;
1313+
1314+ // Join block
1315+ asm. set_current_block ( result_block) ;
1316+ let label = jit. get_label ( asm, result_block, hir_block_id) ;
1317+ asm. write_label ( label) ;
12961318 }
12971319}
12981320
0 commit comments