mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
bpo-45636: Merge all numeric operators (GH-29482)
This commit is contained in:
parent
1cbaa505d0
commit
9178f533ff
16 changed files with 613 additions and 1081 deletions
604
Python/ceval.c
604
Python/ceval.c
|
@ -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 *
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue