@@ -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,8 @@ 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 |
1961+ YARVINSN_opt_size |
19491962 YARVINSN_opt_send_without_block => {
19501963 let cd: * const rb_call_data = get_arg ( pc, 0 ) . as_ptr ( ) ;
19511964 let call_info = unsafe { rb_get_call_data_ci ( cd) } ;
@@ -2907,6 +2920,34 @@ mod tests {
29072920 Return v5
29082921 "# ] ] ) ;
29092922 }
2923+
2924+ #[ test]
2925+ fn test_opt_length ( ) {
2926+ eval ( "
2927+ def test(a,b) = [a,b].length
2928+ " ) ;
2929+ assert_method_hir ( "test" , expect ! [ [ r#"
2930+ fn test:
2931+ bb0(v0:BasicObject, v1:BasicObject):
2932+ v4:ArrayExact = NewArray v0, v1
2933+ v6:BasicObject = SendWithoutBlock v4, :length
2934+ Return v6
2935+ "# ] ] ) ;
2936+ }
2937+
2938+ #[ test]
2939+ fn test_opt_size ( ) {
2940+ eval ( "
2941+ def test(a,b) = [a,b].size
2942+ " ) ;
2943+ assert_method_hir ( "test" , expect ! [ [ r#"
2944+ fn test:
2945+ bb0(v0:BasicObject, v1:BasicObject):
2946+ v4:ArrayExact = NewArray v0, v1
2947+ v6:BasicObject = SendWithoutBlock v4, :size
2948+ Return v6
2949+ "# ] ] ) ;
2950+ }
29102951}
29112952
29122953#[ cfg( test) ]
@@ -3850,4 +3891,32 @@ mod opt_tests {
38503891 Return v12
38513892 "# ] ] ) ;
38523893 }
3894+
3895+ #[ test]
3896+ fn test_opt_length ( ) {
3897+ eval ( "
3898+ def test(a,b) = [a,b].length
3899+ " ) ;
3900+ assert_optimized_method_hir ( "test" , expect ! [ [ r#"
3901+ fn test:
3902+ bb0(v0:BasicObject, v1:BasicObject):
3903+ v4:ArrayExact = NewArray v0, v1
3904+ v6:BasicObject = SendWithoutBlock v4, :length
3905+ Return v6
3906+ "# ] ] ) ;
3907+ }
3908+
3909+ #[ test]
3910+ fn test_opt_size ( ) {
3911+ eval ( "
3912+ def test(a,b) = [a,b].size
3913+ " ) ;
3914+ assert_optimized_method_hir ( "test" , expect ! [ [ r#"
3915+ fn test:
3916+ bb0(v0:BasicObject, v1:BasicObject):
3917+ v4:ArrayExact = NewArray v0, v1
3918+ v6:BasicObject = SendWithoutBlock v4, :size
3919+ Return v6
3920+ "# ] ] ) ;
3921+ }
38533922}
0 commit comments