mirror of https://github.com/python/cpython
bpo-45510: Specialize BINARY_SUBTRACT (GH-29523)
This commit is contained in:
parent
0920b61a0c
commit
345ba3f080
|
@ -23,6 +23,7 @@ static inline PyObject* _PyLong_GetOne(void)
|
||||||
|
|
||||||
PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right);
|
PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right);
|
||||||
PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right);
|
PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right);
|
||||||
|
PyObject *_PyLong_Subtract(PyLongObject *left, PyLongObject *right);
|
||||||
|
|
||||||
/* Used by Python/mystrtoul.c, _PyBytes_FromHex(),
|
/* Used by Python/mystrtoul.c, _PyBytes_FromHex(),
|
||||||
_PyBytes_DecodeEscape(), etc. */
|
_PyBytes_DecodeEscape(), etc. */
|
||||||
|
|
|
@ -118,39 +118,41 @@ extern "C" {
|
||||||
#define BINARY_OP_INPLACE_ADD_UNICODE 16
|
#define BINARY_OP_INPLACE_ADD_UNICODE 16
|
||||||
#define BINARY_OP_MULTIPLY_INT 17
|
#define BINARY_OP_MULTIPLY_INT 17
|
||||||
#define BINARY_OP_MULTIPLY_FLOAT 18
|
#define BINARY_OP_MULTIPLY_FLOAT 18
|
||||||
#define BINARY_SUBSCR_ADAPTIVE 19
|
#define BINARY_OP_SUBTRACT_INT 19
|
||||||
#define BINARY_SUBSCR_LIST_INT 20
|
#define BINARY_OP_SUBTRACT_FLOAT 20
|
||||||
#define BINARY_SUBSCR_TUPLE_INT 21
|
#define BINARY_SUBSCR_ADAPTIVE 21
|
||||||
#define BINARY_SUBSCR_DICT 22
|
#define BINARY_SUBSCR_LIST_INT 22
|
||||||
#define CALL_FUNCTION_ADAPTIVE 23
|
#define BINARY_SUBSCR_TUPLE_INT 23
|
||||||
#define CALL_FUNCTION_BUILTIN_O 24
|
#define BINARY_SUBSCR_DICT 24
|
||||||
#define CALL_FUNCTION_BUILTIN_FAST 26
|
#define CALL_FUNCTION_ADAPTIVE 26
|
||||||
#define CALL_FUNCTION_LEN 27
|
#define CALL_FUNCTION_BUILTIN_O 27
|
||||||
#define CALL_FUNCTION_ISINSTANCE 28
|
#define CALL_FUNCTION_BUILTIN_FAST 28
|
||||||
#define CALL_FUNCTION_PY_SIMPLE 29
|
#define CALL_FUNCTION_LEN 29
|
||||||
#define JUMP_ABSOLUTE_QUICK 34
|
#define CALL_FUNCTION_ISINSTANCE 34
|
||||||
#define LOAD_ATTR_ADAPTIVE 36
|
#define CALL_FUNCTION_PY_SIMPLE 36
|
||||||
#define LOAD_ATTR_INSTANCE_VALUE 38
|
#define JUMP_ABSOLUTE_QUICK 38
|
||||||
#define LOAD_ATTR_WITH_HINT 39
|
#define LOAD_ATTR_ADAPTIVE 39
|
||||||
#define LOAD_ATTR_SLOT 40
|
#define LOAD_ATTR_INSTANCE_VALUE 40
|
||||||
#define LOAD_ATTR_MODULE 41
|
#define LOAD_ATTR_WITH_HINT 41
|
||||||
#define LOAD_GLOBAL_ADAPTIVE 42
|
#define LOAD_ATTR_SLOT 42
|
||||||
#define LOAD_GLOBAL_MODULE 43
|
#define LOAD_ATTR_MODULE 43
|
||||||
#define LOAD_GLOBAL_BUILTIN 44
|
#define LOAD_GLOBAL_ADAPTIVE 44
|
||||||
#define LOAD_METHOD_ADAPTIVE 45
|
#define LOAD_GLOBAL_MODULE 45
|
||||||
#define LOAD_METHOD_CACHED 46
|
#define LOAD_GLOBAL_BUILTIN 46
|
||||||
#define LOAD_METHOD_CLASS 47
|
#define LOAD_METHOD_ADAPTIVE 47
|
||||||
#define LOAD_METHOD_MODULE 48
|
#define LOAD_METHOD_CACHED 48
|
||||||
#define LOAD_METHOD_NO_DICT 55
|
#define LOAD_METHOD_CLASS 55
|
||||||
#define STORE_ATTR_ADAPTIVE 56
|
#define LOAD_METHOD_MODULE 56
|
||||||
#define STORE_ATTR_INSTANCE_VALUE 57
|
#define LOAD_METHOD_NO_DICT 57
|
||||||
#define STORE_ATTR_SLOT 58
|
#define STORE_ATTR_ADAPTIVE 58
|
||||||
#define STORE_ATTR_WITH_HINT 59
|
#define STORE_ATTR_INSTANCE_VALUE 59
|
||||||
#define LOAD_FAST__LOAD_FAST 62
|
#define STORE_ATTR_SLOT 62
|
||||||
#define STORE_FAST__LOAD_FAST 63
|
#define STORE_ATTR_WITH_HINT 63
|
||||||
#define LOAD_FAST__LOAD_CONST 64
|
#define LOAD_FAST__LOAD_FAST 64
|
||||||
#define LOAD_CONST__LOAD_FAST 65
|
#define STORE_FAST__LOAD_FAST 65
|
||||||
#define STORE_FAST__STORE_FAST 66
|
#define LOAD_FAST__LOAD_CONST 66
|
||||||
|
#define LOAD_CONST__LOAD_FAST 67
|
||||||
|
#define STORE_FAST__STORE_FAST 75
|
||||||
#define DO_TRACING 255
|
#define DO_TRACING 255
|
||||||
#ifdef NEED_OPCODE_JUMP_TABLES
|
#ifdef NEED_OPCODE_JUMP_TABLES
|
||||||
static uint32_t _PyOpcode_RelativeJump[8] = {
|
static uint32_t _PyOpcode_RelativeJump[8] = {
|
||||||
|
|
|
@ -231,6 +231,8 @@ _specialized_instructions = [
|
||||||
"BINARY_OP_INPLACE_ADD_UNICODE",
|
"BINARY_OP_INPLACE_ADD_UNICODE",
|
||||||
"BINARY_OP_MULTIPLY_INT",
|
"BINARY_OP_MULTIPLY_INT",
|
||||||
"BINARY_OP_MULTIPLY_FLOAT",
|
"BINARY_OP_MULTIPLY_FLOAT",
|
||||||
|
"BINARY_OP_SUBTRACT_INT",
|
||||||
|
"BINARY_OP_SUBTRACT_FLOAT",
|
||||||
"BINARY_SUBSCR_ADAPTIVE",
|
"BINARY_SUBSCR_ADAPTIVE",
|
||||||
"BINARY_SUBSCR_LIST_INT",
|
"BINARY_SUBSCR_LIST_INT",
|
||||||
"BINARY_SUBSCR_TUPLE_INT",
|
"BINARY_SUBSCR_TUPLE_INT",
|
||||||
|
|
|
@ -3155,14 +3155,11 @@ long_add(PyLongObject *a, PyLongObject *b)
|
||||||
return _PyLong_Add(a, b);
|
return _PyLong_Add(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
static PyObject *
|
_PyLong_Subtract(PyLongObject *a, PyLongObject *b)
|
||||||
long_sub(PyLongObject *a, PyLongObject *b)
|
|
||||||
{
|
{
|
||||||
PyLongObject *z;
|
PyLongObject *z;
|
||||||
|
|
||||||
CHECK_BINOP(a, b);
|
|
||||||
|
|
||||||
if (IS_MEDIUM_VALUE(a) && IS_MEDIUM_VALUE(b)) {
|
if (IS_MEDIUM_VALUE(a) && IS_MEDIUM_VALUE(b)) {
|
||||||
return _PyLong_FromSTwoDigits(medium_value(a) - medium_value(b));
|
return _PyLong_FromSTwoDigits(medium_value(a) - medium_value(b));
|
||||||
}
|
}
|
||||||
|
@ -3187,6 +3184,13 @@ long_sub(PyLongObject *a, PyLongObject *b)
|
||||||
return (PyObject *)z;
|
return (PyObject *)z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
long_sub(PyLongObject *a, PyLongObject *b)
|
||||||
|
{
|
||||||
|
CHECK_BINOP(a, b);
|
||||||
|
return _PyLong_Subtract(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
/* Grade school multiplication, ignoring the signs.
|
/* Grade school multiplication, ignoring the signs.
|
||||||
* Returns the absolute value of the product, or NULL if error.
|
* Returns the absolute value of the product, or NULL if error.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2009,6 +2009,41 @@ check_eval_breaker:
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TARGET(BINARY_OP_SUBTRACT_INT) {
|
||||||
|
PyObject *left = SECOND();
|
||||||
|
PyObject *right = TOP();
|
||||||
|
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
|
||||||
|
DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
|
||||||
|
STAT_INC(BINARY_OP, hit);
|
||||||
|
PyObject *sub = _PyLong_Subtract((PyLongObject *)left, (PyLongObject *)right);
|
||||||
|
SET_SECOND(sub);
|
||||||
|
Py_DECREF(right);
|
||||||
|
Py_DECREF(left);
|
||||||
|
STACK_SHRINK(1);
|
||||||
|
if (sub == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
|
||||||
|
TARGET(BINARY_OP_SUBTRACT_FLOAT) {
|
||||||
|
PyObject *left = SECOND();
|
||||||
|
PyObject *right = TOP();
|
||||||
|
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
|
||||||
|
DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);
|
||||||
|
STAT_INC(BINARY_OP, hit);
|
||||||
|
double dsub = ((PyFloatObject *)left)->ob_fval - ((PyFloatObject *)right)->ob_fval;
|
||||||
|
PyObject *sub = PyFloat_FromDouble(dsub);
|
||||||
|
SET_SECOND(sub);
|
||||||
|
Py_DECREF(right);
|
||||||
|
Py_DECREF(left);
|
||||||
|
STACK_SHRINK(1);
|
||||||
|
if (sub == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
|
||||||
TARGET(BINARY_OP_ADD_UNICODE) {
|
TARGET(BINARY_OP_ADD_UNICODE) {
|
||||||
PyObject *left = SECOND();
|
PyObject *left = SECOND();
|
||||||
PyObject *right = TOP();
|
PyObject *right = TOP();
|
||||||
|
|
|
@ -18,25 +18,27 @@ static void *opcode_targets[256] = {
|
||||||
&&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
|
&&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
|
||||||
&&TARGET_BINARY_OP_MULTIPLY_INT,
|
&&TARGET_BINARY_OP_MULTIPLY_INT,
|
||||||
&&TARGET_BINARY_OP_MULTIPLY_FLOAT,
|
&&TARGET_BINARY_OP_MULTIPLY_FLOAT,
|
||||||
|
&&TARGET_BINARY_OP_SUBTRACT_INT,
|
||||||
|
&&TARGET_BINARY_OP_SUBTRACT_FLOAT,
|
||||||
&&TARGET_BINARY_SUBSCR_ADAPTIVE,
|
&&TARGET_BINARY_SUBSCR_ADAPTIVE,
|
||||||
&&TARGET_BINARY_SUBSCR_LIST_INT,
|
&&TARGET_BINARY_SUBSCR_LIST_INT,
|
||||||
&&TARGET_BINARY_SUBSCR_TUPLE_INT,
|
&&TARGET_BINARY_SUBSCR_TUPLE_INT,
|
||||||
&&TARGET_BINARY_SUBSCR_DICT,
|
&&TARGET_BINARY_SUBSCR_DICT,
|
||||||
|
&&TARGET_BINARY_SUBSCR,
|
||||||
&&TARGET_CALL_FUNCTION_ADAPTIVE,
|
&&TARGET_CALL_FUNCTION_ADAPTIVE,
|
||||||
&&TARGET_CALL_FUNCTION_BUILTIN_O,
|
&&TARGET_CALL_FUNCTION_BUILTIN_O,
|
||||||
&&TARGET_BINARY_SUBSCR,
|
|
||||||
&&TARGET_CALL_FUNCTION_BUILTIN_FAST,
|
&&TARGET_CALL_FUNCTION_BUILTIN_FAST,
|
||||||
&&TARGET_CALL_FUNCTION_LEN,
|
&&TARGET_CALL_FUNCTION_LEN,
|
||||||
&&TARGET_CALL_FUNCTION_ISINSTANCE,
|
|
||||||
&&TARGET_CALL_FUNCTION_PY_SIMPLE,
|
|
||||||
&&TARGET_GET_LEN,
|
&&TARGET_GET_LEN,
|
||||||
&&TARGET_MATCH_MAPPING,
|
&&TARGET_MATCH_MAPPING,
|
||||||
&&TARGET_MATCH_SEQUENCE,
|
&&TARGET_MATCH_SEQUENCE,
|
||||||
&&TARGET_MATCH_KEYS,
|
&&TARGET_MATCH_KEYS,
|
||||||
&&TARGET_JUMP_ABSOLUTE_QUICK,
|
&&TARGET_CALL_FUNCTION_ISINSTANCE,
|
||||||
&&TARGET_PUSH_EXC_INFO,
|
&&TARGET_PUSH_EXC_INFO,
|
||||||
&&TARGET_LOAD_ATTR_ADAPTIVE,
|
&&TARGET_CALL_FUNCTION_PY_SIMPLE,
|
||||||
&&TARGET_POP_EXCEPT_AND_RERAISE,
|
&&TARGET_POP_EXCEPT_AND_RERAISE,
|
||||||
|
&&TARGET_JUMP_ABSOLUTE_QUICK,
|
||||||
|
&&TARGET_LOAD_ATTR_ADAPTIVE,
|
||||||
&&TARGET_LOAD_ATTR_INSTANCE_VALUE,
|
&&TARGET_LOAD_ATTR_INSTANCE_VALUE,
|
||||||
&&TARGET_LOAD_ATTR_WITH_HINT,
|
&&TARGET_LOAD_ATTR_WITH_HINT,
|
||||||
&&TARGET_LOAD_ATTR_SLOT,
|
&&TARGET_LOAD_ATTR_SLOT,
|
||||||
|
@ -46,27 +48,25 @@ static void *opcode_targets[256] = {
|
||||||
&&TARGET_LOAD_GLOBAL_BUILTIN,
|
&&TARGET_LOAD_GLOBAL_BUILTIN,
|
||||||
&&TARGET_LOAD_METHOD_ADAPTIVE,
|
&&TARGET_LOAD_METHOD_ADAPTIVE,
|
||||||
&&TARGET_LOAD_METHOD_CACHED,
|
&&TARGET_LOAD_METHOD_CACHED,
|
||||||
&&TARGET_LOAD_METHOD_CLASS,
|
|
||||||
&&TARGET_LOAD_METHOD_MODULE,
|
|
||||||
&&TARGET_WITH_EXCEPT_START,
|
&&TARGET_WITH_EXCEPT_START,
|
||||||
&&TARGET_GET_AITER,
|
&&TARGET_GET_AITER,
|
||||||
&&TARGET_GET_ANEXT,
|
&&TARGET_GET_ANEXT,
|
||||||
&&TARGET_BEFORE_ASYNC_WITH,
|
&&TARGET_BEFORE_ASYNC_WITH,
|
||||||
&&TARGET_BEFORE_WITH,
|
&&TARGET_BEFORE_WITH,
|
||||||
&&TARGET_END_ASYNC_FOR,
|
&&TARGET_END_ASYNC_FOR,
|
||||||
|
&&TARGET_LOAD_METHOD_CLASS,
|
||||||
|
&&TARGET_LOAD_METHOD_MODULE,
|
||||||
&&TARGET_LOAD_METHOD_NO_DICT,
|
&&TARGET_LOAD_METHOD_NO_DICT,
|
||||||
&&TARGET_STORE_ATTR_ADAPTIVE,
|
&&TARGET_STORE_ATTR_ADAPTIVE,
|
||||||
&&TARGET_STORE_ATTR_INSTANCE_VALUE,
|
&&TARGET_STORE_ATTR_INSTANCE_VALUE,
|
||||||
&&TARGET_STORE_ATTR_SLOT,
|
|
||||||
&&TARGET_STORE_ATTR_WITH_HINT,
|
|
||||||
&&TARGET_STORE_SUBSCR,
|
&&TARGET_STORE_SUBSCR,
|
||||||
&&TARGET_DELETE_SUBSCR,
|
&&TARGET_DELETE_SUBSCR,
|
||||||
|
&&TARGET_STORE_ATTR_SLOT,
|
||||||
|
&&TARGET_STORE_ATTR_WITH_HINT,
|
||||||
&&TARGET_LOAD_FAST__LOAD_FAST,
|
&&TARGET_LOAD_FAST__LOAD_FAST,
|
||||||
&&TARGET_STORE_FAST__LOAD_FAST,
|
&&TARGET_STORE_FAST__LOAD_FAST,
|
||||||
&&TARGET_LOAD_FAST__LOAD_CONST,
|
&&TARGET_LOAD_FAST__LOAD_CONST,
|
||||||
&&TARGET_LOAD_CONST__LOAD_FAST,
|
&&TARGET_LOAD_CONST__LOAD_FAST,
|
||||||
&&TARGET_STORE_FAST__STORE_FAST,
|
|
||||||
&&_unknown_opcode,
|
|
||||||
&&TARGET_GET_ITER,
|
&&TARGET_GET_ITER,
|
||||||
&&TARGET_GET_YIELD_FROM_ITER,
|
&&TARGET_GET_YIELD_FROM_ITER,
|
||||||
&&TARGET_PRINT_EXPR,
|
&&TARGET_PRINT_EXPR,
|
||||||
|
@ -74,7 +74,7 @@ static void *opcode_targets[256] = {
|
||||||
&&TARGET_YIELD_FROM,
|
&&TARGET_YIELD_FROM,
|
||||||
&&TARGET_GET_AWAITABLE,
|
&&TARGET_GET_AWAITABLE,
|
||||||
&&TARGET_LOAD_ASSERTION_ERROR,
|
&&TARGET_LOAD_ASSERTION_ERROR,
|
||||||
&&_unknown_opcode,
|
&&TARGET_STORE_FAST__STORE_FAST,
|
||||||
&&_unknown_opcode,
|
&&_unknown_opcode,
|
||||||
&&_unknown_opcode,
|
&&_unknown_opcode,
|
||||||
&&_unknown_opcode,
|
&&_unknown_opcode,
|
||||||
|
|
|
@ -1424,6 +1424,19 @@ _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
|
||||||
goto success;
|
goto success;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case NB_SUBTRACT:
|
||||||
|
case NB_INPLACE_SUBTRACT:
|
||||||
|
if (PyLong_CheckExact(lhs)) {
|
||||||
|
*instr = _Py_MAKECODEUNIT(BINARY_OP_SUBTRACT_INT,
|
||||||
|
_Py_OPARG(*instr));
|
||||||
|
goto success;
|
||||||
|
}
|
||||||
|
if (PyFloat_CheckExact(lhs)) {
|
||||||
|
*instr = _Py_MAKECODEUNIT(BINARY_OP_SUBTRACT_FLOAT,
|
||||||
|
_Py_OPARG(*instr));
|
||||||
|
goto success;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// These operators don't have any available specializations. Rather
|
// These operators don't have any available specializations. Rather
|
||||||
// than repeatedly attempting to specialize them, just convert them
|
// than repeatedly attempting to specialize them, just convert them
|
||||||
|
|
Loading…
Reference in New Issue