@@ -1573,6 +1573,12 @@ impl FrameState {
15731573 self . stack [ idx] = opnd;
15741574 }
15751575
1576+ /// Get a stack operand at idx
1577+ fn stack_topn ( & mut self , idx : usize ) -> Result < InsnId , ParseError > {
1578+ let idx = self . stack . len ( ) - idx - 1 ;
1579+ self . stack . get ( idx) . ok_or_else ( || ParseError :: StackUnderflow ( self . clone ( ) ) ) . copied ( )
1580+ }
1581+
15761582 fn setlocal ( & mut self , ep_offset : u32 , opnd : InsnId ) {
15771583 let idx = ep_offset_to_local_idx ( self . iseq , ep_offset) ;
15781584 self . locals [ idx] = opnd;
@@ -1896,6 +1902,11 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
18961902 let top = state. stack_top ( ) ?;
18971903 state. stack_setn ( n, top) ;
18981904 }
1905+ YARVINSN_topn => {
1906+ let n = get_arg ( pc, 0 ) . as_usize ( ) ;
1907+ let top = state. stack_topn ( n) ?;
1908+ state. stack_push ( top) ;
1909+ }
18991910 YARVINSN_adjuststack => {
19001911 let mut n = get_arg ( pc, 0 ) . as_usize ( ) ;
19011912 while n > 0 {
@@ -1946,6 +1957,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
19461957 YARVINSN_opt_ge |
19471958 YARVINSN_opt_ltlt |
19481959 YARVINSN_opt_aset |
1960+ YARVINSN_opt_length |
19491961 YARVINSN_opt_send_without_block => {
19501962 let cd: * const rb_call_data = get_arg ( pc, 0 ) . as_ptr ( ) ;
19511963 let call_info = unsafe { rb_get_call_data_ci ( cd) } ;
@@ -2907,6 +2919,20 @@ mod tests {
29072919 Return v5
29082920 "# ] ] ) ;
29092921 }
2922+
2923+ #[ test]
2924+ fn test_opt_length ( ) {
2925+ eval ( "
2926+ def test(a,b) = [a,b].length
2927+ " ) ;
2928+ assert_method_hir ( "test" , expect ! [ [ r#"
2929+ fn test:
2930+ bb0(v0:BasicObject, v1:BasicObject):
2931+ v4:ArrayExact = NewArray v0, v1
2932+ v6:BasicObject = SendWithoutBlock v4, :length
2933+ Return v6
2934+ "# ] ] ) ;
2935+ }
29102936}
29112937
29122938#[ cfg( test) ]
@@ -3850,4 +3876,18 @@ mod opt_tests {
38503876 Return v12
38513877 "# ] ] ) ;
38523878 }
3879+
3880+ #[ test]
3881+ fn test_opt_length ( ) {
3882+ eval ( "
3883+ def test(a,b) = [a,b].length
3884+ " ) ;
3885+ assert_optimized_method_hir ( "test" , expect ! [ [ r#"
3886+ fn test:
3887+ bb0(v0:BasicObject, v1:BasicObject):
3888+ v4:ArrayExact = NewArray v0, v1
3889+ v6:BasicObject = SendWithoutBlock v4, :length
3890+ Return v6
3891+ "# ] ] ) ;
3892+ }
38533893}
0 commit comments