@@ -107,6 +107,8 @@ fn annotate_builtin_method(props_map: &mut HashMap<*mut c_void, FnProperties>, c
107107
108108 // Scan through the ISEQ to find invokebuiltin instructions
109109 let mut insn_idx: u32 = 0 ;
110+ let mut func_ptr = std:: ptr:: null_mut :: < c_void > ( ) ;
111+
110112 while insn_idx < encoded_size {
111113 // Get the PC for this instruction index
112114 let pc = rb_iseq_pc_at_idx ( iseq, insn_idx) ;
@@ -120,13 +122,22 @@ fn annotate_builtin_method(props_map: &mut HashMap<*mut c_void, FnProperties>, c
120122 // The first operand is the builtin function pointer
121123 let bf_value = * pc. add ( 1 ) ;
122124 let bf_ptr = bf_value. as_ptr ( ) as * const rb_builtin_function ;
123- let func_ptr = ( * bf_ptr) . func_ptr as * mut c_void ;
124- props_map. insert ( func_ptr, props) ;
125+
126+ if func_ptr. is_null ( ) {
127+ func_ptr = ( * bf_ptr) . func_ptr as * mut c_void ;
128+ } else {
129+ panic ! ( "Multiple invokebuiltin instructions found in ISEQ for {}#{}" ,
130+ std:: ffi:: CStr :: from_ptr( rb_class2name( class) ) . to_str( ) . unwrap_or( "?" ) ,
131+ method_name) ;
132+ }
125133 }
126134
127135 // Move to the next instruction using the proper length
128136 insn_idx = insn_idx. saturating_add ( rb_insn_len ( VALUE ( opcode as usize ) ) . try_into ( ) . unwrap ( ) ) ;
129137 }
138+
139+ // Only insert the properties if its iseq has exactly one invokebuiltin instruction
140+ props_map. insert ( func_ptr, props) ;
130141 }
131142}
132143
0 commit comments