diff --git a/Include/internal/pycore_abstract.h b/Include/internal/pycore_abstract.h index b791bf24321..b1afb2dc7be 100644 --- a/Include/internal/pycore_abstract.h +++ b/Include/internal/pycore_abstract.h @@ -16,6 +16,9 @@ _PyIndex_Check(PyObject *obj) return (tp_as_number != NULL && tp_as_number->nb_index != NULL); } +PyObject *_PyNumber_PowerNoMod(PyObject *lhs, PyObject *rhs); +PyObject *_PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs); + #ifdef __cplusplus } #endif diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-15-13-32-54.bpo-45636.RDlTdL.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-15-13-32-54.bpo-45636.RDlTdL.rst new file mode 100644 index 00000000000..92b1b272f02 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-15-13-32-54.bpo-45636.RDlTdL.rst @@ -0,0 +1,2 @@ +Simplify the implementation of :opcode:`BINARY_OP` by indexing into an array +of function pointers (rather than switching on the oparg). diff --git a/Objects/abstract.c b/Objects/abstract.c index 6227ad5a18b..82599dd6eca 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1152,6 +1152,12 @@ PyNumber_Power(PyObject *v, PyObject *w, PyObject *z) return ternary_op(v, w, z, NB_SLOT(nb_power), "** or pow()"); } +PyObject * +_PyNumber_PowerNoMod(PyObject *lhs, PyObject *rhs) +{ + return PyNumber_Power(lhs, rhs, Py_None); +} + /* Binary in-place operators */ /* The in-place operators are defined to fall back to the 'normal', @@ -1331,6 +1337,12 @@ PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z) NB_SLOT(nb_power), "**="); } +PyObject * +_PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs) +{ + return PyNumber_InPlacePower(lhs, rhs, Py_None); +} + /* Unary operators and functions */ diff --git a/Python/ceval.c b/Python/ceval.c index bf4e22dc6fe..c02e3517d44 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -835,6 +835,36 @@ _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where) } +static const binaryfunc binary_ops[] = { + [NB_ADD] = PyNumber_Add, + [NB_AND] = PyNumber_And, + [NB_FLOOR_DIVIDE] = PyNumber_FloorDivide, + [NB_LSHIFT] = PyNumber_Lshift, + [NB_MATRIX_MULTIPLY] = PyNumber_MatrixMultiply, + [NB_MULTIPLY] = PyNumber_Multiply, + [NB_REMAINDER] = PyNumber_Remainder, + [NB_OR] = PyNumber_Or, + [NB_POWER] = _PyNumber_PowerNoMod, + [NB_RSHIFT] = PyNumber_Rshift, + [NB_SUBTRACT] = PyNumber_Subtract, + [NB_TRUE_DIVIDE] = PyNumber_TrueDivide, + [NB_XOR] = PyNumber_Xor, + [NB_INPLACE_ADD] = PyNumber_InPlaceAdd, + [NB_INPLACE_AND] = PyNumber_InPlaceAnd, + [NB_INPLACE_FLOOR_DIVIDE] = PyNumber_InPlaceFloorDivide, + [NB_INPLACE_LSHIFT] = PyNumber_InPlaceLshift, + [NB_INPLACE_MATRIX_MULTIPLY] = PyNumber_InPlaceMatrixMultiply, + [NB_INPLACE_MULTIPLY] = PyNumber_InPlaceMultiply, + [NB_INPLACE_REMAINDER] = PyNumber_InPlaceRemainder, + [NB_INPLACE_OR] = PyNumber_InPlaceOr, + [NB_INPLACE_POWER] = _PyNumber_InPlacePowerNoMod, + [NB_INPLACE_RSHIFT] = PyNumber_InPlaceRshift, + [NB_INPLACE_SUBTRACT] = PyNumber_InPlaceSubtract, + [NB_INPLACE_TRUE_DIVIDE] = PyNumber_InPlaceTrueDivide, + [NB_INPLACE_XOR] = PyNumber_InPlaceXor, +}; + + // PEP 634: Structural Pattern Matching @@ -4697,89 +4727,10 @@ check_eval_breaker: 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: - 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(); - } + assert(0 <= oparg); + assert((unsigned)oparg < Py_ARRAY_LENGTH(binary_ops)); + assert(binary_ops[oparg]); + PyObject *res = binary_ops[oparg](lhs, rhs); Py_DECREF(lhs); Py_DECREF(rhs); SET_TOP(res);