diff -r 4cf08147a52e Python/ceval.c --- a/Python/ceval.c Mon Feb 08 01:49:35 2016 +0000 +++ b/Python/ceval.c Sun Feb 07 16:27:55 2016 -0500 @@ -1118,6 +1118,21 @@ Py_XDECREF(traceback); \ } +#define TRY_FAST_NUM_BINOP_DISPATCH(OP, left, right) \ + { \ + if (PyLong_CheckExact(left) && PyLong_CheckExact(right)) { \ + PyObject *result; \ + result = PyLong_Type.tp_as_number->OP(left, right); \ + Py_DECREF(left); \ + Py_DECREF(right); \ + SET_TOP(result); \ + if (result == NULL) { \ + goto error; \ + } \ + DISPATCH(); \ + } \ + } + /* Start of code */ /* push frame */ @@ -1497,12 +1512,15 @@ TARGET(BINARY_MULTIPLY) { PyObject *right = POP(); PyObject *left = TOP(); - PyObject *res = PyNumber_Multiply(left, right); + PyObject *res; + TRY_FAST_NUM_BINOP_DISPATCH(nb_multiply, left, right); + res = PyNumber_Multiply(left, right); Py_DECREF(left); Py_DECREF(right); SET_TOP(res); - if (res == NULL) + if (res == NULL) { goto error; + } DISPATCH(); } @@ -1521,33 +1539,48 @@ TARGET(BINARY_TRUE_DIVIDE) { PyObject *divisor = POP(); PyObject *dividend = TOP(); - PyObject *quotient = PyNumber_TrueDivide(dividend, divisor); + PyObject *quotient; + TRY_FAST_NUM_BINOP_DISPATCH(nb_true_divide, dividend, divisor); + quotient = PyNumber_TrueDivide(dividend, divisor); Py_DECREF(dividend); Py_DECREF(divisor); + SET_TOP(quotient); - if (quotient == NULL) + if (quotient == NULL) { goto error; + } DISPATCH(); } TARGET(BINARY_FLOOR_DIVIDE) { PyObject *divisor = POP(); PyObject *dividend = TOP(); - PyObject *quotient = PyNumber_FloorDivide(dividend, divisor); + PyObject *quotient; + TRY_FAST_NUM_BINOP_DISPATCH(nb_floor_divide, dividend, divisor); + quotient = PyNumber_FloorDivide(dividend, divisor); Py_DECREF(dividend); Py_DECREF(divisor); + SET_TOP(quotient); - if (quotient == NULL) + if (quotient == NULL) { goto error; + } DISPATCH(); } TARGET(BINARY_MODULO) { PyObject *divisor = POP(); PyObject *dividend = TOP(); - PyObject *res = PyUnicode_CheckExact(dividend) ? - PyUnicode_Format(dividend, divisor) : - PyNumber_Remainder(dividend, divisor); + PyObject *res; + + if (PyUnicode_CheckExact(dividend)) { + res = PyUnicode_Format(dividend, divisor); + } + else { + TRY_FAST_NUM_BINOP_DISPATCH(nb_remainder, dividend, divisor); + res = PyNumber_Remainder(dividend, divisor); + } + Py_DECREF(divisor); Py_DECREF(dividend); SET_TOP(res); @@ -1560,31 +1593,39 @@ PyObject *right = POP(); PyObject *left = TOP(); PyObject *sum; - if (PyUnicode_CheckExact(left) && - PyUnicode_CheckExact(right)) { + + if (PyUnicode_CheckExact(left) && PyUnicode_CheckExact(right)) { + /* fast path for string concatenation */ sum = unicode_concatenate(left, right, f, next_instr); - /* unicode_concatenate consumed the ref to v */ + /* unicode_concatenate consumed the ref to left */ } else { + TRY_FAST_NUM_BINOP_DISPATCH(nb_add, left, right); sum = PyNumber_Add(left, right); Py_DECREF(left); } + Py_DECREF(right); SET_TOP(sum); - if (sum == NULL) + if (sum == NULL) { goto error; + } DISPATCH(); } TARGET(BINARY_SUBTRACT) { PyObject *right = POP(); PyObject *left = TOP(); - PyObject *diff = PyNumber_Subtract(left, right); + PyObject *diff; + TRY_FAST_NUM_BINOP_DISPATCH(nb_subtract, left, right); + diff = PyNumber_Subtract(left, right); Py_DECREF(right); Py_DECREF(left); + SET_TOP(diff); - if (diff == NULL) + if (diff == NULL) { goto error; + } DISPATCH(); } @@ -1603,7 +1644,13 @@ TARGET(BINARY_LSHIFT) { PyObject *right = POP(); PyObject *left = TOP(); - PyObject *res = PyNumber_Lshift(left, right); + PyObject *res; + if (PyLong_CheckExact(left) && PyLong_CheckExact(right)) { + res = PyLong_Type.tp_as_number->nb_lshift(left, right); + } + else { + res = PyNumber_Lshift(left, right); + } Py_DECREF(left); Py_DECREF(right); SET_TOP(res); @@ -1615,7 +1662,13 @@ TARGET(BINARY_RSHIFT) { PyObject *right = POP(); PyObject *left = TOP(); - PyObject *res = PyNumber_Rshift(left, right); + PyObject *res; + if (PyLong_CheckExact(left) && PyLong_CheckExact(right)) { + res = PyLong_Type.tp_as_number->nb_rshift(left, right); + } + else { + res = PyNumber_Rshift(left, right); + } Py_DECREF(left); Py_DECREF(right); SET_TOP(res); @@ -1699,12 +1752,16 @@ TARGET(INPLACE_MULTIPLY) { PyObject *right = POP(); PyObject *left = TOP(); - PyObject *res = PyNumber_InPlaceMultiply(left, right); + PyObject *res; + TRY_FAST_NUM_BINOP_DISPATCH(nb_multiply, left, right); + res = PyNumber_InPlaceMultiply(left, right); Py_DECREF(left); Py_DECREF(right); + SET_TOP(res); - if (res == NULL) + if (res == NULL) { goto error; + } DISPATCH(); } @@ -1723,31 +1780,41 @@ TARGET(INPLACE_TRUE_DIVIDE) { PyObject *divisor = POP(); PyObject *dividend = TOP(); - PyObject *quotient = PyNumber_InPlaceTrueDivide(dividend, divisor); + PyObject *quotient; + TRY_FAST_NUM_BINOP_DISPATCH(nb_true_divide, dividend, divisor); + quotient = PyNumber_InPlaceTrueDivide(dividend, divisor); Py_DECREF(dividend); Py_DECREF(divisor); + SET_TOP(quotient); - if (quotient == NULL) + if (quotient == NULL) { goto error; + } DISPATCH(); } TARGET(INPLACE_FLOOR_DIVIDE) { PyObject *divisor = POP(); PyObject *dividend = TOP(); - PyObject *quotient = PyNumber_InPlaceFloorDivide(dividend, divisor); + PyObject *quotient; + TRY_FAST_NUM_BINOP_DISPATCH(nb_floor_divide, dividend, divisor); + quotient = PyNumber_InPlaceFloorDivide(dividend, divisor); Py_DECREF(dividend); Py_DECREF(divisor); + SET_TOP(quotient); - if (quotient == NULL) + if (quotient == NULL) { goto error; + } DISPATCH(); } TARGET(INPLACE_MODULO) { PyObject *right = POP(); PyObject *left = TOP(); - PyObject *mod = PyNumber_InPlaceRemainder(left, right); + PyObject *mod; + TRY_FAST_NUM_BINOP_DISPATCH(nb_remainder, left, right); + mod = PyNumber_InPlaceRemainder(left, right); Py_DECREF(left); Py_DECREF(right); SET_TOP(mod); @@ -1760,30 +1827,39 @@ PyObject *right = POP(); PyObject *left = TOP(); PyObject *sum; + if (PyUnicode_CheckExact(left) && PyUnicode_CheckExact(right)) { + /* fast path for string concatenation */ sum = unicode_concatenate(left, right, f, next_instr); - /* unicode_concatenate consumed the ref to v */ + /* unicode_concatenate consumed the ref to left */ } else { + TRY_FAST_NUM_BINOP_DISPATCH(nb_add, left, right); sum = PyNumber_InPlaceAdd(left, right); Py_DECREF(left); } + Py_DECREF(right); SET_TOP(sum); - if (sum == NULL) + if (sum == NULL) { goto error; + } DISPATCH(); } TARGET(INPLACE_SUBTRACT) { PyObject *right = POP(); PyObject *left = TOP(); - PyObject *diff = PyNumber_InPlaceSubtract(left, right); + PyObject *diff; + TRY_FAST_NUM_BINOP_DISPATCH(nb_subtract, left, right); + diff = PyNumber_InPlaceSubtract(left, right); Py_DECREF(left); Py_DECREF(right); + SET_TOP(diff); - if (diff == NULL) + if (diff == NULL) { goto error; + } DISPATCH(); }