@@ -2486,6 +2486,16 @@ impl FrameState {
24862486 self . stack . pop ( ) . ok_or_else ( || ParseError :: StackUnderflow ( self . clone ( ) ) )
24872487 }
24882488
2489+ fn stack_pop_n ( & mut self , count : usize ) -> Result < Vec < InsnId > , ParseError > {
2490+ // Check if we have enough values on the stack
2491+ let stack_len = self . stack . len ( ) ;
2492+ if stack_len < count {
2493+ return Err ( ParseError :: StackUnderflow ( self . clone ( ) ) ) ;
2494+ }
2495+
2496+ Ok ( self . stack . split_off ( stack_len - count) )
2497+ }
2498+
24892499 /// Get a stack-top operand
24902500 fn stack_top ( & self ) -> Result < InsnId , ParseError > {
24912501 self . stack . last ( ) . ok_or_else ( || ParseError :: StackUnderflow ( self . clone ( ) ) ) . copied ( )
@@ -2809,35 +2819,20 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
28092819 YARVINSN_concatstrings => {
28102820 let count = get_arg ( pc, 0 ) . as_u32 ( ) ;
28112821 let exit_id = fun. push_insn ( block, Insn :: Snapshot { state : exit_state } ) ;
2812- // TODO: Pre-initialize the vector with the correct capacity
2813- // TODO: Fill the vector in the order without needing reversing
2814- // Create an issue for this
2815- let mut strings = vec ! [ ] ;
2816- for _ in 0 ..count {
2817- strings. push ( state. stack_pop ( ) ?) ;
2818- }
2819- strings. reverse ( ) ;
2822+ let strings = state. stack_pop_n ( count as usize ) ?;
28202823 let insn_id = fun. push_insn ( block, Insn :: StringConcat { strings, state : exit_id } ) ;
28212824 state. stack_push ( insn_id) ;
28222825 }
28232826 YARVINSN_newarray => {
28242827 let count = get_arg ( pc, 0 ) . as_usize ( ) ;
28252828 let exit_id = fun. push_insn ( block, Insn :: Snapshot { state : exit_state } ) ;
2826- let mut elements = vec ! [ ] ;
2827- for _ in 0 ..count {
2828- elements. push ( state. stack_pop ( ) ?) ;
2829- }
2830- elements. reverse ( ) ;
2829+ let elements = state. stack_pop_n ( count) ?;
28312830 state. stack_push ( fun. push_insn ( block, Insn :: NewArray { elements, state : exit_id } ) ) ;
28322831 }
28332832 YARVINSN_opt_newarray_send => {
28342833 let count = get_arg ( pc, 0 ) . as_usize ( ) ;
28352834 let method = get_arg ( pc, 1 ) . as_u32 ( ) ;
2836- let mut elements = vec ! [ ] ;
2837- for _ in 0 ..count {
2838- elements. push ( state. stack_pop ( ) ?) ;
2839- }
2840- elements. reverse ( ) ;
2835+ let elements = state. stack_pop_n ( count) ?;
28412836 let exit_id = fun. push_insn ( block, Insn :: Snapshot { state : exit_state } ) ;
28422837 let ( bop, insn) = match method {
28432838 VM_OPT_NEWARRAY_SEND_MAX => ( BOP_MAX , Insn :: ArrayMax { elements, state : exit_id } ) ,
@@ -2902,13 +2897,10 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
29022897 }
29032898 YARVINSN_pushtoarray => {
29042899 let count = get_arg ( pc, 0 ) . as_usize ( ) ;
2905- let mut vals = vec ! [ ] ;
2906- for _ in 0 ..count {
2907- vals. push ( state. stack_pop ( ) ?) ;
2908- }
2900+ let vals = state. stack_pop_n ( count) ?;
29092901 let array = state. stack_pop ( ) ?;
29102902 let exit_id = fun. push_insn ( block, Insn :: Snapshot { state : exit_state } ) ;
2911- for val in vals. into_iter ( ) . rev ( ) {
2903+ for val in vals. into_iter ( ) {
29122904 fun. push_insn ( block, Insn :: ArrayPush { array, val, state : exit_id } ) ;
29132905 }
29142906 state. stack_push ( array) ;
@@ -3110,12 +3102,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
31103102 }
31113103 let argc = unsafe { vm_ci_argc ( ( * cd) . ci ) } ;
31123104
3113- let mut args = vec ! [ ] ;
3114- for _ in 0 ..argc {
3115- args. push ( state. stack_pop ( ) ?) ;
3116- }
3117- args. reverse ( ) ;
3118-
3105+ let args = state. stack_pop_n ( argc as usize ) ?;
31193106 let recv = state. stack_pop ( ) ?;
31203107 let exit_id = fun. push_insn ( block, Insn :: Snapshot { state : exit_state } ) ;
31213108 let send = fun. push_insn ( block, Insn :: SendWithoutBlock { self_val : recv, cd, args, state : exit_id } ) ;
@@ -3191,12 +3178,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
31913178 }
31923179 let argc = unsafe { vm_ci_argc ( ( * cd) . ci ) } ;
31933180
3194- let mut args = vec ! [ ] ;
3195- for _ in 0 ..argc {
3196- args. push ( state. stack_pop ( ) ?) ;
3197- }
3198- args. reverse ( ) ;
3199-
3181+ let args = state. stack_pop_n ( argc as usize ) ?;
32003182 let recv = state. stack_pop ( ) ?;
32013183 let exit_id = fun. push_insn ( block, Insn :: Snapshot { state : exit_state } ) ;
32023184 let send = fun. push_insn ( block, Insn :: SendWithoutBlock { self_val : recv, cd, args, state : exit_id } ) ;
@@ -3214,12 +3196,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
32143196 }
32153197 let argc = unsafe { vm_ci_argc ( ( * cd) . ci ) } ;
32163198
3217- let mut args = vec ! [ ] ;
3218- for _ in 0 ..argc {
3219- args. push ( state. stack_pop ( ) ?) ;
3220- }
3221- args. reverse ( ) ;
3222-
3199+ let args = state. stack_pop_n ( argc as usize ) ?;
32233200 let recv = state. stack_pop ( ) ?;
32243201 let exit_id = fun. push_insn ( block, Insn :: Snapshot { state : exit_state } ) ;
32253202 let send = fun. push_insn ( block, Insn :: Send { self_val : recv, cd, blockiseq, args, state : exit_id } ) ;
0 commit comments