@@ -507,6 +507,7 @@ pub enum Insn {
507507 // Distinct from `SendWithoutBlock` with `mid:to_s` because does not have a patch point for String to_s being redefined
508508 ObjToString { val : InsnId , call_info : CallInfo , cd : * const rb_call_data , state : InsnId } ,
509509 AnyToString { val : InsnId , str : InsnId , state : InsnId } ,
510+ ConcatStrings { strings : Vec < InsnId > , state : InsnId } ,
510511
511512 /// Side-exit if val doesn't have the expected type.
512513 GuardType { val : InsnId , guard_type : Type , state : InsnId } ,
@@ -683,7 +684,14 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
683684 write ! ( f, ", {arg}" ) ?;
684685 }
685686 Ok ( ( ) )
686- } ,
687+ }
688+ Insn :: ConcatStrings { strings, state : _ } => {
689+ write ! ( f, "ConcatStrings {}" , strings[ 0 ] ) ?;
690+ for string in strings. iter ( ) . skip ( 1 ) {
691+ write ! ( f, ", {string}" ) ?;
692+ }
693+ Ok ( ( ) )
694+ }
687695 Insn :: Snapshot { state } => write ! ( f, "Snapshot {}" , state) ,
688696 Insn :: Defined { op_type, v, .. } => {
689697 // op_type (enum defined_type) printing logic from iseq.c.
@@ -1066,6 +1074,7 @@ impl Function {
10661074 str : find ! ( * str ) ,
10671075 state : * state,
10681076 } ,
1077+ ConcatStrings { state, strings } => ConcatStrings { state : * state, strings : find_vec ! ( strings) } ,
10691078 SendWithoutBlock { self_val, call_info, cd, args, state } => SendWithoutBlock {
10701079 self_val : find ! ( * self_val) ,
10711080 call_info : call_info. clone ( ) ,
@@ -1197,6 +1206,7 @@ impl Function {
11971206 Insn :: ToArray { .. } => types:: ArrayExact ,
11981207 Insn :: ObjToString { .. } => types:: BasicObject ,
11991208 Insn :: AnyToString { .. } => types:: String ,
1209+ Insn :: ConcatStrings { .. } => types:: StringExact ,
12001210 Insn :: GetLocal { .. } => types:: BasicObject ,
12011211 }
12021212 }
@@ -1756,7 +1766,8 @@ impl Function {
17561766 worklist. push_back ( state) ;
17571767 }
17581768 Insn :: ArrayMax { elements, state }
1759- | Insn :: NewArray { elements, state } => {
1769+ | Insn :: NewArray { elements, state }
1770+ | Insn :: ConcatStrings { strings : elements, state } => {
17601771 worklist. extend ( elements) ;
17611772 worklist. push_back ( state) ;
17621773 }
@@ -2917,6 +2928,16 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
29172928 let anytostring = fun. push_insn ( block, Insn :: AnyToString { val, str, state : exit_id } ) ;
29182929 state. stack_push ( anytostring) ;
29192930 }
2931+ YARVINSN_concatstrings => {
2932+ let num = get_arg ( pc, 0 ) . as_u32 ( ) ;
2933+ let mut strings = Vec :: with_capacity ( num. as_usize ( ) ) ;
2934+ for _ in 0 ..num {
2935+ strings. push ( state. stack_pop ( ) ?) ;
2936+ }
2937+ strings. reverse ( ) ;
2938+ let snapshot = fun. push_insn ( block, Insn :: Snapshot { state : exit_state } ) ;
2939+ state. stack_push ( fun. push_insn ( block, Insn :: ConcatStrings { state : snapshot, strings } ) ) ;
2940+ }
29202941 _ => {
29212942 // Unknown opcode; side-exit into the interpreter
29222943 let exit_id = fun. push_insn ( block, Insn :: Snapshot { state : exit_state } ) ;
@@ -4642,7 +4663,8 @@ mod tests {
46424663 v3:Fixnum[1] = Const Value(1)
46434664 v5:BasicObject = ObjToString v3
46444665 v7:String = AnyToString v3, str: v5
4645- SideExit
4666+ v9:StringExact = ConcatStrings v2, v7
4667+ Return v9
46464668 "# ] ] ) ;
46474669 }
46484670
@@ -6220,7 +6242,8 @@ mod opt_tests {
62206242 v2:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
62216243 v3:StringExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
62226244 v4:StringExact = StringCopy v3
6223- SideExit
6245+ v10:StringExact = ConcatStrings v2, v4
6246+ Return v10
62246247 "# ] ] ) ;
62256248 }
62266249
@@ -6234,9 +6257,10 @@ mod opt_tests {
62346257 bb0(v0:BasicObject):
62356258 v2:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
62366259 v3:Fixnum[1] = Const Value(1)
6237- v10:BasicObject = SendWithoutBlock v3, :to_s
6238- v7:String = AnyToString v3, str: v10
6239- SideExit
6260+ v11:BasicObject = SendWithoutBlock v3, :to_s
6261+ v7:String = AnyToString v3, str: v11
6262+ v9:StringExact = ConcatStrings v2, v7
6263+ Return v9
62406264 "# ] ] ) ;
62416265 }
62426266
0 commit comments