mirror of
https://github.com/python/cpython.git
synced 2025-08-30 21:48:47 +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 *
|
||||
|
|
165
Python/compile.c
165
Python/compile.c
|
@ -309,7 +309,6 @@ static int compiler_annassign(struct compiler *, stmt_ty);
|
|||
static int compiler_subscript(struct compiler *, expr_ty);
|
||||
static int compiler_slice(struct compiler *, expr_ty);
|
||||
|
||||
static int inplace_binop(operator_ty);
|
||||
static int are_all_items_const(asdl_expr_seq *, Py_ssize_t, Py_ssize_t);
|
||||
|
||||
|
||||
|
@ -1022,40 +1021,13 @@ stack_effect(int opcode, int oparg, int jump)
|
|||
case MAP_ADD:
|
||||
return -2;
|
||||
|
||||
/* Binary operators */
|
||||
case BINARY_POWER:
|
||||
case BINARY_MULTIPLY:
|
||||
case BINARY_MATRIX_MULTIPLY:
|
||||
case BINARY_MODULO:
|
||||
case BINARY_ADD:
|
||||
case BINARY_SUBTRACT:
|
||||
case BINARY_SUBSCR:
|
||||
case BINARY_FLOOR_DIVIDE:
|
||||
case BINARY_TRUE_DIVIDE:
|
||||
return -1;
|
||||
case INPLACE_FLOOR_DIVIDE:
|
||||
case INPLACE_TRUE_DIVIDE:
|
||||
return -1;
|
||||
|
||||
case INPLACE_ADD:
|
||||
case INPLACE_SUBTRACT:
|
||||
case INPLACE_MULTIPLY:
|
||||
case INPLACE_MATRIX_MULTIPLY:
|
||||
case INPLACE_MODULO:
|
||||
return -1;
|
||||
case STORE_SUBSCR:
|
||||
return -3;
|
||||
case DELETE_SUBSCR:
|
||||
return -2;
|
||||
|
||||
case BINARY_LSHIFT:
|
||||
case BINARY_RSHIFT:
|
||||
case BINARY_AND:
|
||||
case BINARY_XOR:
|
||||
case BINARY_OR:
|
||||
return -1;
|
||||
case INPLACE_POWER:
|
||||
return -1;
|
||||
case GET_ITER:
|
||||
return 0;
|
||||
|
||||
|
@ -1063,12 +1035,6 @@ stack_effect(int opcode, int oparg, int jump)
|
|||
return -1;
|
||||
case LOAD_BUILD_CLASS:
|
||||
return 1;
|
||||
case INPLACE_LSHIFT:
|
||||
case INPLACE_RSHIFT:
|
||||
case INPLACE_AND:
|
||||
case INPLACE_XOR:
|
||||
case INPLACE_OR:
|
||||
return -1;
|
||||
|
||||
case RETURN_VALUE:
|
||||
return -1;
|
||||
|
@ -1259,6 +1225,8 @@ stack_effect(int opcode, int oparg, int jump)
|
|||
return 0;
|
||||
case COPY:
|
||||
return 1;
|
||||
case BINARY_OP:
|
||||
return -1;
|
||||
default:
|
||||
return PY_INVALID_STACK_EFFECT;
|
||||
}
|
||||
|
@ -1685,6 +1653,12 @@ compiler_addop_j_noline(struct compiler *c, int opcode, basicblock *b)
|
|||
return 0; \
|
||||
}
|
||||
|
||||
#define ADDOP_BINARY(C, BINOP) \
|
||||
RETURN_IF_FALSE(addop_binary((C), (BINOP), false))
|
||||
|
||||
#define ADDOP_INPLACE(C, BINOP) \
|
||||
RETURN_IF_FALSE(addop_binary((C), (BINOP), true))
|
||||
|
||||
/* VISIT and VISIT_SEQ takes an ASDL type as their second argument. They use
|
||||
the ASDL name to synthesize the name of the C type and the visit function.
|
||||
*/
|
||||
|
@ -3693,77 +3667,56 @@ unaryop(unaryop_ty op)
|
|||
}
|
||||
|
||||
static int
|
||||
binop(operator_ty op)
|
||||
addop_binary(struct compiler *c, operator_ty binop, bool inplace)
|
||||
{
|
||||
switch (op) {
|
||||
case Add:
|
||||
return BINARY_ADD;
|
||||
case Sub:
|
||||
return BINARY_SUBTRACT;
|
||||
case Mult:
|
||||
return BINARY_MULTIPLY;
|
||||
case MatMult:
|
||||
return BINARY_MATRIX_MULTIPLY;
|
||||
case Div:
|
||||
return BINARY_TRUE_DIVIDE;
|
||||
case Mod:
|
||||
return BINARY_MODULO;
|
||||
case Pow:
|
||||
return BINARY_POWER;
|
||||
case LShift:
|
||||
return BINARY_LSHIFT;
|
||||
case RShift:
|
||||
return BINARY_RSHIFT;
|
||||
case BitOr:
|
||||
return BINARY_OR;
|
||||
case BitXor:
|
||||
return BINARY_XOR;
|
||||
case BitAnd:
|
||||
return BINARY_AND;
|
||||
case FloorDiv:
|
||||
return BINARY_FLOOR_DIVIDE;
|
||||
default:
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"binary op %d should not be possible", op);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
inplace_binop(operator_ty op)
|
||||
{
|
||||
switch (op) {
|
||||
case Add:
|
||||
return INPLACE_ADD;
|
||||
case Sub:
|
||||
return INPLACE_SUBTRACT;
|
||||
case Mult:
|
||||
return INPLACE_MULTIPLY;
|
||||
case MatMult:
|
||||
return INPLACE_MATRIX_MULTIPLY;
|
||||
case Div:
|
||||
return INPLACE_TRUE_DIVIDE;
|
||||
case Mod:
|
||||
return INPLACE_MODULO;
|
||||
case Pow:
|
||||
return INPLACE_POWER;
|
||||
case LShift:
|
||||
return INPLACE_LSHIFT;
|
||||
case RShift:
|
||||
return INPLACE_RSHIFT;
|
||||
case BitOr:
|
||||
return INPLACE_OR;
|
||||
case BitXor:
|
||||
return INPLACE_XOR;
|
||||
case BitAnd:
|
||||
return INPLACE_AND;
|
||||
case FloorDiv:
|
||||
return INPLACE_FLOOR_DIVIDE;
|
||||
default:
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"inplace binary op %d should not be possible", op);
|
||||
return 0;
|
||||
int oparg;
|
||||
switch (binop) {
|
||||
case Add:
|
||||
oparg = inplace ? NB_INPLACE_ADD : NB_ADD;
|
||||
break;
|
||||
case Sub:
|
||||
oparg = inplace ? NB_INPLACE_SUBTRACT : NB_SUBTRACT;
|
||||
break;
|
||||
case Mult:
|
||||
oparg = inplace ? NB_INPLACE_MULTIPLY : NB_MULTIPLY;
|
||||
break;
|
||||
case MatMult:
|
||||
oparg = inplace ? NB_INPLACE_MATRIX_MULTIPLY : NB_MATRIX_MULTIPLY;
|
||||
break;
|
||||
case Div:
|
||||
oparg = inplace ? NB_INPLACE_TRUE_DIVIDE : NB_TRUE_DIVIDE;
|
||||
break;
|
||||
case Mod:
|
||||
oparg = inplace ? NB_INPLACE_REMAINDER : NB_REMAINDER;
|
||||
break;
|
||||
case Pow:
|
||||
oparg = inplace ? NB_INPLACE_POWER : NB_POWER;
|
||||
break;
|
||||
case LShift:
|
||||
oparg = inplace ? NB_INPLACE_LSHIFT : NB_LSHIFT;
|
||||
break;
|
||||
case RShift:
|
||||
oparg = inplace ? NB_INPLACE_RSHIFT : NB_RSHIFT;
|
||||
break;
|
||||
case BitOr:
|
||||
oparg = inplace ? NB_INPLACE_OR : NB_OR;
|
||||
break;
|
||||
case BitXor:
|
||||
oparg = inplace ? NB_INPLACE_XOR : NB_XOR;
|
||||
break;
|
||||
case BitAnd:
|
||||
oparg = inplace ? NB_INPLACE_AND : NB_AND;
|
||||
break;
|
||||
case FloorDiv:
|
||||
oparg = inplace ? NB_INPLACE_FLOOR_DIVIDE : NB_FLOOR_DIVIDE;
|
||||
break;
|
||||
default:
|
||||
PyErr_Format(PyExc_SystemError, "%s op %d should not be possible",
|
||||
inplace ? "inplace" : "binary", binop);
|
||||
return 0;
|
||||
}
|
||||
ADDOP_I(c, BINARY_OP, oparg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -5354,7 +5307,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
|
|||
case BinOp_kind:
|
||||
VISIT(c, expr, e->v.BinOp.left);
|
||||
VISIT(c, expr, e->v.BinOp.right);
|
||||
ADDOP(c, binop(e->v.BinOp.op));
|
||||
ADDOP_BINARY(c, e->v.BinOp.op);
|
||||
break;
|
||||
case UnaryOp_kind:
|
||||
VISIT(c, expr, e->v.UnaryOp.operand);
|
||||
|
@ -5540,7 +5493,7 @@ compiler_augassign(struct compiler *c, stmt_ty s)
|
|||
c->u->u_end_col_offset = old_end_col_offset;
|
||||
|
||||
VISIT(c, expr, s->v.AugAssign.value);
|
||||
ADDOP(c, inplace_binop(s->v.AugAssign.op));
|
||||
ADDOP_INPLACE(c, s->v.AugAssign.op);
|
||||
|
||||
SET_LOC(c, e);
|
||||
|
||||
|
@ -6000,7 +5953,7 @@ pattern_helper_sequence_subscr(struct compiler *c, asdl_pattern_seq *patterns,
|
|||
// nonnegative index:
|
||||
ADDOP(c, GET_LEN);
|
||||
ADDOP_LOAD_CONST_NEW(c, PyLong_FromSsize_t(size - i));
|
||||
ADDOP(c, BINARY_SUBTRACT);
|
||||
ADDOP_BINARY(c, Sub);
|
||||
}
|
||||
ADDOP(c, BINARY_SUBSCR);
|
||||
RETURN_IF_FALSE(compiler_pattern_subpattern(c, pattern, pc));
|
||||
|
|
126
Python/opcode_targets.h
generated
126
Python/opcode_targets.h
generated
|
@ -6,67 +6,67 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_DUP_TOP,
|
||||
&&TARGET_DUP_TOP_TWO,
|
||||
&&TARGET_ROT_FOUR,
|
||||
&&TARGET_BINARY_ADD_ADAPTIVE,
|
||||
&&TARGET_BINARY_ADD_INT,
|
||||
&&TARGET_BINARY_OP_ADAPTIVE,
|
||||
&&TARGET_BINARY_OP_ADD_INT,
|
||||
&&TARGET_NOP,
|
||||
&&TARGET_UNARY_POSITIVE,
|
||||
&&TARGET_UNARY_NEGATIVE,
|
||||
&&TARGET_UNARY_NOT,
|
||||
&&TARGET_BINARY_ADD_FLOAT,
|
||||
&&TARGET_BINARY_ADD_UNICODE,
|
||||
&&TARGET_BINARY_OP_ADD_FLOAT,
|
||||
&&TARGET_BINARY_OP_ADD_UNICODE,
|
||||
&&TARGET_UNARY_INVERT,
|
||||
&&TARGET_BINARY_MATRIX_MULTIPLY,
|
||||
&&TARGET_INPLACE_MATRIX_MULTIPLY,
|
||||
&&TARGET_BINARY_ADD_UNICODE_INPLACE_FAST,
|
||||
&&TARGET_BINARY_POWER,
|
||||
&&TARGET_BINARY_MULTIPLY,
|
||||
&&TARGET_BINARY_MULTIPLY_ADAPTIVE,
|
||||
&&TARGET_BINARY_MODULO,
|
||||
&&TARGET_BINARY_ADD,
|
||||
&&TARGET_BINARY_SUBTRACT,
|
||||
&&TARGET_BINARY_SUBSCR,
|
||||
&&TARGET_BINARY_FLOOR_DIVIDE,
|
||||
&&TARGET_BINARY_TRUE_DIVIDE,
|
||||
&&TARGET_INPLACE_FLOOR_DIVIDE,
|
||||
&&TARGET_INPLACE_TRUE_DIVIDE,
|
||||
&&TARGET_GET_LEN,
|
||||
&&TARGET_MATCH_MAPPING,
|
||||
&&TARGET_MATCH_SEQUENCE,
|
||||
&&TARGET_MATCH_KEYS,
|
||||
&&TARGET_BINARY_MULTIPLY_INT,
|
||||
&&TARGET_PUSH_EXC_INFO,
|
||||
&&TARGET_BINARY_MULTIPLY_FLOAT,
|
||||
&&TARGET_POP_EXCEPT_AND_RERAISE,
|
||||
&&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
|
||||
&&TARGET_BINARY_OP_MULTIPLY_INT,
|
||||
&&TARGET_BINARY_OP_MULTIPLY_FLOAT,
|
||||
&&TARGET_BINARY_SUBSCR_ADAPTIVE,
|
||||
&&TARGET_BINARY_SUBSCR_LIST_INT,
|
||||
&&TARGET_BINARY_SUBSCR_TUPLE_INT,
|
||||
&&TARGET_BINARY_SUBSCR_DICT,
|
||||
&&TARGET_CALL_FUNCTION_ADAPTIVE,
|
||||
&&TARGET_CALL_FUNCTION_BUILTIN_O,
|
||||
&&TARGET_BINARY_SUBSCR,
|
||||
&&TARGET_CALL_FUNCTION_BUILTIN_FAST,
|
||||
&&TARGET_CALL_FUNCTION_LEN,
|
||||
&&TARGET_CALL_FUNCTION_ISINSTANCE,
|
||||
&&TARGET_CALL_FUNCTION_PY_SIMPLE,
|
||||
&&TARGET_GET_LEN,
|
||||
&&TARGET_MATCH_MAPPING,
|
||||
&&TARGET_MATCH_SEQUENCE,
|
||||
&&TARGET_MATCH_KEYS,
|
||||
&&TARGET_JUMP_ABSOLUTE_QUICK,
|
||||
&&TARGET_PUSH_EXC_INFO,
|
||||
&&TARGET_LOAD_ATTR_ADAPTIVE,
|
||||
&&TARGET_POP_EXCEPT_AND_RERAISE,
|
||||
&&TARGET_LOAD_ATTR_INSTANCE_VALUE,
|
||||
&&TARGET_LOAD_ATTR_WITH_HINT,
|
||||
&&TARGET_LOAD_ATTR_SLOT,
|
||||
&&TARGET_LOAD_ATTR_MODULE,
|
||||
&&TARGET_LOAD_GLOBAL_ADAPTIVE,
|
||||
&&TARGET_LOAD_GLOBAL_MODULE,
|
||||
&&TARGET_LOAD_GLOBAL_BUILTIN,
|
||||
&&TARGET_LOAD_METHOD_ADAPTIVE,
|
||||
&&TARGET_LOAD_METHOD_CACHED,
|
||||
&&TARGET_LOAD_METHOD_CLASS,
|
||||
&&TARGET_LOAD_METHOD_MODULE,
|
||||
&&TARGET_WITH_EXCEPT_START,
|
||||
&&TARGET_GET_AITER,
|
||||
&&TARGET_GET_ANEXT,
|
||||
&&TARGET_BEFORE_ASYNC_WITH,
|
||||
&&TARGET_BEFORE_WITH,
|
||||
&&TARGET_END_ASYNC_FOR,
|
||||
&&TARGET_INPLACE_ADD,
|
||||
&&TARGET_INPLACE_SUBTRACT,
|
||||
&&TARGET_INPLACE_MULTIPLY,
|
||||
&&TARGET_LOAD_ATTR_ADAPTIVE,
|
||||
&&TARGET_INPLACE_MODULO,
|
||||
&&TARGET_LOAD_METHOD_NO_DICT,
|
||||
&&TARGET_STORE_ATTR_ADAPTIVE,
|
||||
&&TARGET_STORE_ATTR_INSTANCE_VALUE,
|
||||
&&TARGET_STORE_ATTR_SLOT,
|
||||
&&TARGET_STORE_ATTR_WITH_HINT,
|
||||
&&TARGET_STORE_SUBSCR,
|
||||
&&TARGET_DELETE_SUBSCR,
|
||||
&&TARGET_BINARY_LSHIFT,
|
||||
&&TARGET_BINARY_RSHIFT,
|
||||
&&TARGET_BINARY_AND,
|
||||
&&TARGET_BINARY_XOR,
|
||||
&&TARGET_BINARY_OR,
|
||||
&&TARGET_INPLACE_POWER,
|
||||
&&TARGET_LOAD_FAST__LOAD_FAST,
|
||||
&&TARGET_STORE_FAST__LOAD_FAST,
|
||||
&&TARGET_LOAD_FAST__LOAD_CONST,
|
||||
&&TARGET_LOAD_CONST__LOAD_FAST,
|
||||
&&TARGET_STORE_FAST__STORE_FAST,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_GET_ITER,
|
||||
&&TARGET_GET_YIELD_FROM_ITER,
|
||||
&&TARGET_PRINT_EXPR,
|
||||
|
@ -74,20 +74,20 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_YIELD_FROM,
|
||||
&&TARGET_GET_AWAITABLE,
|
||||
&&TARGET_LOAD_ASSERTION_ERROR,
|
||||
&&TARGET_INPLACE_LSHIFT,
|
||||
&&TARGET_INPLACE_RSHIFT,
|
||||
&&TARGET_INPLACE_AND,
|
||||
&&TARGET_INPLACE_XOR,
|
||||
&&TARGET_INPLACE_OR,
|
||||
&&TARGET_LOAD_ATTR_INSTANCE_VALUE,
|
||||
&&TARGET_LOAD_ATTR_WITH_HINT,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_LIST_TO_TUPLE,
|
||||
&&TARGET_RETURN_VALUE,
|
||||
&&TARGET_IMPORT_STAR,
|
||||
&&TARGET_SETUP_ANNOTATIONS,
|
||||
&&TARGET_YIELD_VALUE,
|
||||
&&TARGET_LOAD_ATTR_SLOT,
|
||||
&&TARGET_LOAD_ATTR_MODULE,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_POP_EXCEPT,
|
||||
&&TARGET_STORE_NAME,
|
||||
&&TARGET_DELETE_NAME,
|
||||
|
@ -121,44 +121,44 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_RERAISE,
|
||||
&&TARGET_COPY,
|
||||
&&TARGET_JUMP_IF_NOT_EXC_MATCH,
|
||||
&&TARGET_LOAD_GLOBAL_ADAPTIVE,
|
||||
&&TARGET_LOAD_GLOBAL_MODULE,
|
||||
&&TARGET_BINARY_OP,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_LOAD_FAST,
|
||||
&&TARGET_STORE_FAST,
|
||||
&&TARGET_DELETE_FAST,
|
||||
&&TARGET_LOAD_GLOBAL_BUILTIN,
|
||||
&&TARGET_LOAD_METHOD_ADAPTIVE,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_GEN_START,
|
||||
&&TARGET_RAISE_VARARGS,
|
||||
&&TARGET_CALL_FUNCTION,
|
||||
&&TARGET_MAKE_FUNCTION,
|
||||
&&TARGET_BUILD_SLICE,
|
||||
&&TARGET_LOAD_METHOD_CACHED,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_MAKE_CELL,
|
||||
&&TARGET_LOAD_CLOSURE,
|
||||
&&TARGET_LOAD_DEREF,
|
||||
&&TARGET_STORE_DEREF,
|
||||
&&TARGET_DELETE_DEREF,
|
||||
&&TARGET_LOAD_METHOD_CLASS,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_CALL_FUNCTION_KW,
|
||||
&&TARGET_CALL_FUNCTION_EX,
|
||||
&&TARGET_LOAD_METHOD_MODULE,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_EXTENDED_ARG,
|
||||
&&TARGET_LIST_APPEND,
|
||||
&&TARGET_SET_ADD,
|
||||
&&TARGET_MAP_ADD,
|
||||
&&TARGET_LOAD_CLASSDEREF,
|
||||
&&TARGET_LOAD_METHOD_NO_DICT,
|
||||
&&TARGET_STORE_ATTR_ADAPTIVE,
|
||||
&&TARGET_STORE_ATTR_INSTANCE_VALUE,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_MATCH_CLASS,
|
||||
&&TARGET_STORE_ATTR_SLOT,
|
||||
&&TARGET_STORE_ATTR_WITH_HINT,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_FORMAT_VALUE,
|
||||
&&TARGET_BUILD_CONST_KEY_MAP,
|
||||
&&TARGET_BUILD_STRING,
|
||||
&&TARGET_LOAD_FAST__LOAD_FAST,
|
||||
&&TARGET_STORE_FAST__LOAD_FAST,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_LOAD_METHOD,
|
||||
&&TARGET_CALL_METHOD,
|
||||
&&TARGET_LIST_EXTEND,
|
||||
|
@ -166,9 +166,9 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_DICT_MERGE,
|
||||
&&TARGET_DICT_UPDATE,
|
||||
&&TARGET_CALL_METHOD_KW,
|
||||
&&TARGET_LOAD_FAST__LOAD_CONST,
|
||||
&&TARGET_LOAD_CONST__LOAD_FAST,
|
||||
&&TARGET_STORE_FAST__STORE_FAST,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
|
|
|
@ -124,11 +124,10 @@ _Py_GetSpecializationStats(void) {
|
|||
err += add_stat_dict(stats, LOAD_ATTR, "load_attr");
|
||||
err += add_stat_dict(stats, LOAD_GLOBAL, "load_global");
|
||||
err += add_stat_dict(stats, LOAD_METHOD, "load_method");
|
||||
err += add_stat_dict(stats, BINARY_ADD, "binary_add");
|
||||
err += add_stat_dict(stats, BINARY_MULTIPLY, "binary_multiply");
|
||||
err += add_stat_dict(stats, BINARY_SUBSCR, "binary_subscr");
|
||||
err += add_stat_dict(stats, STORE_ATTR, "store_attr");
|
||||
err += add_stat_dict(stats, CALL_FUNCTION, "call_function");
|
||||
err += add_stat_dict(stats, BINARY_OP, "binary_op");
|
||||
if (err < 0) {
|
||||
Py_DECREF(stats);
|
||||
return NULL;
|
||||
|
@ -182,11 +181,10 @@ _Py_PrintSpecializationStats(void)
|
|||
print_stats(out, &_specialization_stats[LOAD_ATTR], "load_attr");
|
||||
print_stats(out, &_specialization_stats[LOAD_GLOBAL], "load_global");
|
||||
print_stats(out, &_specialization_stats[LOAD_METHOD], "load_method");
|
||||
print_stats(out, &_specialization_stats[BINARY_ADD], "binary_add");
|
||||
print_stats(out, &_specialization_stats[BINARY_MULTIPLY], "binary_multiply");
|
||||
print_stats(out, &_specialization_stats[BINARY_SUBSCR], "binary_subscr");
|
||||
print_stats(out, &_specialization_stats[STORE_ATTR], "store_attr");
|
||||
print_stats(out, &_specialization_stats[CALL_FUNCTION], "call_function");
|
||||
print_stats(out, &_specialization_stats[BINARY_OP], "binary_op");
|
||||
if (out != stderr) {
|
||||
fclose(out);
|
||||
}
|
||||
|
@ -234,11 +232,10 @@ static uint8_t adaptive_opcodes[256] = {
|
|||
[LOAD_ATTR] = LOAD_ATTR_ADAPTIVE,
|
||||
[LOAD_GLOBAL] = LOAD_GLOBAL_ADAPTIVE,
|
||||
[LOAD_METHOD] = LOAD_METHOD_ADAPTIVE,
|
||||
[BINARY_ADD] = BINARY_ADD_ADAPTIVE,
|
||||
[BINARY_MULTIPLY] = BINARY_MULTIPLY_ADAPTIVE,
|
||||
[BINARY_SUBSCR] = BINARY_SUBSCR_ADAPTIVE,
|
||||
[CALL_FUNCTION] = CALL_FUNCTION_ADAPTIVE,
|
||||
[STORE_ATTR] = STORE_ATTR_ADAPTIVE,
|
||||
[BINARY_OP] = BINARY_OP_ADAPTIVE,
|
||||
};
|
||||
|
||||
/* The number of cache entries required for a "family" of instructions. */
|
||||
|
@ -246,11 +243,10 @@ static uint8_t cache_requirements[256] = {
|
|||
[LOAD_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */
|
||||
[LOAD_GLOBAL] = 2, /* _PyAdaptiveEntry and _PyLoadGlobalCache */
|
||||
[LOAD_METHOD] = 3, /* _PyAdaptiveEntry, _PyAttrCache and _PyObjectCache */
|
||||
[BINARY_ADD] = 0,
|
||||
[BINARY_MULTIPLY] = 0,
|
||||
[BINARY_SUBSCR] = 0,
|
||||
[CALL_FUNCTION] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */
|
||||
[STORE_ATTR] = 2, /* _PyAdaptiveEntry and _PyAttrCache */
|
||||
[BINARY_OP] = 1, // _PyAdaptiveEntry
|
||||
};
|
||||
|
||||
/* Return the oparg for the cache_offset and instruction index.
|
||||
|
@ -1183,76 +1179,6 @@ success:
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_Py_Specialize_BinaryAdd(PyObject *left, PyObject *right, _Py_CODEUNIT *instr)
|
||||
{
|
||||
PyTypeObject *left_type = Py_TYPE(left);
|
||||
if (left_type != Py_TYPE(right)) {
|
||||
SPECIALIZATION_FAIL(BINARY_ADD, SPEC_FAIL_DIFFERENT_TYPES);
|
||||
goto fail;
|
||||
}
|
||||
if (left_type == &PyUnicode_Type) {
|
||||
int next_opcode = _Py_OPCODE(instr[1]);
|
||||
if (next_opcode == STORE_FAST) {
|
||||
*instr = _Py_MAKECODEUNIT(BINARY_ADD_UNICODE_INPLACE_FAST, initial_counter_value());
|
||||
}
|
||||
else {
|
||||
*instr = _Py_MAKECODEUNIT(BINARY_ADD_UNICODE, initial_counter_value());
|
||||
}
|
||||
goto success;
|
||||
}
|
||||
else if (left_type == &PyLong_Type) {
|
||||
*instr = _Py_MAKECODEUNIT(BINARY_ADD_INT, initial_counter_value());
|
||||
goto success;
|
||||
}
|
||||
else if (left_type == &PyFloat_Type) {
|
||||
*instr = _Py_MAKECODEUNIT(BINARY_ADD_FLOAT, initial_counter_value());
|
||||
goto success;
|
||||
|
||||
}
|
||||
else {
|
||||
SPECIALIZATION_FAIL(BINARY_ADD, SPEC_FAIL_OTHER);
|
||||
}
|
||||
fail:
|
||||
STAT_INC(BINARY_ADD, specialization_failure);
|
||||
assert(!PyErr_Occurred());
|
||||
*instr = _Py_MAKECODEUNIT(_Py_OPCODE(*instr), ADAPTIVE_CACHE_BACKOFF);
|
||||
return 0;
|
||||
success:
|
||||
STAT_INC(BINARY_ADD, specialization_success);
|
||||
assert(!PyErr_Occurred());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_Py_Specialize_BinaryMultiply(PyObject *left, PyObject *right, _Py_CODEUNIT *instr)
|
||||
{
|
||||
if (!Py_IS_TYPE(left, Py_TYPE(right))) {
|
||||
SPECIALIZATION_FAIL(BINARY_MULTIPLY, SPEC_FAIL_DIFFERENT_TYPES);
|
||||
goto fail;
|
||||
}
|
||||
if (PyLong_CheckExact(left)) {
|
||||
*instr = _Py_MAKECODEUNIT(BINARY_MULTIPLY_INT, initial_counter_value());
|
||||
goto success;
|
||||
}
|
||||
else if (PyFloat_CheckExact(left)) {
|
||||
*instr = _Py_MAKECODEUNIT(BINARY_MULTIPLY_FLOAT, initial_counter_value());
|
||||
goto success;
|
||||
}
|
||||
else {
|
||||
SPECIALIZATION_FAIL(BINARY_MULTIPLY, SPEC_FAIL_OTHER);
|
||||
}
|
||||
fail:
|
||||
STAT_INC(BINARY_MULTIPLY, specialization_failure);
|
||||
assert(!PyErr_Occurred());
|
||||
*instr = _Py_MAKECODEUNIT(_Py_OPCODE(*instr), ADAPTIVE_CACHE_BACKOFF);
|
||||
return 0;
|
||||
success:
|
||||
STAT_INC(BINARY_MULTIPLY, specialization_success);
|
||||
assert(!PyErr_Occurred());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
specialize_class_call(
|
||||
PyObject *callable, _Py_CODEUNIT *instr,
|
||||
|
@ -1448,3 +1374,64 @@ _Py_Specialize_CallFunction(
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
_Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
|
||||
SpecializedCacheEntry *cache)
|
||||
{
|
||||
_PyAdaptiveEntry *adaptive = &cache->adaptive;
|
||||
if (!Py_IS_TYPE(lhs, Py_TYPE(rhs))) {
|
||||
SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_DIFFERENT_TYPES);
|
||||
goto failure;
|
||||
}
|
||||
switch (adaptive->original_oparg) {
|
||||
case NB_ADD:
|
||||
case NB_INPLACE_ADD:
|
||||
if (PyUnicode_CheckExact(lhs)) {
|
||||
if (_Py_OPCODE(instr[1]) == STORE_FAST && Py_REFCNT(lhs) == 2) {
|
||||
*instr = _Py_MAKECODEUNIT(BINARY_OP_INPLACE_ADD_UNICODE,
|
||||
_Py_OPARG(*instr));
|
||||
goto success;
|
||||
}
|
||||
*instr = _Py_MAKECODEUNIT(BINARY_OP_ADD_UNICODE,
|
||||
_Py_OPARG(*instr));
|
||||
goto success;
|
||||
}
|
||||
if (PyLong_CheckExact(lhs)) {
|
||||
*instr = _Py_MAKECODEUNIT(BINARY_OP_ADD_INT, _Py_OPARG(*instr));
|
||||
goto success;
|
||||
}
|
||||
if (PyFloat_CheckExact(lhs)) {
|
||||
*instr = _Py_MAKECODEUNIT(BINARY_OP_ADD_FLOAT,
|
||||
_Py_OPARG(*instr));
|
||||
goto success;
|
||||
}
|
||||
break;
|
||||
case NB_MULTIPLY:
|
||||
case NB_INPLACE_MULTIPLY:
|
||||
if (PyLong_CheckExact(lhs)) {
|
||||
*instr = _Py_MAKECODEUNIT(BINARY_OP_MULTIPLY_INT,
|
||||
_Py_OPARG(*instr));
|
||||
goto success;
|
||||
}
|
||||
if (PyFloat_CheckExact(lhs)) {
|
||||
*instr = _Py_MAKECODEUNIT(BINARY_OP_MULTIPLY_FLOAT,
|
||||
_Py_OPARG(*instr));
|
||||
goto success;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// These operators don't have any available specializations. Rather
|
||||
// than repeatedly attempting to specialize them, just convert them
|
||||
// back to BINARY_OP (while still recording a failure, of course)!
|
||||
*instr = _Py_MAKECODEUNIT(BINARY_OP, adaptive->original_oparg);
|
||||
}
|
||||
SPECIALIZATION_FAIL(BINARY_OP, SPEC_FAIL_OTHER);
|
||||
failure:
|
||||
STAT_INC(BINARY_OP, specialization_failure);
|
||||
cache_backoff(adaptive);
|
||||
return;
|
||||
success:
|
||||
STAT_INC(BINARY_OP, specialization_success);
|
||||
adaptive->counter = initial_counter_value();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue