diff options
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 604 | ||||
-rw-r--r-- | Python/compile.c | 165 | ||||
-rw-r--r-- | Python/opcode_targets.h | 126 | ||||
-rw-r--r-- | Python/specialize.c | 143 |
4 files changed, 338 insertions, 700 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index fadb97a..030d983 100644 --- a/Python/ceval.c +++ b/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 * diff --git a/Python/compile.c b/Python/compile.c index 47889ab..8135f18 100644 --- a/Python/compile.c +++ b/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) -{ - 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) +addop_binary(struct compiler *c, operator_ty binop, bool inplace) { - 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)); diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 93a9e4a..a57617e 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -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, diff --git a/Python/specialize.c b/Python/specialize.c index 1627283..7e72013 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -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(); +} |