@@ -1130,11 +1130,31 @@ fn gen_store_field(asm: &mut Assembler, recv: Opnd, id: ID, offset: i32, val: Op
11301130}
11311131
11321132fn gen_write_barrier ( asm : & mut Assembler , recv : Opnd , val : Opnd , val_type : Type ) {
1133- // See RB_OBJ_WRITE/rb_obj_write: it's just assignment and rb_obj_written()->rb_gc_writebarrier()
1134- if !val_type. is_immediate ( ) {
1135- asm_comment ! ( asm, "Write barrier" ) ;
1133+ // See RB_OBJ_WRITE/rb_obj_write: it's just assignment and rb_obj_written().
1134+ // rb_obj_written() does: if (!RB_SPECIAL_CONST_P(val)) { rb_gc_writebarrier(recv, val); }
1135+ if val_type. is_immediate ( ) {
1136+ return ;
1137+ } else if val_type. is_heap_object ( ) {
1138+ asm_comment ! ( asm, "Write barrier with known heap object value" ) ;
11361139 let recv = asm. load ( recv) ;
11371140 asm_ccall ! ( asm, rb_gc_writebarrier, recv, val) ;
1141+ } else {
1142+ // Unknown if immediate or not, need to check because rb_gc_writebarrier() assumes not immediate
1143+ asm_comment ! ( asm, "Write barrier with unknown value" ) ;
1144+ let no_wb = asm. new_label ( "no_write_barrier_for_immediate" ) ;
1145+
1146+ // Continue if special constant
1147+ asm. test ( val, Opnd :: UImm ( RUBY_IMMEDIATE_MASK as u64 ) ) ;
1148+ asm. jnz ( no_wb. clone ( ) ) ;
1149+
1150+ // Continue if false
1151+ asm. cmp ( val, Qfalse . into ( ) ) ;
1152+ asm. je ( no_wb. clone ( ) ) ;
1153+
1154+ let recv = asm. load ( recv) ;
1155+ asm_ccall ! ( asm, rb_gc_writebarrier, recv, val) ;
1156+
1157+ asm. write_label ( no_wb) ;
11381158 }
11391159}
11401160
0 commit comments