|
|
|
@ -92,8 +92,6 @@ static PyObject * import_from(PyThreadState *, PyObject *, PyObject *); |
|
|
|
static int import_all_from(PyThreadState *, PyObject *, PyObject *); |
|
|
|
static void format_exc_check_arg(PyThreadState *, PyObject *, const char *, PyObject *); |
|
|
|
static void format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg); |
|
|
|
static PyObject * unicode_concatenate(PyThreadState *, PyObject *, PyObject *, |
|
|
|
InterpreterFrame *, const _Py_CODEUNIT *); |
|
|
|
static int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg); |
|
|
|
static void format_kwargs_error(PyThreadState *, PyObject *func, PyObject *kwargs); |
|
|
|
static void format_awaitable_error(PyThreadState *, PyTypeObject *, int, int); |
|
|
|
@ -1921,57 +1919,12 @@ check_eval_breaker: |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_POWER) { |
|
|
|
PyObject *exp = POP(); |
|
|
|
PyObject *base = TOP(); |
|
|
|
PyObject *res = PyNumber_Power(base, exp, Py_None); |
|
|
|
Py_DECREF(base); |
|
|
|
Py_DECREF(exp); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_MULTIPLY) { |
|
|
|
PREDICTED(BINARY_MULTIPLY); |
|
|
|
STAT_INC(BINARY_MULTIPLY, unquickened); |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *res = PyNumber_Multiply(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) { |
|
|
|
goto error; |
|
|
|
} |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_MULTIPLY_ADAPTIVE) { |
|
|
|
if (oparg == 0) { |
|
|
|
PyObject *left = SECOND(); |
|
|
|
PyObject *right = TOP(); |
|
|
|
next_instr--; |
|
|
|
if (_Py_Specialize_BinaryMultiply(left, right, next_instr) < 0) { |
|
|
|
goto error; |
|
|
|
} |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
else { |
|
|
|
STAT_INC(BINARY_MULTIPLY, deferred); |
|
|
|
UPDATE_PREV_INSTR_OPARG(next_instr, oparg - 1); |
|
|
|
STAT_DEC(BINARY_MULTIPLY, unquickened); |
|
|
|
JUMP_TO_INSTRUCTION(BINARY_MULTIPLY); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_MULTIPLY_INT) { |
|
|
|
TARGET(BINARY_OP_MULTIPLY_INT) { |
|
|
|
PyObject *left = SECOND(); |
|
|
|
PyObject *right = TOP(); |
|
|
|
DEOPT_IF(!PyLong_CheckExact(left), BINARY_MULTIPLY); |
|
|
|
DEOPT_IF(!PyLong_CheckExact(right), BINARY_MULTIPLY); |
|
|
|
STAT_INC(BINARY_MULTIPLY, hit); |
|
|
|
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); |
|
|
|
DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP); |
|
|
|
STAT_INC(BINARY_OP, hit); |
|
|
|
PyObject *prod = _PyLong_Multiply((PyLongObject *)left, (PyLongObject *)right); |
|
|
|
SET_SECOND(prod); |
|
|
|
Py_DECREF(right); |
|
|
|
@ -1983,12 +1936,12 @@ check_eval_breaker: |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_MULTIPLY_FLOAT) { |
|
|
|
TARGET(BINARY_OP_MULTIPLY_FLOAT) { |
|
|
|
PyObject *left = SECOND(); |
|
|
|
PyObject *right = TOP(); |
|
|
|
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_MULTIPLY); |
|
|
|
DEOPT_IF(!PyFloat_CheckExact(right), BINARY_MULTIPLY); |
|
|
|
STAT_INC(BINARY_MULTIPLY, hit); |
|
|
|
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); |
|
|
|
DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP); |
|
|
|
STAT_INC(BINARY_OP, hit); |
|
|
|
double dprod = ((PyFloatObject *)left)->ob_fval * |
|
|
|
((PyFloatObject *)right)->ob_fval; |
|
|
|
PyObject *prod = PyFloat_FromDouble(dprod); |
|
|
|
@ -2002,101 +1955,12 @@ check_eval_breaker: |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_MATRIX_MULTIPLY) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *res = PyNumber_MatrixMultiply(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_TRUE_DIVIDE) { |
|
|
|
PyObject *divisor = POP(); |
|
|
|
PyObject *dividend = TOP(); |
|
|
|
PyObject *quotient = PyNumber_TrueDivide(dividend, divisor); |
|
|
|
Py_DECREF(dividend); |
|
|
|
Py_DECREF(divisor); |
|
|
|
SET_TOP(quotient); |
|
|
|
if (quotient == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_FLOOR_DIVIDE) { |
|
|
|
PyObject *divisor = POP(); |
|
|
|
PyObject *dividend = TOP(); |
|
|
|
PyObject *quotient = PyNumber_FloorDivide(dividend, divisor); |
|
|
|
Py_DECREF(dividend); |
|
|
|
Py_DECREF(divisor); |
|
|
|
SET_TOP(quotient); |
|
|
|
if (quotient == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_MODULO) { |
|
|
|
PyObject *divisor = POP(); |
|
|
|
PyObject *dividend = TOP(); |
|
|
|
PyObject *res; |
|
|
|
if (PyUnicode_CheckExact(dividend) && ( |
|
|
|
!PyUnicode_Check(divisor) || PyUnicode_CheckExact(divisor))) { |
|
|
|
// fast path; string formatting, but not if the RHS is a str subclass |
|
|
|
// (see issue28598) |
|
|
|
res = PyUnicode_Format(dividend, divisor); |
|
|
|
} else { |
|
|
|
res = PyNumber_Remainder(dividend, divisor); |
|
|
|
} |
|
|
|
Py_DECREF(divisor); |
|
|
|
Py_DECREF(dividend); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_ADD) { |
|
|
|
PREDICTED(BINARY_ADD); |
|
|
|
STAT_INC(BINARY_ADD, unquickened); |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *sum = PyNumber_Add(left, right); |
|
|
|
SET_TOP(sum); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
if (sum == NULL) { |
|
|
|
goto error; |
|
|
|
} |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_ADD_ADAPTIVE) { |
|
|
|
if (oparg == 0) { |
|
|
|
PyObject *left = SECOND(); |
|
|
|
PyObject *right = TOP(); |
|
|
|
next_instr--; |
|
|
|
if (_Py_Specialize_BinaryAdd(left, right, next_instr) < 0) { |
|
|
|
goto error; |
|
|
|
} |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
else { |
|
|
|
STAT_INC(BINARY_ADD, deferred); |
|
|
|
UPDATE_PREV_INSTR_OPARG(next_instr, oparg - 1); |
|
|
|
STAT_DEC(BINARY_ADD, unquickened); |
|
|
|
JUMP_TO_INSTRUCTION(BINARY_ADD); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_ADD_UNICODE) { |
|
|
|
TARGET(BINARY_OP_ADD_UNICODE) { |
|
|
|
PyObject *left = SECOND(); |
|
|
|
PyObject *right = TOP(); |
|
|
|
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_ADD); |
|
|
|
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD); |
|
|
|
STAT_INC(BINARY_ADD, hit); |
|
|
|
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); |
|
|
|
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP); |
|
|
|
STAT_INC(BINARY_OP, hit); |
|
|
|
PyObject *res = PyUnicode_Concat(left, right); |
|
|
|
STACK_SHRINK(1); |
|
|
|
SET_TOP(res); |
|
|
|
@ -2108,12 +1972,12 @@ check_eval_breaker: |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_ADD_UNICODE_INPLACE_FAST) { |
|
|
|
TARGET(BINARY_OP_INPLACE_ADD_UNICODE) { |
|
|
|
PyObject *left = SECOND(); |
|
|
|
PyObject *right = TOP(); |
|
|
|
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_ADD); |
|
|
|
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD); |
|
|
|
DEOPT_IF(Py_REFCNT(left) != 2, BINARY_ADD); |
|
|
|
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP); |
|
|
|
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP); |
|
|
|
DEOPT_IF(Py_REFCNT(left) != 2, BINARY_OP); |
|
|
|
int next_oparg = _Py_OPARG(*next_instr); |
|
|
|
assert(_Py_OPCODE(*next_instr) == STORE_FAST); |
|
|
|
/* In the common case, there are 2 references to the value |
|
|
|
@ -2123,8 +1987,8 @@ check_eval_breaker: |
|
|
|
* the refcnt to 1. |
|
|
|
*/ |
|
|
|
PyObject *var = GETLOCAL(next_oparg); |
|
|
|
DEOPT_IF(var != left, BINARY_ADD); |
|
|
|
STAT_INC(BINARY_ADD, hit); |
|
|
|
DEOPT_IF(var != left, BINARY_OP); |
|
|
|
STAT_INC(BINARY_OP, hit); |
|
|
|
GETLOCAL(next_oparg) = NULL; |
|
|
|
Py_DECREF(left); |
|
|
|
STACK_SHRINK(1); |
|
|
|
@ -2136,12 +2000,12 @@ check_eval_breaker: |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_ADD_FLOAT) { |
|
|
|
TARGET(BINARY_OP_ADD_FLOAT) { |
|
|
|
PyObject *left = SECOND(); |
|
|
|
PyObject *right = TOP(); |
|
|
|
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_ADD); |
|
|
|
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD); |
|
|
|
STAT_INC(BINARY_ADD, hit); |
|
|
|
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP); |
|
|
|
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP); |
|
|
|
STAT_INC(BINARY_OP, hit); |
|
|
|
double dsum = ((PyFloatObject *)left)->ob_fval + |
|
|
|
((PyFloatObject *)right)->ob_fval; |
|
|
|
PyObject *sum = PyFloat_FromDouble(dsum); |
|
|
|
@ -2155,12 +2019,12 @@ check_eval_breaker: |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_ADD_INT) { |
|
|
|
TARGET(BINARY_OP_ADD_INT) { |
|
|
|
PyObject *left = SECOND(); |
|
|
|
PyObject *right = TOP(); |
|
|
|
DEOPT_IF(!PyLong_CheckExact(left), BINARY_ADD); |
|
|
|
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_ADD); |
|
|
|
STAT_INC(BINARY_ADD, hit); |
|
|
|
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP); |
|
|
|
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP); |
|
|
|
STAT_INC(BINARY_OP, hit); |
|
|
|
PyObject *sum = _PyLong_Add((PyLongObject *)left, (PyLongObject *)right); |
|
|
|
SET_SECOND(sum); |
|
|
|
Py_DECREF(right); |
|
|
|
@ -2172,18 +2036,6 @@ check_eval_breaker: |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_SUBTRACT) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *diff = PyNumber_Subtract(left, right); |
|
|
|
Py_DECREF(right); |
|
|
|
Py_DECREF(left); |
|
|
|
SET_TOP(diff); |
|
|
|
if (diff == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_SUBSCR) { |
|
|
|
PREDICTED(BINARY_SUBSCR); |
|
|
|
STAT_INC(BINARY_SUBSCR, unquickened); |
|
|
|
@ -2282,66 +2134,6 @@ check_eval_breaker: |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_LSHIFT) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *res = PyNumber_Lshift(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_RSHIFT) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *res = PyNumber_Rshift(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_AND) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *res = PyNumber_And(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_XOR) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *res = PyNumber_Xor(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_OR) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *res = PyNumber_Or(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(LIST_APPEND) { |
|
|
|
PyObject *v = POP(); |
|
|
|
PyObject *list = PEEK(oparg); |
|
|
|
@ -2366,169 +2158,6 @@ check_eval_breaker: |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(INPLACE_POWER) { |
|
|
|
PyObject *exp = POP(); |
|
|
|
PyObject *base = TOP(); |
|
|
|
PyObject *res = PyNumber_InPlacePower(base, exp, Py_None); |
|
|
|
Py_DECREF(base); |
|
|
|
Py_DECREF(exp); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(INPLACE_MULTIPLY) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *res = PyNumber_InPlaceMultiply(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(INPLACE_MATRIX_MULTIPLY) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *res = PyNumber_InPlaceMatrixMultiply(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(INPLACE_TRUE_DIVIDE) { |
|
|
|
PyObject *divisor = POP(); |
|
|
|
PyObject *dividend = TOP(); |
|
|
|
PyObject *quotient = PyNumber_InPlaceTrueDivide(dividend, divisor); |
|
|
|
Py_DECREF(dividend); |
|
|
|
Py_DECREF(divisor); |
|
|
|
SET_TOP(quotient); |
|
|
|
if (quotient == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(INPLACE_FLOOR_DIVIDE) { |
|
|
|
PyObject *divisor = POP(); |
|
|
|
PyObject *dividend = TOP(); |
|
|
|
PyObject *quotient = PyNumber_InPlaceFloorDivide(dividend, divisor); |
|
|
|
Py_DECREF(dividend); |
|
|
|
Py_DECREF(divisor); |
|
|
|
SET_TOP(quotient); |
|
|
|
if (quotient == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(INPLACE_MODULO) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *mod = PyNumber_InPlaceRemainder(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(mod); |
|
|
|
if (mod == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(INPLACE_ADD) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *sum; |
|
|
|
if (PyUnicode_CheckExact(left) && PyUnicode_CheckExact(right)) { |
|
|
|
sum = unicode_concatenate(tstate, left, right, frame, next_instr); |
|
|
|
/* unicode_concatenate consumed the ref to left */ |
|
|
|
} |
|
|
|
else { |
|
|
|
sum = PyNumber_InPlaceAdd(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
} |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(sum); |
|
|
|
if (sum == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(INPLACE_SUBTRACT) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *diff = PyNumber_InPlaceSubtract(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(diff); |
|
|
|
if (diff == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(INPLACE_LSHIFT) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *res = PyNumber_InPlaceLshift(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(INPLACE_RSHIFT) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *res = PyNumber_InPlaceRshift(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(INPLACE_AND) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *res = PyNumber_InPlaceAnd(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(INPLACE_XOR) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *res = PyNumber_InPlaceXor(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(INPLACE_OR) { |
|
|
|
PyObject *right = POP(); |
|
|
|
PyObject *left = TOP(); |
|
|
|
PyObject *res = PyNumber_InPlaceOr(left, right); |
|
|
|
Py_DECREF(left); |
|
|
|
Py_DECREF(right); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) |
|
|
|
goto error; |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(STORE_SUBSCR) { |
|
|
|
PyObject *sub = TOP(); |
|
|
|
PyObject *container = SECOND(); |
|
|
|
@ -5032,6 +4661,130 @@ check_eval_breaker: |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_OP) { |
|
|
|
PREDICTED(BINARY_OP); |
|
|
|
STAT_INC(BINARY_OP, unquickened); |
|
|
|
PyObject *rhs = POP(); |
|
|
|
PyObject *lhs = TOP(); |
|
|
|
PyObject *res; |
|
|
|
switch (oparg) { |
|
|
|
case NB_ADD: |
|
|
|
res = PyNumber_Add(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_AND: |
|
|
|
res = PyNumber_And(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_FLOOR_DIVIDE: |
|
|
|
res = PyNumber_FloorDivide(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_LSHIFT: |
|
|
|
res = PyNumber_Lshift(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_MATRIX_MULTIPLY: |
|
|
|
res = PyNumber_MatrixMultiply(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_MULTIPLY: |
|
|
|
res = PyNumber_Multiply(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_REMAINDER: |
|
|
|
if (PyUnicode_CheckExact(lhs) && |
|
|
|
(!PyUnicode_Check(rhs) || PyUnicode_CheckExact(rhs))) |
|
|
|
{ |
|
|
|
// bpo-28598: Fast path for string formatting (but not |
|
|
|
// if the RHS is a str subclass). |
|
|
|
res = PyUnicode_Format(lhs, rhs); |
|
|
|
break; |
|
|
|
} |
|
|
|
res = PyNumber_Remainder(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_OR: |
|
|
|
res = PyNumber_Or(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_POWER: |
|
|
|
res = PyNumber_Power(lhs, rhs, Py_None); |
|
|
|
break; |
|
|
|
case NB_RSHIFT: |
|
|
|
res = PyNumber_Rshift(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_SUBTRACT: |
|
|
|
res = PyNumber_Subtract(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_TRUE_DIVIDE: |
|
|
|
res = PyNumber_TrueDivide(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_XOR: |
|
|
|
res = PyNumber_Xor(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_INPLACE_ADD: |
|
|
|
res = PyNumber_InPlaceAdd(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_INPLACE_AND: |
|
|
|
res = PyNumber_InPlaceAnd(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_INPLACE_FLOOR_DIVIDE: |
|
|
|
res = PyNumber_InPlaceFloorDivide(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_INPLACE_LSHIFT: |
|
|
|
res = PyNumber_InPlaceLshift(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_INPLACE_MATRIX_MULTIPLY: |
|
|
|
res = PyNumber_InPlaceMatrixMultiply(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_INPLACE_MULTIPLY: |
|
|
|
res = PyNumber_InPlaceMultiply(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_INPLACE_REMAINDER: |
|
|
|
res = PyNumber_InPlaceRemainder(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_INPLACE_OR: |
|
|
|
res = PyNumber_InPlaceOr(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_INPLACE_POWER: |
|
|
|
res = PyNumber_InPlacePower(lhs, rhs, Py_None); |
|
|
|
break; |
|
|
|
case NB_INPLACE_RSHIFT: |
|
|
|
res = PyNumber_InPlaceRshift(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_INPLACE_SUBTRACT: |
|
|
|
res = PyNumber_InPlaceSubtract(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_INPLACE_TRUE_DIVIDE: |
|
|
|
res = PyNumber_InPlaceTrueDivide(lhs, rhs); |
|
|
|
break; |
|
|
|
case NB_INPLACE_XOR: |
|
|
|
res = PyNumber_InPlaceXor(lhs, rhs); |
|
|
|
break; |
|
|
|
default: |
|
|
|
Py_UNREACHABLE(); |
|
|
|
} |
|
|
|
Py_DECREF(lhs); |
|
|
|
Py_DECREF(rhs); |
|
|
|
SET_TOP(res); |
|
|
|
if (res == NULL) { |
|
|
|
goto error; |
|
|
|
} |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(BINARY_OP_ADAPTIVE) { |
|
|
|
assert(cframe.use_tracing == 0); |
|
|
|
SpecializedCacheEntry *cache = GET_CACHE(); |
|
|
|
if (cache->adaptive.counter == 0) { |
|
|
|
PyObject *lhs = SECOND(); |
|
|
|
PyObject *rhs = TOP(); |
|
|
|
next_instr--; |
|
|
|
_Py_Specialize_BinaryOp(lhs, rhs, next_instr, cache); |
|
|
|
DISPATCH(); |
|
|
|
} |
|
|
|
else { |
|
|
|
STAT_INC(BINARY_OP, deferred); |
|
|
|
cache->adaptive.counter--; |
|
|
|
oparg = cache->adaptive.original_oparg; |
|
|
|
STAT_DEC(BINARY_OP, unquickened); |
|
|
|
JUMP_TO_INSTRUCTION(BINARY_OP); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
TARGET(EXTENDED_ARG) { |
|
|
|
int oldoparg = oparg; |
|
|
|
NEXTOPARG(); |
|
|
|
@ -5137,9 +4890,8 @@ MISS_WITH_CACHE(STORE_ATTR) |
|
|
|
MISS_WITH_CACHE(LOAD_GLOBAL) |
|
|
|
MISS_WITH_CACHE(LOAD_METHOD) |
|
|
|
MISS_WITH_CACHE(CALL_FUNCTION) |
|
|
|
MISS_WITH_CACHE(BINARY_OP) |
|
|
|
MISS_WITH_OPARG_COUNTER(BINARY_SUBSCR) |
|
|
|
MISS_WITH_OPARG_COUNTER(BINARY_ADD) |
|
|
|
MISS_WITH_OPARG_COUNTER(BINARY_MULTIPLY) |
|
|
|
|
|
|
|
binary_subscr_dict_error: |
|
|
|
{ |
|
|
|
@ -7173,60 +6925,6 @@ format_awaitable_error(PyThreadState *tstate, PyTypeObject *type, int prevprevop |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static PyObject * |
|
|
|
unicode_concatenate(PyThreadState *tstate, PyObject *v, PyObject *w, |
|
|
|
InterpreterFrame *frame, const _Py_CODEUNIT *next_instr) |
|
|
|
{ |
|
|
|
PyObject *res; |
|
|
|
if (Py_REFCNT(v) == 2) { |
|
|
|
/* In the common case, there are 2 references to the value |
|
|
|
* stored in 'variable' when the += is performed: one on the |
|
|
|
* value stack (in 'v') and one still stored in the |
|
|
|
* 'variable'. We try to delete the variable now to reduce |
|
|
|
* the refcnt to 1. |
|
|
|
*/ |
|
|
|
int opcode, oparg; |
|
|
|
NEXTOPARG(); |
|
|
|
next_instr++; |
|
|
|
switch (opcode) { |
|
|
|
case STORE_FAST: |
|
|
|
{ |
|
|
|
if (GETLOCAL(oparg) == v) |
|
|
|
SETLOCAL(oparg, NULL); |
|
|
|
break; |
|
|
|
} |
|
|
|
case STORE_DEREF: |
|
|
|
{ |
|
|
|
PyObject *c = _PyFrame_GetLocalsArray(frame)[oparg]; |
|
|
|
if (PyCell_GET(c) == v) { |
|
|
|
PyCell_SET(c, NULL); |
|
|
|
Py_DECREF(v); |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
case STORE_NAME: |
|
|
|
{ |
|
|
|
PyObject *names = frame->f_code->co_names; |
|
|
|
PyObject *name = GETITEM(names, oparg); |
|
|
|
PyObject *locals = frame->f_locals; |
|
|
|
if (locals && PyDict_CheckExact(locals)) { |
|
|
|
PyObject *w = PyDict_GetItemWithError(locals, name); |
|
|
|
if ((w == v && PyDict_DelItem(locals, name) != 0) || |
|
|
|
(w == NULL && _PyErr_Occurred(tstate))) |
|
|
|
{ |
|
|
|
Py_DECREF(v); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
res = v; |
|
|
|
PyUnicode_Append(&res, w); |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef DYNAMIC_EXECUTION_PROFILE |
|
|
|
|
|
|
|
static PyObject * |
|
|
|
|