[Python-checkins] bpo-45636: Simplify BINARY_OP (GH-29565)

brandtbucher webhook-mailer at python.org
Tue Nov 16 08:54:06 EST 2021


https://github.com/python/cpython/commit/6a84d61c55f2e543cf5fa84522d8781a795bba33
commit: 6a84d61c55f2e543cf5fa84522d8781a795bba33
branch: main
author: Brandt Bucher <brandt at python.org>
committer: brandtbucher <brandtbucher at gmail.com>
date: 2021-11-16T05:53:57-08:00
summary:

bpo-45636: Simplify BINARY_OP (GH-29565)

files:
A Misc/NEWS.d/next/Core and Builtins/2021-11-15-13-32-54.bpo-45636.RDlTdL.rst
M Include/internal/pycore_abstract.h
M Objects/abstract.c
M Python/ceval.c

diff --git a/Include/internal/pycore_abstract.h b/Include/internal/pycore_abstract.h
index b791bf2432199..b1afb2dc7be65 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 0000000000000..92b1b272f0215
--- /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 6227ad5a18bb9..82599dd6eca23 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 bf4e22dc6fec4..c02e3517d44f4 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 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
             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);



More information about the Python-checkins mailing list