@@ -405,6 +405,9 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
405405 & Insn :: ToArray { val, state } => { gen_to_array ( jit, asm, opnd ! ( val) , & function. frame_state ( state) ) } ,
406406 & Insn :: DefinedIvar { self_val, id, pushval, .. } => { gen_defined_ivar ( asm, opnd ! ( self_val) , id, pushval) } ,
407407 & Insn :: ArrayExtend { left, right, state } => { no_output ! ( gen_array_extend( jit, asm, opnd!( left) , opnd!( right) , & function. frame_state( state) ) ) } ,
408+ & Insn :: GuardShape { val, shape, state } => gen_guard_shape ( jit, asm, opnd ! ( val) , shape, & function. frame_state ( state) ) ,
409+ & Insn :: LoadIvarEmbedded { self_val, id, index } => gen_load_ivar_embedded ( asm, opnd ! ( self_val) , id, index) ,
410+ & Insn :: LoadIvarExtended { self_val, id, index } => gen_load_ivar_extended ( asm, opnd ! ( self_val) , id, index) ,
408411 & Insn :: ArrayMax { state, .. }
409412 | & Insn :: FixnumDiv { state, .. }
410413 | & Insn :: FixnumMod { state, .. }
@@ -716,6 +719,38 @@ fn gen_array_extend(jit: &mut JITState, asm: &mut Assembler, left: Opnd, right:
716719 asm_ccall ! ( asm, rb_ary_concat, left, right) ;
717720}
718721
722+ fn gen_guard_shape ( jit : & mut JITState , asm : & mut Assembler , val : Opnd , shape : ShapeId , state : & FrameState ) -> Opnd {
723+ let shape_id_offset = unsafe { rb_shape_id_offset ( ) } ;
724+ let val = asm. load ( val) ;
725+ let shape_opnd = Opnd :: mem ( SHAPE_ID_NUM_BITS as u8 , val, shape_id_offset) ;
726+ asm. cmp ( shape_opnd, Opnd :: UImm ( shape. 0 as u64 ) ) ;
727+ asm. jne ( side_exit ( jit, state, SideExitReason :: GuardShape ( shape) ) ) ;
728+ val
729+ }
730+
731+ fn gen_load_ivar_embedded ( asm : & mut Assembler , self_val : Opnd , id : ID , index : u16 ) -> Opnd {
732+ // See ROBJECT_FIELDS() from include/ruby/internal/core/robject.h
733+
734+ asm_comment ! ( asm, "Load embedded ivar id={} index={}" , id. contents_lossy( ) , index) ;
735+ let offs = ROBJECT_OFFSET_AS_ARY as i32 + ( SIZEOF_VALUE * index as usize ) as i32 ;
736+ let self_val = asm. load ( self_val) ;
737+ let ivar_opnd = Opnd :: mem ( 64 , self_val, offs) ;
738+ asm. load ( ivar_opnd)
739+ }
740+
741+ fn gen_load_ivar_extended ( asm : & mut Assembler , self_val : Opnd , id : ID , index : u16 ) -> Opnd {
742+ asm_comment ! ( asm, "Load extended ivar id={} index={}" , id. contents_lossy( ) , index) ;
743+ // Compile time value is *not* embedded.
744+
745+ // Get a pointer to the extended table
746+ let self_val = asm. load ( self_val) ;
747+ let tbl_opnd = asm. load ( Opnd :: mem ( 64 , self_val, ROBJECT_OFFSET_AS_HEAP_FIELDS as i32 ) ) ;
748+
749+ // Read the ivar from the extended table
750+ let ivar_opnd = Opnd :: mem ( 64 , tbl_opnd, ( SIZEOF_VALUE * index as usize ) as i32 ) ;
751+ asm. load ( ivar_opnd)
752+ }
753+
719754/// Compile an interpreter entry block to be inserted into an ISEQ
720755fn gen_entry_prologue ( asm : & mut Assembler , iseq : IseqPtr ) {
721756 asm_comment ! ( asm, "ZJIT entry point: {}" , iseq_get_location( iseq, 0 ) ) ;
@@ -1270,6 +1305,12 @@ fn gen_guard_type(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, guard
12701305
12711306 asm. cmp ( klass, Opnd :: Value ( expected_class) ) ;
12721307 asm. jne ( side_exit) ;
1308+ } else if guard_type. bit_equal ( types:: HeapObject ) {
1309+ let side_exit = side_exit ( jit, state, GuardType ( guard_type) ) ;
1310+ asm. cmp ( val, Opnd :: Value ( Qfalse ) ) ;
1311+ asm. je ( side_exit. clone ( ) ) ;
1312+ asm. test ( val, ( RUBY_IMMEDIATE_MASK as u64 ) . into ( ) ) ;
1313+ asm. jnz ( side_exit) ;
12731314 } else {
12741315 unimplemented ! ( "unsupported type: {guard_type}" ) ;
12751316 }
0 commit comments