@@ -8051,7 +8051,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
80518051 } ) ;
80528052
80538053 let result = if is_ifunc {
8054- // Get the local EP to load the block handler
8054+ // Load the block handler from LEP
80558055 let level = get_lvar_level ( fun. iseq ) ;
80568056 let lep = fun. push_insn ( block, Insn :: GetEP { level } ) ;
80578057 let block_handler = fun. push_insn ( block, Insn :: LoadField {
@@ -8061,23 +8061,34 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
80618061 return_type : types:: CInt64 ,
80628062 } ) ;
80638063
8064- // Guard that the block handler is an IFUNC (tag bits & 0x3 == 0x3),
8065- // matching VM_BH_IFUNC_P() in the interpreter.
8064+ // Check IFUNC tag: (block_handler & 0x3) == 0x3
80668065 let tag_mask = fun. push_insn ( block, Insn :: Const { val : Const :: CInt64 ( 0x3 ) } ) ;
80678066 let tag_bits = fun. push_insn ( block, Insn :: IntAnd { left : block_handler, right : tag_mask } ) ;
8068- fun. push_insn ( block, Insn :: GuardBitEquals {
8069- val : tag_bits,
8070- expected : Const :: CInt64 ( 0x3 ) ,
8071- reason : SideExitReason :: InvokeBlockNotIfunc ,
8072- state : exit_id,
8073- } ) ;
8067+ let ifunc_tag = fun. push_insn ( block, Insn :: Const { val : Const :: CInt64 ( 0x3 ) } ) ;
8068+ let is_ifunc_match = fun. push_insn ( block, Insn :: IsBitEqual { left : tag_bits, right : ifunc_tag } ) ;
80748069
8075- fun. push_insn ( block, Insn :: InvokeBlockIfunc {
8070+ // Branch: on match, call InvokeBlockIfunc directly
8071+ let join_block = fun. new_block ( insn_idx) ;
8072+ let join_param = fun. push_insn ( join_block, Insn :: Param ) ;
8073+ let ifunc_block = fun. new_block ( insn_idx) ;
8074+ fun. push_insn ( block, Insn :: IfTrue { val : is_ifunc_match, target : BranchEdge { target : ifunc_block, args : vec ! [ ] } } ) ;
8075+ let ifunc_result = fun. push_insn ( ifunc_block, Insn :: InvokeBlockIfunc {
80768076 cd,
80778077 block_handler,
8078- args,
8078+ args : args . clone ( ) ,
80798079 state : exit_id,
8080- } )
8080+ } ) ;
8081+ fun. push_insn ( ifunc_block, Insn :: Jump ( BranchEdge { target : join_block, args : vec ! [ ifunc_result] } ) ) ;
8082+
8083+ // In the fallthrough case, use generic rb_vm_invokeblock and join
8084+ let fallback_result = fun. push_insn ( block, Insn :: InvokeBlock {
8085+ cd, args, state : exit_id, reason : InvokeBlockNotSpecialized ,
8086+ } ) ;
8087+ fun. push_insn ( block, Insn :: Jump ( BranchEdge { target : join_block, args : vec ! [ fallback_result] } ) ) ;
8088+
8089+ // Continue compilation from the join block
8090+ block = join_block;
8091+ join_param
80818092 } else {
80828093 fun. push_insn ( block, Insn :: InvokeBlock { cd, args, state : exit_id, reason : InvokeBlockNotSpecialized } )
80838094 } ;
0 commit comments