@@ -564,6 +564,9 @@ pub enum Insn {
564564 return_type : Option < Type > , // None for unannotated builtins
565565 } ,
566566
567+ /// Parallel of `opt_aref_with` in the interpreter.
568+ ArefWith { receiver : InsnId , key : InsnId , send_state : InsnId , cd : * const rb_call_data } ,
569+
567570 /// Control flow instructions
568571 Return { val : InsnId } ,
569572 /// Non-local control flow. See the throw YARV instruction
@@ -849,6 +852,7 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
849852 Insn :: ToNewArray { val, .. } => write ! ( f, "ToNewArray {val}" ) ,
850853 Insn :: ArrayExtend { left, right, .. } => write ! ( f, "ArrayExtend {left}, {right}" ) ,
851854 Insn :: ArrayPush { array, val, .. } => write ! ( f, "ArrayPush {array}, {val}" ) ,
855+ Insn :: ArefWith { receiver, key, .. } => write ! ( f, "ArefWith {receiver}, {key}" ) ,
852856 Insn :: ObjToString { val, .. } => { write ! ( f, "ObjToString {val}" ) } ,
853857 Insn :: StringIntern { val, .. } => { write ! ( f, "StringIntern {val}" ) } ,
854858 Insn :: AnyToString { val, str, .. } => { write ! ( f, "AnyToString {val}, str: {str}" ) } ,
@@ -1289,6 +1293,7 @@ impl Function {
12891293 NewHash { elements : found_elements, state : find ! ( state) }
12901294 }
12911295 & NewRange { low, high, flag, state } => NewRange { low : find ! ( low) , high : find ! ( high) , flag, state : find ! ( state) } ,
1296+ & ArefWith { receiver : self_val, key, send_state, cd } => ArefWith { receiver : find ! ( self_val) , key : find ! ( key) , send_state : find ! ( send_state) , cd } ,
12921297 & ArrayMax { ref elements, state } => ArrayMax { elements : find_vec ! ( elements) , state : find ! ( state) } ,
12931298 & SetGlobal { id, val, state } => SetGlobal { id, val : find ! ( val) , state } ,
12941299 & GetIvar { self_val, id, state } => GetIvar { self_val : find ! ( self_val) , id, state } ,
@@ -1382,6 +1387,7 @@ impl Function {
13821387 Insn :: DefinedIvar { .. } => types:: BasicObject ,
13831388 Insn :: GetConstantPath { .. } => types:: BasicObject ,
13841389 Insn :: ArrayMax { .. } => types:: BasicObject ,
1390+ Insn :: ArefWith { .. } => types:: BasicObject ,
13851391 Insn :: GetGlobal { .. } => types:: BasicObject ,
13861392 Insn :: GetIvar { .. } => types:: BasicObject ,
13871393 Insn :: GetSpecialSymbol { .. } => types:: BasicObject ,
@@ -2018,6 +2024,7 @@ impl Function {
20182024 | & Insn :: FixnumDiv { left, right, state }
20192025 | & Insn :: FixnumMod { left, right, state }
20202026 | & Insn :: ArrayExtend { left, right, state }
2027+ | & Insn :: ArefWith { receiver : left, key : right, send_state : state, cd : _ }
20212028 => {
20222029 worklist. push_back ( left) ;
20232030 worklist. push_back ( right) ;
@@ -3193,23 +3200,18 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
31933200 // NB: opt_aref_with has an instruction argument for the call at get_arg(0)
31943201 let cd: * const rb_call_data = get_arg ( pc, 1 ) . as_ptr ( ) ;
31953202 let call_info = unsafe { rb_get_call_data_ci ( cd) } ;
3203+ let exit_id = fun. push_insn ( block, Insn :: Snapshot { state : exit_state } ) ;
31963204 if unknown_call_type ( unsafe { rb_vm_ci_flag ( call_info) } ) {
31973205 // Unknown call type; side-exit into the interpreter
3198- let exit_id = fun. push_insn ( block, Insn :: Snapshot { state : exit_state } ) ;
31993206 fun. push_insn ( block, Insn :: SideExit { state : exit_id, reason : SideExitReason :: UnknownCallType } ) ;
32003207 break ; // End the block
32013208 }
32023209 let argc = unsafe { vm_ci_argc ( ( * cd) . ci ) } ;
32033210
32043211 assert_eq ! ( 1 , argc, "opt_aref_with should only be emitted for argc=1" ) ;
3205- let aref_arg = fun. push_insn ( block, Insn :: Const { val : Const :: Value ( get_arg ( pc, 0 ) ) } ) ;
3206- let args = vec ! [ aref_arg] ;
3207-
3208- let mut send_state = state. clone ( ) ;
3209- send_state. stack_push ( aref_arg) ;
3210- let send_state = fun. push_insn ( block, Insn :: Snapshot { state : send_state } ) ;
3212+ let key = fun. push_insn ( block, Insn :: Const { val : Const :: Value ( get_arg ( pc, 0 ) ) } ) ;
32113213 let recv = state. stack_pop ( ) ?;
3212- let send = fun. push_insn ( block, Insn :: SendWithoutBlock { self_val : recv, cd , args , state : send_state } ) ;
3214+ let send = fun. push_insn ( block, Insn :: ArefWith { receiver : recv, key , cd , send_state : exit_id } ) ;
32133215 state. stack_push ( send) ;
32143216 }
32153217 YARVINSN_opt_neq => {
@@ -5229,8 +5231,8 @@ mod tests {
52295231 assert_snapshot ! ( hir_string( "test" ) , @r"
52305232 fn test@<compiled>:2:
52315233 bb0(v0:BasicObject, v1:BasicObject):
5232- v3 :StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
5233- v5:BasicObject = SendWithoutBlock v1, :[], v3
5234+ v4 :StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
5235+ v5:BasicObject = ArefWith v1, v4
52345236 CheckInterrupts
52355237 Return v5
52365238 " ) ;
0 commit comments