@@ -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) ) ,
@@ -488,21 +488,19 @@ fn gen_getlocal_with_ep(asm: &mut Assembler, local_ep_offset: u32, level: u32) -
488488/// Set a local variable from a higher scope or the heap. `local_ep_offset` is in number of VALUEs.
489489/// We generate this instruction with level=0 only when the local variable is on the heap, so we
490490/// can't optimize the level=0 case using the SP register.
491- fn gen_setlocal_with_ep ( asm : & mut Assembler , val : Opnd , local_ep_offset : u32 , level : u32 ) -> Option < ( ) > {
491+ fn gen_setlocal_with_ep ( asm : & mut Assembler , jit : & JITState , function : & Function , val : InsnId , local_ep_offset : u32 , level : u32 ) -> Option < ( ) > {
492492 let ep = gen_get_ep ( asm, level) ;
493- match val {
494- // If we're writing a constant, non-heap VALUE, do a raw memory write without
495- // running write barrier.
496- lir :: Opnd :: Value ( const_val ) if const_val . special_const_p ( ) => {
497- let offset = -( SIZEOF_VALUE_I32 * i32:: try_from ( local_ep_offset) . ok ( ) ?) ;
498- asm. mov ( Opnd :: mem ( 64 , ep, offset) , val) ;
499- }
493+
494+ // When we've proved that we're writing an immediate,
495+ // we can skip the write barrier.
496+ if function . is_a ( val , types :: Immediate ) {
497+ let offset = -( SIZEOF_VALUE_I32 * i32:: try_from ( local_ep_offset) . ok ( ) ?) ;
498+ asm. mov ( Opnd :: mem ( 64 , ep, offset) , jit . get_opnd ( val) ? ) ;
499+ } else {
500500 // We're potentially writing a reference to an IMEMO/env object,
501501 // so take care of the write barrier with a function.
502- _ => {
503- let local_index = c_int:: try_from ( local_ep_offset) . ok ( ) . and_then ( |idx| idx. checked_mul ( -1 ) ) ?;
504- asm_ccall ! ( asm, rb_vm_env_write, ep, local_index. into( ) , val) ;
505- }
502+ let local_index = c_int:: try_from ( local_ep_offset) . ok ( ) . and_then ( |idx| idx. checked_mul ( -1 ) ) ?;
503+ asm_ccall ! ( asm, rb_vm_env_write, ep, local_index. into( ) , jit. get_opnd( val) ?) ;
506504 }
507505 Some ( ( ) )
508506}
0 commit comments