@@ -674,6 +674,7 @@ pub enum Insn {
674674 ArrayHash { elements : Vec < InsnId > , state : InsnId } ,
675675 ArrayMax { elements : Vec < InsnId > , state : InsnId } ,
676676 ArrayInclude { elements : Vec < InsnId > , target : InsnId , state : InsnId } ,
677+ ArrayPackBuffer { elements : Vec < InsnId > , fmt : InsnId , buffer : InsnId , state : InsnId } ,
677678 DupArrayInclude { ary : VALUE , target : InsnId , state : InsnId } ,
678679 /// Extend `left` with the elements from `right`. `left` and `right` must both be `Array`.
679680 ArrayExtend { left : InsnId , right : InsnId , state : InsnId } ,
@@ -1097,6 +1098,13 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
10971098 }
10981099 write ! ( f, " | {target}" )
10991100 }
1101+ Insn :: ArrayPackBuffer { elements, fmt, buffer, .. } => {
1102+ write ! ( f, "ArrayPackBuffer" ) ?;
1103+ for element in elements {
1104+ write ! ( f, "{element}, " ) ?;
1105+ }
1106+ write ! ( f, "fmt: {fmt}, buf: {buffer}" )
1107+ }
11001108 Insn :: DupArrayInclude { ary, target, .. } => {
11011109 write ! ( f, "DupArrayInclude {} | {}" , ary. print( self . ptr_map) , target)
11021110 }
@@ -1956,6 +1964,7 @@ impl Function {
19561964 & ArrayLength { array } => ArrayLength { array : find ! ( array) } ,
19571965 & ArrayMax { ref elements, state } => ArrayMax { elements : find_vec ! ( elements) , state : find ! ( state) } ,
19581966 & ArrayInclude { ref elements, target, state } => ArrayInclude { elements : find_vec ! ( elements) , target : find ! ( target) , state : find ! ( state) } ,
1967+ & ArrayPackBuffer { ref elements, fmt, buffer, state } => ArrayPackBuffer { elements : find_vec ! ( elements) , fmt : find ! ( fmt) , buffer : find ! ( buffer) , state : find ! ( state) } ,
19591968 & DupArrayInclude { ary, target, state } => DupArrayInclude { ary, target : find ! ( target) , state : find ! ( state) } ,
19601969 & ArrayHash { ref elements, state } => ArrayHash { elements : find_vec ! ( elements) , state } ,
19611970 & SetGlobal { id, val, state } => SetGlobal { id, val : find ! ( val) , state } ,
@@ -2110,6 +2119,7 @@ impl Function {
21102119 Insn :: FixnumBitCheck { .. } => types:: BoolExact ,
21112120 Insn :: ArrayMax { .. } => types:: BasicObject ,
21122121 Insn :: ArrayInclude { .. } => types:: BoolExact ,
2122+ Insn :: ArrayPackBuffer { .. } => types:: String ,
21132123 Insn :: DupArrayInclude { .. } => types:: BoolExact ,
21142124 Insn :: ArrayHash { .. } => types:: Fixnum ,
21152125 Insn :: GetGlobal { .. } => types:: BasicObject ,
@@ -3593,6 +3603,12 @@ impl Function {
35933603 worklist. push_back ( target) ;
35943604 worklist. push_back ( state) ;
35953605 }
3606+ & Insn :: ArrayPackBuffer { ref elements, fmt, buffer, state } => {
3607+ worklist. extend ( elements) ;
3608+ worklist. push_back ( fmt) ;
3609+ worklist. push_back ( buffer) ;
3610+ worklist. push_back ( state) ;
3611+ }
35963612 & Insn :: DupArrayInclude { target, state, .. } => {
35973613 worklist. push_back ( target) ;
35983614 worklist. push_back ( state) ;
@@ -4352,6 +4368,14 @@ impl Function {
43524368 }
43534369 Ok ( ( ) )
43544370 }
4371+ Insn :: ArrayPackBuffer { ref elements, fmt, buffer, .. } => {
4372+ self . assert_subtype ( insn_id, fmt, types:: BasicObject ) ?;
4373+ self . assert_subtype ( insn_id, buffer, types:: BasicObject ) ?;
4374+ for & element in elements {
4375+ self . assert_subtype ( insn_id, element, types:: BasicObject ) ?;
4376+ }
4377+ Ok ( ( ) )
4378+ }
43554379 // Instructions with a Vec of Ruby objects
43564380 Insn :: InvokeBlock { ref args, .. }
43574381 | Insn :: NewArray { elements : ref args, .. }
@@ -5201,6 +5225,12 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
52015225 let elements = state. stack_pop_n ( count - 1 ) ?;
52025226 ( BOP_INCLUDE_P , Insn :: ArrayInclude { elements, target, state : exit_id } )
52035227 }
5228+ VM_OPT_NEWARRAY_SEND_PACK_BUFFER => {
5229+ let buffer = state. stack_pop ( ) ?;
5230+ let fmt = state. stack_pop ( ) ?;
5231+ let elements = state. stack_pop_n ( count - 2 ) ?;
5232+ ( BOP_PACK , Insn :: ArrayPackBuffer { elements, fmt, buffer, state : exit_id } )
5233+ }
52045234 _ => {
52055235 // Unknown opcode; side-exit into the interpreter
52065236 fun. push_insn ( block, Insn :: SideExit { state : exit_id, reason : SideExitReason :: UnhandledNewarraySend ( method) } ) ;
0 commit comments