@@ -2041,6 +2041,12 @@ _PyCode_ReturnsOnlyNone(PyCodeObject *co)
2041
2041
if (!_PyCode_CheckPureFunction (co , NULL )) {
2042
2042
return 0 ;
2043
2043
}
2044
+ Py_ssize_t len = Py_SIZE (co );
2045
+ assert (len > 0 );
2046
+
2047
+ // The last instruction either returns or raises. We can take advantage
2048
+ // of that for a quick exit.
2049
+ _Py_CODEUNIT final = _Py_GetBaseCodeUnit (co , len - 1 );
2044
2050
2045
2051
// Look up None in co_consts.
2046
2052
Py_ssize_t nconsts = PyTuple_Size (co -> co_consts );
@@ -2052,26 +2058,42 @@ _PyCode_ReturnsOnlyNone(PyCodeObject *co)
2052
2058
}
2053
2059
if (none_index == nconsts ) {
2054
2060
// None wasn't there, which means there was no implicit return,
2055
- // "return", or "return None". That means there must be
2056
- // an explicit return (non-None).
2057
- return 0 ;
2058
- }
2061
+ // "return", or "return None".
2059
2062
2060
- // Walk the bytecode, looking for RETURN_VALUE.
2061
- Py_ssize_t len = Py_SIZE (co );
2062
- for (int i = 0 ; i < len ; i ++ ) {
2063
- _Py_CODEUNIT inst = _Py_GetBaseCodeUnit (co , i );
2064
- if (IS_RETURN_OPCODE (inst .op .code )) {
2065
- assert (i != 0 );
2066
- // Ignore it if it returns None.
2067
- _Py_CODEUNIT prev = _Py_GetBaseCodeUnit (co , i - 1 );
2068
- if (prev .op .code == LOAD_CONST ) {
2069
- // We don't worry about EXTENDED_ARG for now.
2070
- if (prev .op .arg == none_index ) {
2071
- continue ;
2063
+ // That means there must be
2064
+ // an explicit return (non-None), or it only raises.
2065
+ if (IS_RETURN_OPCODE (final .op .code )) {
2066
+ // It was an explicit return (non-None).
2067
+ return 0 ;
2068
+ }
2069
+ // It must end with a raise then. We still have to walk the
2070
+ // bytecode to see if there's any explicit return (non-None).
2071
+ assert (IS_RAISE_OPCODE (final .op .code ));
2072
+ for (int i = 0 ; i < len ; i ++ ) {
2073
+ _Py_CODEUNIT inst = _Py_GetBaseCodeUnit (co , i );
2074
+ if (IS_RETURN_OPCODE (inst .op .code )) {
2075
+ // We alraedy know it isn't returning None.
2076
+ return 0 ;
2077
+ }
2078
+ }
2079
+ // It must only raise.
2080
+ }
2081
+ else {
2082
+ // Walk the bytecode, looking for RETURN_VALUE.
2083
+ for (int i = 0 ; i < len ; i ++ ) {
2084
+ _Py_CODEUNIT inst = _Py_GetBaseCodeUnit (co , i );
2085
+ if (IS_RETURN_OPCODE (inst .op .code )) {
2086
+ assert (i != 0 );
2087
+ // Ignore it if it returns None.
2088
+ _Py_CODEUNIT prev = _Py_GetBaseCodeUnit (co , i - 1 );
2089
+ if (prev .op .code == LOAD_CONST ) {
2090
+ // We don't worry about EXTENDED_ARG for now.
2091
+ if (prev .op .arg == none_index ) {
2092
+ continue ;
2093
+ }
2072
2094
}
2095
+ return 0 ;
2073
2096
}
2074
- return 0 ;
2075
2097
}
2076
2098
}
2077
2099
return 1 ;
0 commit comments