bpo-45636: Merge all numeric operators (GH-29482)

This commit is contained in:
Brandt Bucher 2021-11-10 22:56:22 -08:00 committed by GitHub
parent 1cbaa505d0
commit 9178f533ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 613 additions and 1081 deletions

View file

@ -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 *