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