@@ -371,7 +371,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
371371 Insn :: SetGlobal { id, val, state } => return gen_setglobal ( jit, asm, * id, opnd ! ( val) , & function. frame_state ( * state) ) ,
372372 Insn :: GetGlobal { id, state : _ } => gen_getglobal ( asm, * id) ,
373373 & Insn :: GetLocal { ep_offset, level } => gen_getlocal_with_ep ( asm, ep_offset, level) ?,
374- Insn :: SetLocal { val, ep_offset, level } => return gen_setlocal_with_ep ( asm, opnd ! ( val) , * ep_offset, * level) ,
374+ & Insn :: SetLocal { val, ep_offset, level } => return gen_setlocal_with_ep ( asm, jit , function , val, ep_offset, level) ,
375375 Insn :: GetConstantPath { ic, state } => gen_get_constant_path ( jit, asm, * ic, & function. frame_state ( * state) ) ?,
376376 Insn :: SetIvar { self_val, id, val, state : _ } => return gen_setivar ( asm, opnd ! ( self_val) , * id, opnd ! ( val) ) ,
377377 Insn :: SideExit { state, reason } => return gen_side_exit ( jit, asm, reason, & function. frame_state ( * state) ) ,
@@ -506,21 +506,19 @@ fn gen_getlocal_with_ep(asm: &mut Assembler, local_ep_offset: u32, level: u32) -
506506/// Set a local variable from a higher scope or the heap. `local_ep_offset` is in number of VALUEs.
507507/// We generate this instruction with level=0 only when the local variable is on the heap, so we
508508/// can't optimize the level=0 case using the SP register.
509- fn gen_setlocal_with_ep ( asm : & mut Assembler , val : Opnd , local_ep_offset : u32 , level : u32 ) -> Option < ( ) > {
509+ fn gen_setlocal_with_ep ( asm : & mut Assembler , jit : & JITState , function : & Function , val : InsnId , local_ep_offset : u32 , level : u32 ) -> Option < ( ) > {
510510 let ep = gen_get_ep ( asm, level) ;
511- match val {
512- // If we're writing a constant, non-heap VALUE, do a raw memory write without
513- // running write barrier.
514- lir :: Opnd :: Value ( const_val ) if const_val . special_const_p ( ) => {
515- let offset = -( SIZEOF_VALUE_I32 * i32:: try_from ( local_ep_offset) . ok ( ) ?) ;
516- asm. mov ( Opnd :: mem ( 64 , ep, offset) , val) ;
517- }
511+
512+ // When we've proved that we're writing an immediate,
513+ // we can skip the write barrier.
514+ if function . type_of ( val ) . is_immediate ( ) {
515+ let offset = -( SIZEOF_VALUE_I32 * i32:: try_from ( local_ep_offset) . ok ( ) ?) ;
516+ asm. mov ( Opnd :: mem ( 64 , ep, offset) , jit . get_opnd ( val) ? ) ;
517+ } else {
518518 // We're potentially writing a reference to an IMEMO/env object,
519519 // so take care of the write barrier with a function.
520- _ => {
521- let local_index = c_int:: try_from ( local_ep_offset) . ok ( ) . and_then ( |idx| idx. checked_mul ( -1 ) ) ?;
522- asm_ccall ! ( asm, rb_vm_env_write, ep, local_index. into( ) , val) ;
523- }
520+ let local_index = c_int:: try_from ( local_ep_offset) . ok ( ) . and_then ( |idx| idx. checked_mul ( -1 ) ) ?;
521+ asm_ccall ! ( asm, rb_vm_env_write, ep, local_index. into( ) , jit. get_opnd( val) ?) ;
524522 }
525523 Some ( ( ) )
526524}
0 commit comments