diff options
author | Mark Shannon <mark@hotpy.org> | 2023-01-16 12:35:21 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-16 12:35:21 (GMT) |
commit | 7b14c2ef194b6eed79670aa9d7e29ab8e2256a56 (patch) | |
tree | 794188d49a9f359cfa7663c25be587634f070f22 /Python | |
parent | b1a74a182d8762bda51838401ac92b6ebad9632a (diff) | |
download | cpython-7b14c2ef194b6eed79670aa9d7e29ab8e2256a56.zip cpython-7b14c2ef194b6eed79670aa9d7e29ab8e2256a56.tar.gz cpython-7b14c2ef194b6eed79670aa9d7e29ab8e2256a56.tar.bz2 |
GH-100982: Add `COMPARE_AND_BRANCH` instruction (GH-100983)
Diffstat (limited to 'Python')
-rw-r--r-- | Python/bytecodes.c | 107 | ||||
-rw-r--r-- | Python/compile.c | 3 | ||||
-rw-r--r-- | Python/generated_cases.c.h | 187 | ||||
-rw-r--r-- | Python/opcode_metadata.h | 9 | ||||
-rw-r--r-- | Python/opcode_targets.h | 14 | ||||
-rw-r--r-- | Python/specialize.c | 81 |
6 files changed, 199 insertions, 202 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c index faa6df6..18f9eab 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -90,11 +90,6 @@ static size_t jump; // Dummy variables for cache effects static uint16_t invert, counter, index, hint; static uint32_t type_version; -// Dummy opcode names for 'op' opcodes -#define _COMPARE_OP_FLOAT 1003 -#define _COMPARE_OP_INT 1004 -#define _COMPARE_OP_STR 1005 -#define _JUMP_IF 1006 static PyObject * dummy_func( @@ -1829,64 +1824,76 @@ dummy_func( Py_DECREF(owner); } - family(compare_op) = { - COMPARE_OP, - _COMPARE_OP_FLOAT, - _COMPARE_OP_INT, - _COMPARE_OP_STR, + inst(COMPARE_OP, (unused/1, left, right -- res)) { + STAT_INC(COMPARE_OP, deferred); + assert((oparg >> 4) <= Py_GE); + res = PyObject_RichCompare(left, right, oparg>>4); + Py_DECREF(left); + Py_DECREF(right); + ERROR_IF(res == NULL, error); + } + + family(compare_and_branch) = { + COMPARE_AND_BRANCH, + COMPARE_AND_BRANCH_FLOAT, + COMPARE_AND_BRANCH_INT, + COMPARE_AND_BRANCH_STR, }; - inst(COMPARE_OP, (unused/1, left, right -- res)) { + inst(COMPARE_AND_BRANCH, (unused/2, left, right -- )) { _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { assert(cframe.use_tracing == 0); next_instr--; - _Py_Specialize_CompareOp(left, right, next_instr, oparg); + _Py_Specialize_CompareAndBranch(left, right, next_instr, oparg); DISPATCH_SAME_OPARG(); } - STAT_INC(COMPARE_OP, deferred); + STAT_INC(COMPARE_AND_BRANCH, deferred); DECREMENT_ADAPTIVE_COUNTER(cache->counter); assert((oparg >> 4) <= Py_GE); - res = PyObject_RichCompare(left, right, oparg>>4); + PyObject *cond = PyObject_RichCompare(left, right, oparg>>4); Py_DECREF(left); Py_DECREF(right); - ERROR_IF(res == NULL, error); + ERROR_IF(cond == NULL, error); + assert(_Py_OPCODE(next_instr[1]) == POP_JUMP_IF_FALSE || + _Py_OPCODE(next_instr[1]) == POP_JUMP_IF_TRUE); + bool jump_on_true = _Py_OPCODE(next_instr[1]) == POP_JUMP_IF_TRUE; + int offset = _Py_OPARG(next_instr[1]); + int err = PyObject_IsTrue(cond); + Py_DECREF(cond); + if (err < 0) { + goto error; + } + if (jump_on_true == (err != 0)) { + JUMPBY(offset); + } } - // The result is an int disguised as an object pointer. - op(_COMPARE_OP_FLOAT, (unused/1, left, right -- jump: size_t)) { + inst(COMPARE_AND_BRANCH_FLOAT, (unused/2, left, right -- )) { assert(cframe.use_tracing == 0); - // Combined: COMPARE_OP (float ? float) + POP_JUMP_IF_(true/false) - DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP); - DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP); - STAT_INC(COMPARE_OP, hit); + DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_AND_BRANCH); + DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_AND_BRANCH); + STAT_INC(COMPARE_AND_BRANCH, hit); double dleft = PyFloat_AS_DOUBLE(left); double dright = PyFloat_AS_DOUBLE(right); // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches low four bits of the oparg int sign_ish = COMPARISON_BIT(dleft, dright); _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc); _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); - jump = sign_ish & oparg; - } - // The input is an int disguised as an object pointer! - op(_JUMP_IF, (jump: size_t --)) { - assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE); - if (jump) { - JUMPBY(oparg); + if (sign_ish & oparg) { + int offset = _Py_OPARG(next_instr[1]); + JUMPBY(offset); } } - // We're praying that the compiler optimizes the flags manipuations. - super(COMPARE_OP_FLOAT_JUMP) = _COMPARE_OP_FLOAT + _JUMP_IF; - // Similar to COMPARE_OP_FLOAT - op(_COMPARE_OP_INT, (unused/1, left, right -- jump: size_t)) { + // Similar to COMPARE_AND_BRANCH_FLOAT + inst(COMPARE_AND_BRANCH_INT, (unused/2, left, right -- )) { assert(cframe.use_tracing == 0); - // Combined: COMPARE_OP (int ? int) + POP_JUMP_IF_(true/false) - DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP); - DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP); - DEOPT_IF((size_t)(Py_SIZE(left) + 1) > 2, COMPARE_OP); - DEOPT_IF((size_t)(Py_SIZE(right) + 1) > 2, COMPARE_OP); - STAT_INC(COMPARE_OP, hit); + DEOPT_IF(!PyLong_CheckExact(left), COMPARE_AND_BRANCH); + DEOPT_IF(!PyLong_CheckExact(right), COMPARE_AND_BRANCH); + DEOPT_IF((size_t)(Py_SIZE(left) + 1) > 2, COMPARE_AND_BRANCH); + DEOPT_IF((size_t)(Py_SIZE(right) + 1) > 2, COMPARE_AND_BRANCH); + STAT_INC(COMPARE_AND_BRANCH, hit); assert(Py_ABS(Py_SIZE(left)) <= 1 && Py_ABS(Py_SIZE(right)) <= 1); Py_ssize_t ileft = Py_SIZE(left) * ((PyLongObject *)left)->ob_digit[0]; Py_ssize_t iright = Py_SIZE(right) * ((PyLongObject *)right)->ob_digit[0]; @@ -1894,17 +1901,18 @@ dummy_func( int sign_ish = COMPARISON_BIT(ileft, iright); _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); - jump = sign_ish & oparg; + if (sign_ish & oparg) { + int offset = _Py_OPARG(next_instr[1]); + JUMPBY(offset); + } } - super(COMPARE_OP_INT_JUMP) = _COMPARE_OP_INT + _JUMP_IF; - // Similar to COMPARE_OP_FLOAT, but for ==, != only - op(_COMPARE_OP_STR, (unused/1, left, right -- jump: size_t)) { + // Similar to COMPARE_AND_BRANCH_FLOAT, but for ==, != only + inst(COMPARE_AND_BRANCH_STR, (unused/2, left, right -- )) { assert(cframe.use_tracing == 0); - // Combined: COMPARE_OP (str == str or str != str) + POP_JUMP_IF_(true/false) - DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP); - DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP); - STAT_INC(COMPARE_OP, hit); + DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_AND_BRANCH); + DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_AND_BRANCH); + STAT_INC(COMPARE_AND_BRANCH, hit); int res = _PyUnicode_Equal(left, right); assert((oparg >>4) == Py_EQ || (oparg >>4) == Py_NE); _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); @@ -1912,11 +1920,12 @@ dummy_func( assert(res == 0 || res == 1); assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS); assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS); - jump = (res + COMPARISON_NOT_EQUALS) & oparg; + if ((res + COMPARISON_NOT_EQUALS) & oparg) { + int offset = _Py_OPARG(next_instr[1]); + JUMPBY(offset); + } } - super(COMPARE_OP_STR_JUMP) = _COMPARE_OP_STR + _JUMP_IF; - inst(IS_OP, (left, right -- b)) { int res = Py_Is(left, right) ^ oparg; DECREF_INPUTS(); diff --git a/Python/compile.c b/Python/compile.c index c0177fb..f98892e 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1195,6 +1195,9 @@ stack_effect(int opcode, int oparg, int jump) case POP_JUMP_IF_TRUE: return -1; + case COMPARE_AND_BRANCH: + return -2; + case LOAD_GLOBAL: return (oparg & 1) + 1; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 9874ddf..e9819df 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -2077,19 +2077,10 @@ } TARGET(COMPARE_OP) { - PREDICTED(COMPARE_OP); PyObject *right = PEEK(1); PyObject *left = PEEK(2); PyObject *res; - _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr; - if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { - assert(cframe.use_tracing == 0); - next_instr--; - _Py_Specialize_CompareOp(left, right, next_instr, oparg); - DISPATCH_SAME_OPARG(); - } STAT_INC(COMPARE_OP, deferred); - DECREMENT_ADAPTIVE_COUNTER(cache->counter); assert((oparg >> 4) <= Py_GE); res = PyObject_RichCompare(left, right, oparg>>4); Py_DECREF(left); @@ -2101,112 +2092,108 @@ DISPATCH(); } - TARGET(COMPARE_OP_FLOAT_JUMP) { - PyObject *_tmp_1 = PEEK(1); - PyObject *_tmp_2 = PEEK(2); - { - PyObject *right = _tmp_1; - PyObject *left = _tmp_2; - size_t jump; + TARGET(COMPARE_AND_BRANCH) { + PREDICTED(COMPARE_AND_BRANCH); + PyObject *right = PEEK(1); + PyObject *left = PEEK(2); + _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr; + if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { assert(cframe.use_tracing == 0); - // Combined: COMPARE_OP (float ? float) + POP_JUMP_IF_(true/false) - DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP); - DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP); - STAT_INC(COMPARE_OP, hit); - double dleft = PyFloat_AS_DOUBLE(left); - double dright = PyFloat_AS_DOUBLE(right); - // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches low four bits of the oparg - int sign_ish = COMPARISON_BIT(dleft, dright); - _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc); - _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); - jump = sign_ish & oparg; - _tmp_2 = (PyObject *)jump; + next_instr--; + _Py_Specialize_CompareAndBranch(left, right, next_instr, oparg); + DISPATCH_SAME_OPARG(); } - JUMPBY(1); - NEXTOPARG(); - JUMPBY(1); - { - size_t jump = (size_t)_tmp_2; - assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE); - if (jump) { - JUMPBY(oparg); - } + STAT_INC(COMPARE_AND_BRANCH, deferred); + DECREMENT_ADAPTIVE_COUNTER(cache->counter); + assert((oparg >> 4) <= Py_GE); + PyObject *cond = PyObject_RichCompare(left, right, oparg>>4); + Py_DECREF(left); + Py_DECREF(right); + if (cond == NULL) goto pop_2_error; + assert(_Py_OPCODE(next_instr[1]) == POP_JUMP_IF_FALSE || + _Py_OPCODE(next_instr[1]) == POP_JUMP_IF_TRUE); + bool jump_on_true = _Py_OPCODE(next_instr[1]) == POP_JUMP_IF_TRUE; + int offset = _Py_OPARG(next_instr[1]); + int err = PyObject_IsTrue(cond); + Py_DECREF(cond); + if (err < 0) { + goto error; + } + if (jump_on_true == (err != 0)) { + JUMPBY(offset); } STACK_SHRINK(2); + JUMPBY(2); DISPATCH(); } - TARGET(COMPARE_OP_INT_JUMP) { - PyObject *_tmp_1 = PEEK(1); - PyObject *_tmp_2 = PEEK(2); - { - PyObject *right = _tmp_1; - PyObject *left = _tmp_2; - size_t jump; - assert(cframe.use_tracing == 0); - // Combined: COMPARE_OP (int ? int) + POP_JUMP_IF_(true/false) - DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP); - DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP); - DEOPT_IF((size_t)(Py_SIZE(left) + 1) > 2, COMPARE_OP); - DEOPT_IF((size_t)(Py_SIZE(right) + 1) > 2, COMPARE_OP); - STAT_INC(COMPARE_OP, hit); - assert(Py_ABS(Py_SIZE(left)) <= 1 && Py_ABS(Py_SIZE(right)) <= 1); - Py_ssize_t ileft = Py_SIZE(left) * ((PyLongObject *)left)->ob_digit[0]; - Py_ssize_t iright = Py_SIZE(right) * ((PyLongObject *)right)->ob_digit[0]; - // 2 if <, 4 if >, 8 if ==; this matches the low 4 bits of the oparg - int sign_ish = COMPARISON_BIT(ileft, iright); - _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); - _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); - jump = sign_ish & oparg; - _tmp_2 = (PyObject *)jump; - } - JUMPBY(1); - NEXTOPARG(); - JUMPBY(1); - { - size_t jump = (size_t)_tmp_2; - assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE); - if (jump) { - JUMPBY(oparg); - } + TARGET(COMPARE_AND_BRANCH_FLOAT) { + PyObject *right = PEEK(1); + PyObject *left = PEEK(2); + assert(cframe.use_tracing == 0); + DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_AND_BRANCH); + DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_AND_BRANCH); + STAT_INC(COMPARE_AND_BRANCH, hit); + double dleft = PyFloat_AS_DOUBLE(left); + double dright = PyFloat_AS_DOUBLE(right); + // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches low four bits of the oparg + int sign_ish = COMPARISON_BIT(dleft, dright); + _Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc); + _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc); + if (sign_ish & oparg) { + int offset = _Py_OPARG(next_instr[1]); + JUMPBY(offset); } STACK_SHRINK(2); + JUMPBY(2); DISPATCH(); } - TARGET(COMPARE_OP_STR_JUMP) { - PyObject *_tmp_1 = PEEK(1); - PyObject *_tmp_2 = PEEK(2); - { - PyObject *right = _tmp_1; - PyObject *left = _tmp_2; - size_t jump; - assert(cframe.use_tracing == 0); - // Combined: COMPARE_OP (str == str or str != str) + POP_JUMP_IF_(true/false) - DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP); - DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP); - STAT_INC(COMPARE_OP, hit); - int res = _PyUnicode_Equal(left, right); - assert((oparg >>4) == Py_EQ || (oparg >>4) == Py_NE); - _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); - _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); - assert(res == 0 || res == 1); - assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS); - assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS); - jump = (res + COMPARISON_NOT_EQUALS) & oparg; - _tmp_2 = (PyObject *)jump; + TARGET(COMPARE_AND_BRANCH_INT) { + PyObject *right = PEEK(1); + PyObject *left = PEEK(2); + assert(cframe.use_tracing == 0); + DEOPT_IF(!PyLong_CheckExact(left), COMPARE_AND_BRANCH); + DEOPT_IF(!PyLong_CheckExact(right), COMPARE_AND_BRANCH); + DEOPT_IF((size_t)(Py_SIZE(left) + 1) > 2, COMPARE_AND_BRANCH); + DEOPT_IF((size_t)(Py_SIZE(right) + 1) > 2, COMPARE_AND_BRANCH); + STAT_INC(COMPARE_AND_BRANCH, hit); + assert(Py_ABS(Py_SIZE(left)) <= 1 && Py_ABS(Py_SIZE(right)) <= 1); + Py_ssize_t ileft = Py_SIZE(left) * ((PyLongObject *)left)->ob_digit[0]; + Py_ssize_t iright = Py_SIZE(right) * ((PyLongObject *)right)->ob_digit[0]; + // 2 if <, 4 if >, 8 if ==; this matches the low 4 bits of the oparg + int sign_ish = COMPARISON_BIT(ileft, iright); + _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free); + _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free); + if (sign_ish & oparg) { + int offset = _Py_OPARG(next_instr[1]); + JUMPBY(offset); } - JUMPBY(1); - NEXTOPARG(); - JUMPBY(1); - { - size_t jump = (size_t)_tmp_2; - assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE); - if (jump) { - JUMPBY(oparg); - } + STACK_SHRINK(2); + JUMPBY(2); + DISPATCH(); + } + + TARGET(COMPARE_AND_BRANCH_STR) { + PyObject *right = PEEK(1); + PyObject *left = PEEK(2); + assert(cframe.use_tracing == 0); + DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_AND_BRANCH); + DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_AND_BRANCH); + STAT_INC(COMPARE_AND_BRANCH, hit); + int res = _PyUnicode_Equal(left, right); + assert((oparg >>4) == Py_EQ || (oparg >>4) == Py_NE); + _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc); + _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc); + assert(res == 0 || res == 1); + assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS); + assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS); + if ((res + COMPARISON_NOT_EQUALS) & oparg) { + int offset = _Py_OPARG(next_instr[1]); + JUMPBY(offset); } STACK_SHRINK(2); + JUMPBY(2); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 4c8b9dd..d293ada 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -2,7 +2,7 @@ // from Python/bytecodes.c // Do not edit! enum Direction { DIR_NONE, DIR_READ, DIR_WRITE }; -enum InstructionFormat { INSTR_FMT_IB, INSTR_FMT_IBC, INSTR_FMT_IBC000, INSTR_FMT_IBCIB, INSTR_FMT_IBIB, INSTR_FMT_IX, INSTR_FMT_IXC, INSTR_FMT_IXC000 }; +enum InstructionFormat { INSTR_FMT_IB, INSTR_FMT_IBC, INSTR_FMT_IBC0, INSTR_FMT_IBC000, INSTR_FMT_IBIB, INSTR_FMT_IX, INSTR_FMT_IXC, INSTR_FMT_IXC000 }; static const struct { short n_popped; short n_pushed; @@ -113,9 +113,10 @@ static const struct { [STORE_ATTR_WITH_HINT] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC000 }, [STORE_ATTR_SLOT] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 }, [COMPARE_OP] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC }, - [COMPARE_OP_FLOAT_JUMP] = { 3, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBCIB }, - [COMPARE_OP_INT_JUMP] = { 3, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBCIB }, - [COMPARE_OP_STR_JUMP] = { 3, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBCIB }, + [COMPARE_AND_BRANCH] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0 }, + [COMPARE_AND_BRANCH_FLOAT] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0 }, + [COMPARE_AND_BRANCH_INT] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0 }, + [COMPARE_AND_BRANCH_STR] = { 2, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0 }, [IS_OP] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [CONTAINS_OP] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [CHECK_EG_MATCH] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 83b3af7..f1c3f3e 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -47,7 +47,7 @@ static void *opcode_targets[256] = { &&TARGET_CALL_NO_KW_STR_1, &&TARGET_CALL_NO_KW_TUPLE_1, &&TARGET_CALL_NO_KW_TYPE_1, - &&TARGET_COMPARE_OP_FLOAT_JUMP, + &&TARGET_COMPARE_AND_BRANCH_FLOAT, &&TARGET_WITH_EXCEPT_START, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, @@ -55,8 +55,8 @@ static void *opcode_targets[256] = { &&TARGET_BEFORE_WITH, &&TARGET_END_ASYNC_FOR, &&TARGET_CLEANUP_THROW, - &&TARGET_COMPARE_OP_INT_JUMP, - &&TARGET_COMPARE_OP_STR_JUMP, + &&TARGET_COMPARE_AND_BRANCH_INT, + &&TARGET_COMPARE_AND_BRANCH_STR, &&TARGET_FOR_ITER_LIST, &&TARGET_FOR_ITER_TUPLE, &&TARGET_STORE_SUBSCR, @@ -140,9 +140,9 @@ static void *opcode_targets[256] = { &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, &&TARGET_JUMP_BACKWARD, - &&TARGET_STORE_FAST__STORE_FAST, + &&TARGET_COMPARE_AND_BRANCH, &&TARGET_CALL_FUNCTION_EX, - &&TARGET_STORE_SUBSCR_DICT, + &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_EXTENDED_ARG, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, @@ -152,15 +152,15 @@ static void *opcode_targets[256] = { &&TARGET_YIELD_VALUE, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, + &&TARGET_STORE_SUBSCR_DICT, &&TARGET_STORE_SUBSCR_LIST_INT, - &&TARGET_UNPACK_SEQUENCE_LIST, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, + &&TARGET_UNPACK_SEQUENCE_LIST, &&TARGET_UNPACK_SEQUENCE_TUPLE, &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, diff --git a/Python/specialize.c b/Python/specialize.c index 38bb151..500fd71 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -126,6 +126,7 @@ print_spec_stats(FILE *out, OpcodeStats *stats) /* Mark some opcodes as specializable for stats, * even though we don't specialize them yet. */ fprintf(out, "opcode[%d].specializable : 1\n", BINARY_SLICE); + fprintf(out, "opcode[%d].specializable : 1\n", COMPARE_OP); fprintf(out, "opcode[%d].specializable : 1\n", STORE_SLICE); for (int i = 0; i < 256; i++) { if (_PyOpcode_Caches[i]) { @@ -311,6 +312,7 @@ _PyCode_Quicken(PyCodeObject *code) if (opcode == POP_JUMP_IF_FALSE) { mask = mask ^ 0xf; } + instructions[i - 1 - INLINE_CACHE_ENTRIES_COMPARE_OP].opcode = COMPARE_AND_BRANCH; instructions[i - 1 - INLINE_CACHE_ENTRIES_COMPARE_OP].oparg = (oparg & 0xf0) | mask; break; } @@ -431,19 +433,19 @@ _PyCode_Quicken(PyCodeObject *code) #define SPEC_FAIL_CALL_OPERATOR_WRAPPER 29 /* COMPARE_OP */ -#define SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES 12 -#define SPEC_FAIL_COMPARE_OP_STRING 13 -#define SPEC_FAIL_COMPARE_OP_NOT_FOLLOWED_BY_COND_JUMP 14 -#define SPEC_FAIL_COMPARE_OP_BIG_INT 15 -#define SPEC_FAIL_COMPARE_OP_BYTES 16 -#define SPEC_FAIL_COMPARE_OP_TUPLE 17 -#define SPEC_FAIL_COMPARE_OP_LIST 18 -#define SPEC_FAIL_COMPARE_OP_SET 19 -#define SPEC_FAIL_COMPARE_OP_BOOL 20 -#define SPEC_FAIL_COMPARE_OP_BASEOBJECT 21 -#define SPEC_FAIL_COMPARE_OP_FLOAT_LONG 22 -#define SPEC_FAIL_COMPARE_OP_LONG_FLOAT 23 -#define SPEC_FAIL_COMPARE_OP_EXTENDED_ARG 24 +#define SPEC_FAIL_COMPARE_DIFFERENT_TYPES 12 +#define SPEC_FAIL_COMPARE_STRING 13 +#define SPEC_FAIL_COMPARE_NOT_FOLLOWED_BY_COND_JUMP 14 +#define SPEC_FAIL_COMPARE_BIG_INT 15 +#define SPEC_FAIL_COMPARE_BYTES 16 +#define SPEC_FAIL_COMPARE_TUPLE 17 +#define SPEC_FAIL_COMPARE_LIST 18 +#define SPEC_FAIL_COMPARE_SET 19 +#define SPEC_FAIL_COMPARE_BOOL 20 +#define SPEC_FAIL_COMPARE_BASEOBJECT 21 +#define SPEC_FAIL_COMPARE_FLOAT_LONG 22 +#define SPEC_FAIL_COMPARE_LONG_FLOAT 23 +#define SPEC_FAIL_COMPARE_EXTENDED_ARG 24 /* FOR_ITER */ #define SPEC_FAIL_FOR_ITER_GENERATOR 10 @@ -1968,87 +1970,82 @@ compare_op_fail_kind(PyObject *lhs, PyObject *rhs) { if (Py_TYPE(lhs) != Py_TYPE(rhs)) { if (PyFloat_CheckExact(lhs) && PyLong_CheckExact(rhs)) { - return SPEC_FAIL_COMPARE_OP_FLOAT_LONG; + return SPEC_FAIL_COMPARE_FLOAT_LONG; } if (PyLong_CheckExact(lhs) && PyFloat_CheckExact(rhs)) { - return SPEC_FAIL_COMPARE_OP_LONG_FLOAT; + return SPEC_FAIL_COMPARE_LONG_FLOAT; } - return SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES; + return SPEC_FAIL_COMPARE_DIFFERENT_TYPES; } if (PyBytes_CheckExact(lhs)) { - return SPEC_FAIL_COMPARE_OP_BYTES; + return SPEC_FAIL_COMPARE_BYTES; } if (PyTuple_CheckExact(lhs)) { - return SPEC_FAIL_COMPARE_OP_TUPLE; + return SPEC_FAIL_COMPARE_TUPLE; } if (PyList_CheckExact(lhs)) { - return SPEC_FAIL_COMPARE_OP_LIST; + return SPEC_FAIL_COMPARE_LIST; } if (PySet_CheckExact(lhs) || PyFrozenSet_CheckExact(lhs)) { - return SPEC_FAIL_COMPARE_OP_SET; + return SPEC_FAIL_COMPARE_SET; } if (PyBool_Check(lhs)) { - return SPEC_FAIL_COMPARE_OP_BOOL; + return SPEC_FAIL_COMPARE_BOOL; } if (Py_TYPE(lhs)->tp_richcompare == PyBaseObject_Type.tp_richcompare) { - return SPEC_FAIL_COMPARE_OP_BASEOBJECT; + return SPEC_FAIL_COMPARE_BASEOBJECT; } return SPEC_FAIL_OTHER; } #endif void -_Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, +_Py_Specialize_CompareAndBranch(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, int oparg) { - assert(_PyOpcode_Caches[COMPARE_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP); + assert(_PyOpcode_Caches[COMPARE_AND_BRANCH] == INLINE_CACHE_ENTRIES_COMPARE_OP); _PyCompareOpCache *cache = (_PyCompareOpCache *)(instr + 1); +#ifndef NDEBUG int next_opcode = _Py_OPCODE(instr[INLINE_CACHE_ENTRIES_COMPARE_OP + 1]); - if (next_opcode != POP_JUMP_IF_FALSE && next_opcode != POP_JUMP_IF_TRUE) { - if (next_opcode == EXTENDED_ARG) { - SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_EXTENDED_ARG); - goto failure; - } - SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_NOT_FOLLOWED_BY_COND_JUMP); - goto failure; - } + assert(next_opcode == POP_JUMP_IF_FALSE || next_opcode == POP_JUMP_IF_TRUE); +#endif if (Py_TYPE(lhs) != Py_TYPE(rhs)) { - SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs)); + SPECIALIZATION_FAIL(COMPARE_AND_BRANCH, compare_op_fail_kind(lhs, rhs)); goto failure; } if (PyFloat_CheckExact(lhs)) { - _py_set_opcode(instr, COMPARE_OP_FLOAT_JUMP); + _py_set_opcode(instr, COMPARE_AND_BRANCH_FLOAT); goto success; } if (PyLong_CheckExact(lhs)) { if (Py_ABS(Py_SIZE(lhs)) <= 1 && Py_ABS(Py_SIZE(rhs)) <= 1) { - _py_set_opcode(instr, COMPARE_OP_INT_JUMP); + _py_set_opcode(instr, COMPARE_AND_BRANCH_INT); goto success; } else { - SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_BIG_INT); + SPECIALIZATION_FAIL(COMPARE_AND_BRANCH, SPEC_FAIL_COMPARE_BIG_INT); goto failure; } } if (PyUnicode_CheckExact(lhs)) { int cmp = oparg >> 4; if (cmp != Py_EQ && cmp != Py_NE) { - SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_STRING); + SPECIALIZATION_FAIL(COMPARE_AND_BRANCH, SPEC_FAIL_COMPARE_STRING); goto failure; } else { - _py_set_opcode(instr, COMPARE_OP_STR_JUMP); + _py_set_opcode(instr, COMPARE_AND_BRANCH_STR); goto success; } } - SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs)); + SPECIALIZATION_FAIL(COMPARE_AND_BRANCH, compare_op_fail_kind(lhs, rhs)); failure: - STAT_INC(COMPARE_OP, failure); - _py_set_opcode(instr, COMPARE_OP); + STAT_INC(COMPARE_AND_BRANCH, failure); + _py_set_opcode(instr, COMPARE_AND_BRANCH); cache->counter = adaptive_counter_backoff(cache->counter); return; success: - STAT_INC(COMPARE_OP, success); + STAT_INC(COMPARE_AND_BRANCH, success); cache->counter = adaptive_counter_cooldown(); } |