@@ -675,6 +675,7 @@ pub enum Insn {
675675 ArrayHash { elements : Vec < InsnId > , state : InsnId } ,
676676 ArrayMax { elements : Vec < InsnId > , state : InsnId } ,
677677 ArrayInclude { elements : Vec < InsnId > , target : InsnId , state : InsnId } ,
678+ ArrayPackBuffer { elements : Vec < InsnId > , fmt : InsnId , buffer : InsnId , state : InsnId } ,
678679 DupArrayInclude { ary : VALUE , target : InsnId , state : InsnId } ,
679680 /// Extend `left` with the elements from `right`. `left` and `right` must both be `Array`.
680681 ArrayExtend { left : InsnId , right : InsnId , state : InsnId } ,
@@ -1122,6 +1123,13 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
11221123 }
11231124 write ! ( f, " | {target}" )
11241125 }
1126+ Insn :: ArrayPackBuffer { elements, fmt, buffer, .. } => {
1127+ write ! ( f, "ArrayPackBuffer " ) ?;
1128+ for element in elements {
1129+ write ! ( f, "{element}, " ) ?;
1130+ }
1131+ write ! ( f, "fmt: {fmt}, buf: {buffer}" )
1132+ }
11251133 Insn :: DupArrayInclude { ary, target, .. } => {
11261134 write ! ( f, "DupArrayInclude {} | {}" , ary. print( self . ptr_map) , target)
11271135 }
@@ -1990,6 +1998,7 @@ impl Function {
19901998 & ArrayLength { array } => ArrayLength { array : find ! ( array) } ,
19911999 & ArrayMax { ref elements, state } => ArrayMax { elements : find_vec ! ( elements) , state : find ! ( state) } ,
19922000 & ArrayInclude { ref elements, target, state } => ArrayInclude { elements : find_vec ! ( elements) , target : find ! ( target) , state : find ! ( state) } ,
2001+ & ArrayPackBuffer { ref elements, fmt, buffer, state } => ArrayPackBuffer { elements : find_vec ! ( elements) , fmt : find ! ( fmt) , buffer : find ! ( buffer) , state : find ! ( state) } ,
19932002 & DupArrayInclude { ary, target, state } => DupArrayInclude { ary, target : find ! ( target) , state : find ! ( state) } ,
19942003 & ArrayHash { ref elements, state } => ArrayHash { elements : find_vec ! ( elements) , state } ,
19952004 & SetGlobal { id, val, state } => SetGlobal { id, val : find ! ( val) , state } ,
@@ -2144,6 +2153,7 @@ impl Function {
21442153 Insn :: FixnumBitCheck { .. } => types:: BoolExact ,
21452154 Insn :: ArrayMax { .. } => types:: BasicObject ,
21462155 Insn :: ArrayInclude { .. } => types:: BoolExact ,
2156+ Insn :: ArrayPackBuffer { .. } => types:: String ,
21472157 Insn :: DupArrayInclude { .. } => types:: BoolExact ,
21482158 Insn :: ArrayHash { .. } => types:: Fixnum ,
21492159 Insn :: GetGlobal { .. } => types:: BasicObject ,
@@ -3658,6 +3668,12 @@ impl Function {
36583668 worklist. push_back ( target) ;
36593669 worklist. push_back ( state) ;
36603670 }
3671+ & Insn :: ArrayPackBuffer { ref elements, fmt, buffer, state } => {
3672+ worklist. extend ( elements) ;
3673+ worklist. push_back ( fmt) ;
3674+ worklist. push_back ( buffer) ;
3675+ worklist. push_back ( state) ;
3676+ }
36613677 & Insn :: DupArrayInclude { target, state, .. } => {
36623678 worklist. push_back ( target) ;
36633679 worklist. push_back ( state) ;
@@ -4417,6 +4433,14 @@ impl Function {
44174433 }
44184434 Ok ( ( ) )
44194435 }
4436+ Insn :: ArrayPackBuffer { ref elements, fmt, buffer, .. } => {
4437+ self . assert_subtype ( insn_id, fmt, types:: BasicObject ) ?;
4438+ self . assert_subtype ( insn_id, buffer, types:: BasicObject ) ?;
4439+ for & element in elements {
4440+ self . assert_subtype ( insn_id, element, types:: BasicObject ) ?;
4441+ }
4442+ Ok ( ( ) )
4443+ }
44204444 // Instructions with a Vec of Ruby objects
44214445 Insn :: InvokeBlock { ref args, .. }
44224446 | Insn :: NewArray { elements : ref args, .. }
@@ -5266,6 +5290,12 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
52665290 let elements = state. stack_pop_n ( count - 1 ) ?;
52675291 ( BOP_INCLUDE_P , Insn :: ArrayInclude { elements, target, state : exit_id } )
52685292 }
5293+ VM_OPT_NEWARRAY_SEND_PACK_BUFFER => {
5294+ let buffer = state. stack_pop ( ) ?;
5295+ let fmt = state. stack_pop ( ) ?;
5296+ let elements = state. stack_pop_n ( count - 2 ) ?;
5297+ ( BOP_PACK , Insn :: ArrayPackBuffer { elements, fmt, buffer, state : exit_id } )
5298+ }
52695299 _ => {
52705300 // Unknown opcode; side-exit into the interpreter
52715301 fun. push_insn ( block, Insn :: SideExit { state : exit_id, reason : SideExitReason :: UnhandledNewarraySend ( method) } ) ;
0 commit comments