@@ -859,41 +859,31 @@ dummy_func(
859
859
}
860
860
}
861
861
862
- // stack effect: (__0 -- __array[oparg])
863
- inst (UNPACK_SEQUENCE ) {
862
+ inst (UNPACK_SEQUENCE , (unused /1 , seq -- unused [oparg ])) {
864
863
#if ENABLE_SPECIALIZATION
865
864
_PyUnpackSequenceCache * cache = (_PyUnpackSequenceCache * )next_instr ;
866
865
if (ADAPTIVE_COUNTER_IS_ZERO (cache -> counter )) {
867
866
assert (cframe .use_tracing == 0 );
868
- PyObject * seq = TOP ();
869
867
next_instr -- ;
870
868
_Py_Specialize_UnpackSequence (seq , next_instr , oparg );
871
869
DISPATCH_SAME_OPARG ();
872
870
}
873
871
STAT_INC (UNPACK_SEQUENCE , deferred );
874
872
DECREMENT_ADAPTIVE_COUNTER (cache -> counter );
875
873
#endif /* ENABLE_SPECIALIZATION */
876
- PyObject * seq = POP ();
877
- PyObject * * top = stack_pointer + oparg ;
878
- if (!unpack_iterable (tstate , seq , oparg , -1 , top )) {
879
- Py_DECREF (seq );
880
- goto error ;
881
- }
882
- STACK_GROW (oparg );
874
+ PyObject * * top = stack_pointer + oparg - 1 ;
875
+ int res = unpack_iterable (tstate , seq , oparg , -1 , top );
883
876
Py_DECREF (seq );
884
- JUMPBY ( INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE );
877
+ ERROR_IF ( res == 0 , error );
885
878
}
886
879
887
- // stack effect: (__0 -- __array[oparg])
888
- inst (UNPACK_SEQUENCE_TWO_TUPLE ) {
889
- PyObject * seq = TOP ();
880
+ inst (UNPACK_SEQUENCE_TWO_TUPLE , (unused /1 , seq -- v1 , v0 )) {
890
881
DEOPT_IF (!PyTuple_CheckExact (seq ), UNPACK_SEQUENCE );
891
882
DEOPT_IF (PyTuple_GET_SIZE (seq ) != 2 , UNPACK_SEQUENCE );
892
883
STAT_INC (UNPACK_SEQUENCE , hit );
893
- SET_TOP ( Py_NewRef (PyTuple_GET_ITEM (seq , 1 ) ));
894
- PUSH ( Py_NewRef (PyTuple_GET_ITEM (seq , 0 ) ));
884
+ v1 = Py_NewRef (PyTuple_GET_ITEM (seq , 1 ));
885
+ v0 = Py_NewRef (PyTuple_GET_ITEM (seq , 0 ));
895
886
Py_DECREF (seq );
896
- JUMPBY (INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE );
897
887
}
898
888
899
889
// stack effect: (__0 -- __array[oparg])
@@ -926,17 +916,12 @@ dummy_func(
926
916
JUMPBY (INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE );
927
917
}
928
918
929
- // error: UNPACK_EX has irregular stack effect
930
- inst (UNPACK_EX ) {
919
+ inst (UNPACK_EX , (seq -- unused [oparg & 0xFF ], unused , unused [oparg >> 8 ])) {
931
920
int totalargs = 1 + (oparg & 0xFF ) + (oparg >> 8 );
932
- PyObject * seq = POP ();
933
- PyObject * * top = stack_pointer + totalargs ;
934
- if (!unpack_iterable (tstate , seq , oparg & 0xFF , oparg >> 8 , top )) {
935
- Py_DECREF (seq );
936
- goto error ;
937
- }
938
- STACK_GROW (totalargs );
921
+ PyObject * * top = stack_pointer + totalargs - 1 ;
922
+ int res = unpack_iterable (tstate , seq , oparg & 0xFF , oparg >> 8 , top );
939
923
Py_DECREF (seq );
924
+ ERROR_IF (res == 0 , error );
940
925
}
941
926
942
927
family (store_attr , INLINE_CACHE_ENTRIES_STORE_ATTR ) = {
@@ -2066,27 +2051,35 @@ dummy_func(
2066
2051
PREDICT (LOAD_CONST );
2067
2052
}
2068
2053
2069
- // stack effect: ( -- __0)
2070
- inst (FOR_ITER ) {
2054
+ // Most members of this family are "secretly" super-instructions.
2055
+ // When the loop is exhausted, they jump, and the jump target is
2056
+ // always END_FOR, which pops two values off the stack.
2057
+ // This is optimized by skipping that instruction and combining
2058
+ // its effect (popping 'iter' instead of pushing 'next'.)
2059
+
2060
+ family (for_iter , INLINE_CACHE_ENTRIES_FOR_ITER ) = {
2061
+ FOR_ITER ,
2062
+ FOR_ITER_LIST ,
2063
+ FOR_ITER_TUPLE ,
2064
+ FOR_ITER_RANGE ,
2065
+ FOR_ITER_GEN ,
2066
+ };
2067
+
2068
+ inst (FOR_ITER , (unused /1 , iter -- iter , next )) {
2071
2069
#if ENABLE_SPECIALIZATION
2072
2070
_PyForIterCache * cache = (_PyForIterCache * )next_instr ;
2073
2071
if (ADAPTIVE_COUNTER_IS_ZERO (cache -> counter )) {
2074
2072
assert (cframe .use_tracing == 0 );
2075
2073
next_instr -- ;
2076
- _Py_Specialize_ForIter (TOP () , next_instr , oparg );
2074
+ _Py_Specialize_ForIter (iter , next_instr , oparg );
2077
2075
DISPATCH_SAME_OPARG ();
2078
2076
}
2079
2077
STAT_INC (FOR_ITER , deferred );
2080
2078
DECREMENT_ADAPTIVE_COUNTER (cache -> counter );
2081
2079
#endif /* ENABLE_SPECIALIZATION */
2082
- /* before: [iter]; after: [iter, iter()] *or* [] */
2083
- PyObject * iter = TOP ();
2084
- PyObject * next = (* Py_TYPE (iter )-> tp_iternext )(iter );
2085
- if (next != NULL ) {
2086
- PUSH (next );
2087
- JUMPBY (INLINE_CACHE_ENTRIES_FOR_ITER );
2088
- }
2089
- else {
2080
+ /* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */
2081
+ next = (* Py_TYPE (iter )-> tp_iternext )(iter );
2082
+ if (next == NULL ) {
2090
2083
if (_PyErr_Occurred (tstate )) {
2091
2084
if (!_PyErr_ExceptionMatches (tstate , PyExc_StopIteration )) {
2092
2085
goto error ;
@@ -2098,70 +2091,74 @@ dummy_func(
2098
2091
}
2099
2092
/* iterator ended normally */
2100
2093
assert (_Py_OPCODE (next_instr [INLINE_CACHE_ENTRIES_FOR_ITER + oparg ]) == END_FOR );
2101
- STACK_SHRINK (1 );
2102
2094
Py_DECREF (iter );
2103
- /* Skip END_FOR */
2095
+ STACK_SHRINK (1 );
2096
+ /* Jump forward oparg, then skip following END_FOR instruction */
2104
2097
JUMPBY (INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1 );
2098
+ DISPATCH ();
2105
2099
}
2100
+ // Common case: no jump, leave it to the code generator
2106
2101
}
2107
2102
2108
- // stack effect: ( -- __0)
2109
- inst (FOR_ITER_LIST ) {
2103
+ inst (FOR_ITER_LIST , (unused /1 , iter -- iter , next )) {
2110
2104
assert (cframe .use_tracing == 0 );
2111
- _PyListIterObject * it = ( _PyListIterObject * ) TOP ( );
2112
- DEOPT_IF ( Py_TYPE ( it ) != & PyListIter_Type , FOR_ITER ) ;
2105
+ DEOPT_IF ( Py_TYPE ( iter ) != & PyListIter_Type , FOR_ITER );
2106
+ _PyListIterObject * it = ( _PyListIterObject * ) iter ;
2113
2107
STAT_INC (FOR_ITER , hit );
2114
2108
PyListObject * seq = it -> it_seq ;
2115
2109
if (seq ) {
2116
2110
if (it -> it_index < PyList_GET_SIZE (seq )) {
2117
- PyObject * next = PyList_GET_ITEM (seq , it -> it_index ++ );
2118
- PUSH (Py_NewRef (next ));
2119
- JUMPBY (INLINE_CACHE_ENTRIES_FOR_ITER );
2111
+ next = Py_NewRef (PyList_GET_ITEM (seq , it -> it_index ++ ));
2120
2112
goto end_for_iter_list ; // End of this instruction
2121
2113
}
2122
2114
it -> it_seq = NULL ;
2123
2115
Py_DECREF (seq );
2124
2116
}
2117
+ Py_DECREF (iter );
2125
2118
STACK_SHRINK (1 );
2126
- Py_DECREF ( it );
2119
+ /* Jump forward oparg, then skip following END_FOR instruction */
2127
2120
JUMPBY (INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1 );
2121
+ DISPATCH ();
2128
2122
end_for_iter_list :
2123
+ // Common case: no jump, leave it to the code generator
2129
2124
}
2130
2125
2131
- // stack effect: ( -- __0)
2132
- inst (FOR_ITER_TUPLE ) {
2126
+ inst (FOR_ITER_TUPLE , (unused /1 , iter -- iter , next )) {
2133
2127
assert (cframe .use_tracing == 0 );
2134
- _PyTupleIterObject * it = (_PyTupleIterObject * )TOP () ;
2128
+ _PyTupleIterObject * it = (_PyTupleIterObject * )iter ;
2135
2129
DEOPT_IF (Py_TYPE (it ) != & PyTupleIter_Type , FOR_ITER );
2136
2130
STAT_INC (FOR_ITER , hit );
2137
2131
PyTupleObject * seq = it -> it_seq ;
2138
2132
if (seq ) {
2139
2133
if (it -> it_index < PyTuple_GET_SIZE (seq )) {
2140
- PyObject * next = PyTuple_GET_ITEM (seq , it -> it_index ++ );
2141
- PUSH (Py_NewRef (next ));
2142
- JUMPBY (INLINE_CACHE_ENTRIES_FOR_ITER );
2134
+ next = Py_NewRef (PyTuple_GET_ITEM (seq , it -> it_index ++ ));
2143
2135
goto end_for_iter_tuple ; // End of this instruction
2144
2136
}
2145
2137
it -> it_seq = NULL ;
2146
2138
Py_DECREF (seq );
2147
2139
}
2140
+ Py_DECREF (iter );
2148
2141
STACK_SHRINK (1 );
2149
- Py_DECREF ( it );
2142
+ /* Jump forward oparg, then skip following END_FOR instruction */
2150
2143
JUMPBY (INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1 );
2144
+ DISPATCH ();
2151
2145
end_for_iter_tuple :
2146
+ // Common case: no jump, leave it to the code generator
2152
2147
}
2153
2148
2154
- // stack effect: ( -- __0)
2155
- inst (FOR_ITER_RANGE ) {
2149
+ // This is slightly different, when the loop isn't terminated we
2150
+ // jump over the immediately following STORE_FAST instruction.
2151
+ inst (FOR_ITER_RANGE , (unused /1 , iter -- iter , unused )) {
2156
2152
assert (cframe .use_tracing == 0 );
2157
- _PyRangeIterObject * r = (_PyRangeIterObject * )TOP () ;
2153
+ _PyRangeIterObject * r = (_PyRangeIterObject * )iter ;
2158
2154
DEOPT_IF (Py_TYPE (r ) != & PyRangeIter_Type , FOR_ITER );
2159
2155
STAT_INC (FOR_ITER , hit );
2160
2156
_Py_CODEUNIT next = next_instr [INLINE_CACHE_ENTRIES_FOR_ITER ];
2161
2157
assert (_PyOpcode_Deopt [_Py_OPCODE (next )] == STORE_FAST );
2162
2158
if (r -> len <= 0 ) {
2163
2159
STACK_SHRINK (1 );
2164
2160
Py_DECREF (r );
2161
+ // Jump over END_FOR instruction.
2165
2162
JUMPBY (INLINE_CACHE_ENTRIES_FOR_ITER + oparg + 1 );
2166
2163
}
2167
2164
else {
@@ -2174,11 +2171,13 @@ dummy_func(
2174
2171
// The STORE_FAST is already done.
2175
2172
JUMPBY (INLINE_CACHE_ENTRIES_FOR_ITER + 1 );
2176
2173
}
2174
+ DISPATCH ();
2177
2175
}
2178
2176
2179
- inst (FOR_ITER_GEN ) {
2177
+ // This is *not* a super-instruction, unique in the family.
2178
+ inst (FOR_ITER_GEN , (unused /1 , iter -- iter , unused )) {
2180
2179
assert (cframe .use_tracing == 0 );
2181
- PyGenObject * gen = (PyGenObject * )TOP () ;
2180
+ PyGenObject * gen = (PyGenObject * )iter ;
2182
2181
DEOPT_IF (Py_TYPE (gen ) != & PyGen_Type , FOR_ITER );
2183
2182
DEOPT_IF (gen -> gi_frame_state >= FRAME_EXECUTING , FOR_ITER );
2184
2183
STAT_INC (FOR_ITER , hit );
@@ -3168,9 +3167,6 @@ family(call, INLINE_CACHE_ENTRIES_CALL) = {
3168
3167
CALL_NO_KW_LIST_APPEND , CALL_NO_KW_METHOD_DESCRIPTOR_FAST , CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS ,
3169
3168
CALL_NO_KW_METHOD_DESCRIPTOR_O , CALL_NO_KW_STR_1 , CALL_NO_KW_TUPLE_1 ,
3170
3169
CALL_NO_KW_TYPE_1 };
3171
- family (for_iter , INLINE_CACHE_ENTRIES_FOR_ITER ) = {
3172
- FOR_ITER , FOR_ITER_LIST ,
3173
- FOR_ITER_RANGE };
3174
3170
family (store_fast ) = { STORE_FAST , STORE_FAST__LOAD_FAST , STORE_FAST__STORE_FAST };
3175
3171
family (unpack_sequence , INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE ) = {
3176
3172
UNPACK_SEQUENCE , UNPACK_SEQUENCE_LIST ,
0 commit comments