mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
GH-111848: Convert remaining jumps to deopts into tier 2 code. (GH-112045)
This commit is contained in:
parent
b11c443bb2
commit
a519b87958
7 changed files with 194 additions and 139 deletions
142
Include/internal/pycore_opcode_metadata.h
generated
142
Include/internal/pycore_opcode_metadata.h
generated
|
@ -76,46 +76,50 @@
|
||||||
#define _STORE_ATTR_SLOT 348
|
#define _STORE_ATTR_SLOT 348
|
||||||
#define _SPECIALIZE_COMPARE_OP 349
|
#define _SPECIALIZE_COMPARE_OP 349
|
||||||
#define _COMPARE_OP 350
|
#define _COMPARE_OP 350
|
||||||
#define _IS_NONE 351
|
#define _POP_JUMP_IF_FALSE 351
|
||||||
#define _SPECIALIZE_FOR_ITER 352
|
#define _POP_JUMP_IF_TRUE 352
|
||||||
#define _FOR_ITER 353
|
#define _IS_NONE 353
|
||||||
#define _ITER_CHECK_LIST 354
|
#define _SPECIALIZE_FOR_ITER 354
|
||||||
#define _ITER_JUMP_LIST 355
|
#define _FOR_ITER 355
|
||||||
#define _GUARD_NOT_EXHAUSTED_LIST 356
|
#define _ITER_CHECK_LIST 356
|
||||||
#define _ITER_NEXT_LIST 357
|
#define _ITER_JUMP_LIST 357
|
||||||
#define _ITER_CHECK_TUPLE 358
|
#define _GUARD_NOT_EXHAUSTED_LIST 358
|
||||||
#define _ITER_JUMP_TUPLE 359
|
#define _ITER_NEXT_LIST 359
|
||||||
#define _GUARD_NOT_EXHAUSTED_TUPLE 360
|
#define _ITER_CHECK_TUPLE 360
|
||||||
#define _ITER_NEXT_TUPLE 361
|
#define _ITER_JUMP_TUPLE 361
|
||||||
#define _ITER_CHECK_RANGE 362
|
#define _GUARD_NOT_EXHAUSTED_TUPLE 362
|
||||||
#define _ITER_JUMP_RANGE 363
|
#define _ITER_NEXT_TUPLE 363
|
||||||
#define _GUARD_NOT_EXHAUSTED_RANGE 364
|
#define _ITER_CHECK_RANGE 364
|
||||||
#define _ITER_NEXT_RANGE 365
|
#define _ITER_JUMP_RANGE 365
|
||||||
#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 366
|
#define _GUARD_NOT_EXHAUSTED_RANGE 366
|
||||||
#define _GUARD_KEYS_VERSION 367
|
#define _ITER_NEXT_RANGE 367
|
||||||
#define _LOAD_ATTR_METHOD_WITH_VALUES 368
|
#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 368
|
||||||
#define _LOAD_ATTR_METHOD_NO_DICT 369
|
#define _GUARD_KEYS_VERSION 369
|
||||||
#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 370
|
#define _LOAD_ATTR_METHOD_WITH_VALUES 370
|
||||||
#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 371
|
#define _LOAD_ATTR_METHOD_NO_DICT 371
|
||||||
#define _CHECK_ATTR_METHOD_LAZY_DICT 372
|
#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 372
|
||||||
#define _LOAD_ATTR_METHOD_LAZY_DICT 373
|
#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 373
|
||||||
#define _SPECIALIZE_CALL 374
|
#define _CHECK_ATTR_METHOD_LAZY_DICT 374
|
||||||
#define _CALL 375
|
#define _LOAD_ATTR_METHOD_LAZY_DICT 375
|
||||||
#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 376
|
#define _SPECIALIZE_CALL 376
|
||||||
#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 377
|
#define _CALL 377
|
||||||
#define _CHECK_PEP_523 378
|
#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 378
|
||||||
#define _CHECK_FUNCTION_EXACT_ARGS 379
|
#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 379
|
||||||
#define _CHECK_STACK_SPACE 380
|
#define _CHECK_PEP_523 380
|
||||||
#define _INIT_CALL_PY_EXACT_ARGS 381
|
#define _CHECK_FUNCTION_EXACT_ARGS 381
|
||||||
#define _PUSH_FRAME 382
|
#define _CHECK_STACK_SPACE 382
|
||||||
#define _SPECIALIZE_BINARY_OP 383
|
#define _INIT_CALL_PY_EXACT_ARGS 383
|
||||||
#define _BINARY_OP 384
|
#define _PUSH_FRAME 384
|
||||||
#define _POP_JUMP_IF_FALSE 385
|
#define _SPECIALIZE_BINARY_OP 385
|
||||||
#define _POP_JUMP_IF_TRUE 386
|
#define _BINARY_OP 386
|
||||||
#define _JUMP_TO_TOP 387
|
#define _GUARD_IS_TRUE_POP 387
|
||||||
#define _SAVE_RETURN_OFFSET 388
|
#define _GUARD_IS_FALSE_POP 388
|
||||||
#define _INSERT 389
|
#define _GUARD_IS_NONE_POP 389
|
||||||
#define _CHECK_VALIDITY 390
|
#define _GUARD_IS_NOT_NONE_POP 390
|
||||||
|
#define _JUMP_TO_TOP 391
|
||||||
|
#define _SAVE_RETURN_OFFSET 392
|
||||||
|
#define _INSERT 393
|
||||||
|
#define _CHECK_VALIDITY 394
|
||||||
|
|
||||||
extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump);
|
extern int _PyOpcode_num_popped(int opcode, int oparg, bool jump);
|
||||||
#ifdef NEED_OPCODE_METADATA
|
#ifdef NEED_OPCODE_METADATA
|
||||||
|
@ -505,11 +509,15 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
|
||||||
return 0;
|
return 0;
|
||||||
case ENTER_EXECUTOR:
|
case ENTER_EXECUTOR:
|
||||||
return 0;
|
return 0;
|
||||||
case POP_JUMP_IF_FALSE:
|
case _POP_JUMP_IF_FALSE:
|
||||||
|
return 1;
|
||||||
|
case _POP_JUMP_IF_TRUE:
|
||||||
|
return 1;
|
||||||
|
case _IS_NONE:
|
||||||
return 1;
|
return 1;
|
||||||
case POP_JUMP_IF_TRUE:
|
case POP_JUMP_IF_TRUE:
|
||||||
return 1;
|
return 1;
|
||||||
case _IS_NONE:
|
case POP_JUMP_IF_FALSE:
|
||||||
return 1;
|
return 1;
|
||||||
case POP_JUMP_IF_NONE:
|
case POP_JUMP_IF_NONE:
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -725,9 +733,13 @@ int _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
|
||||||
return 0;
|
return 0;
|
||||||
case RESERVED:
|
case RESERVED:
|
||||||
return 0;
|
return 0;
|
||||||
case _POP_JUMP_IF_FALSE:
|
case _GUARD_IS_TRUE_POP:
|
||||||
return 1;
|
return 1;
|
||||||
case _POP_JUMP_IF_TRUE:
|
case _GUARD_IS_FALSE_POP:
|
||||||
|
return 1;
|
||||||
|
case _GUARD_IS_NONE_POP:
|
||||||
|
return 1;
|
||||||
|
case _GUARD_IS_NOT_NONE_POP:
|
||||||
return 1;
|
return 1;
|
||||||
case _JUMP_TO_TOP:
|
case _JUMP_TO_TOP:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1135,12 +1147,16 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
|
||||||
return 0;
|
return 0;
|
||||||
case ENTER_EXECUTOR:
|
case ENTER_EXECUTOR:
|
||||||
return 0;
|
return 0;
|
||||||
case POP_JUMP_IF_FALSE:
|
case _POP_JUMP_IF_FALSE:
|
||||||
return 0;
|
return 0;
|
||||||
case POP_JUMP_IF_TRUE:
|
case _POP_JUMP_IF_TRUE:
|
||||||
return 0;
|
return 0;
|
||||||
case _IS_NONE:
|
case _IS_NONE:
|
||||||
return 1;
|
return 1;
|
||||||
|
case POP_JUMP_IF_TRUE:
|
||||||
|
return 0;
|
||||||
|
case POP_JUMP_IF_FALSE:
|
||||||
|
return 0;
|
||||||
case POP_JUMP_IF_NONE:
|
case POP_JUMP_IF_NONE:
|
||||||
return 0;
|
return 0;
|
||||||
case POP_JUMP_IF_NOT_NONE:
|
case POP_JUMP_IF_NOT_NONE:
|
||||||
|
@ -1355,9 +1371,13 @@ int _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
|
||||||
return 0;
|
return 0;
|
||||||
case RESERVED:
|
case RESERVED:
|
||||||
return 0;
|
return 0;
|
||||||
case _POP_JUMP_IF_FALSE:
|
case _GUARD_IS_TRUE_POP:
|
||||||
return 0;
|
return 0;
|
||||||
case _POP_JUMP_IF_TRUE:
|
case _GUARD_IS_FALSE_POP:
|
||||||
|
return 0;
|
||||||
|
case _GUARD_IS_NONE_POP:
|
||||||
|
return 0;
|
||||||
|
case _GUARD_IS_NOT_NONE_POP:
|
||||||
return 0;
|
return 0;
|
||||||
case _JUMP_TO_TOP:
|
case _JUMP_TO_TOP:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1639,9 +1659,11 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
|
||||||
[JUMP] = { true, 0, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
[JUMP] = { true, 0, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
||||||
[JUMP_NO_INTERRUPT] = { true, 0, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
[JUMP_NO_INTERRUPT] = { true, 0, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
||||||
[ENTER_EXECUTOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
|
[ENTER_EXECUTOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
|
[_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
|
[_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[_IS_NONE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
|
[_IS_NONE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
|
||||||
|
[POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
|
||||||
|
[POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
|
[POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
|
[POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[JUMP_BACKWARD_NO_INTERRUPT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
[JUMP_BACKWARD_NO_INTERRUPT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
||||||
|
@ -1749,8 +1771,10 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
|
||||||
[EXTENDED_ARG] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
[EXTENDED_ARG] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
||||||
[CACHE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
|
[CACHE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
|
||||||
[RESERVED] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
|
[RESERVED] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
|
||||||
[_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ESCAPES_FLAG },
|
[_GUARD_IS_TRUE_POP] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ESCAPES_FLAG },
|
[_GUARD_IS_FALSE_POP] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
|
||||||
|
[_GUARD_IS_NONE_POP] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
|
||||||
|
[_GUARD_IS_NOT_NONE_POP] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[_JUMP_TO_TOP] = { true, INSTR_FMT_IX, HAS_EVAL_BREAK_FLAG },
|
[_JUMP_TO_TOP] = { true, INSTR_FMT_IX, HAS_EVAL_BREAK_FLAG },
|
||||||
[_SET_IP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ESCAPES_FLAG },
|
[_SET_IP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ESCAPES_FLAG },
|
||||||
[_SAVE_RETURN_OFFSET] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
[_SAVE_RETURN_OFFSET] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
||||||
|
@ -1871,6 +1895,10 @@ const struct opcode_macro_expansion _PyOpcode_macro_expansion[OPCODE_MACRO_EXPAN
|
||||||
[CONTAINS_OP] = { .nuops = 1, .uops = { { CONTAINS_OP, 0, 0 } } },
|
[CONTAINS_OP] = { .nuops = 1, .uops = { { CONTAINS_OP, 0, 0 } } },
|
||||||
[CHECK_EG_MATCH] = { .nuops = 1, .uops = { { CHECK_EG_MATCH, 0, 0 } } },
|
[CHECK_EG_MATCH] = { .nuops = 1, .uops = { { CHECK_EG_MATCH, 0, 0 } } },
|
||||||
[CHECK_EXC_MATCH] = { .nuops = 1, .uops = { { CHECK_EXC_MATCH, 0, 0 } } },
|
[CHECK_EXC_MATCH] = { .nuops = 1, .uops = { { CHECK_EXC_MATCH, 0, 0 } } },
|
||||||
|
[POP_JUMP_IF_TRUE] = { .nuops = 1, .uops = { { _POP_JUMP_IF_TRUE, 0, 0 } } },
|
||||||
|
[POP_JUMP_IF_FALSE] = { .nuops = 1, .uops = { { _POP_JUMP_IF_FALSE, 0, 0 } } },
|
||||||
|
[POP_JUMP_IF_NONE] = { .nuops = 2, .uops = { { _IS_NONE, 0, 0 }, { _POP_JUMP_IF_TRUE, 0, 0 } } },
|
||||||
|
[POP_JUMP_IF_NOT_NONE] = { .nuops = 2, .uops = { { _IS_NONE, 0, 0 }, { _POP_JUMP_IF_FALSE, 0, 0 } } },
|
||||||
[GET_LEN] = { .nuops = 1, .uops = { { GET_LEN, 0, 0 } } },
|
[GET_LEN] = { .nuops = 1, .uops = { { GET_LEN, 0, 0 } } },
|
||||||
[MATCH_CLASS] = { .nuops = 1, .uops = { { MATCH_CLASS, 0, 0 } } },
|
[MATCH_CLASS] = { .nuops = 1, .uops = { { MATCH_CLASS, 0, 0 } } },
|
||||||
[MATCH_MAPPING] = { .nuops = 1, .uops = { { MATCH_MAPPING, 0, 0 } } },
|
[MATCH_MAPPING] = { .nuops = 1, .uops = { { MATCH_MAPPING, 0, 0 } } },
|
||||||
|
@ -1972,6 +2000,8 @@ const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] = {
|
||||||
[_STORE_ATTR_SLOT] = "_STORE_ATTR_SLOT",
|
[_STORE_ATTR_SLOT] = "_STORE_ATTR_SLOT",
|
||||||
[_SPECIALIZE_COMPARE_OP] = "_SPECIALIZE_COMPARE_OP",
|
[_SPECIALIZE_COMPARE_OP] = "_SPECIALIZE_COMPARE_OP",
|
||||||
[_COMPARE_OP] = "_COMPARE_OP",
|
[_COMPARE_OP] = "_COMPARE_OP",
|
||||||
|
[_POP_JUMP_IF_FALSE] = "_POP_JUMP_IF_FALSE",
|
||||||
|
[_POP_JUMP_IF_TRUE] = "_POP_JUMP_IF_TRUE",
|
||||||
[_IS_NONE] = "_IS_NONE",
|
[_IS_NONE] = "_IS_NONE",
|
||||||
[_SPECIALIZE_FOR_ITER] = "_SPECIALIZE_FOR_ITER",
|
[_SPECIALIZE_FOR_ITER] = "_SPECIALIZE_FOR_ITER",
|
||||||
[_FOR_ITER] = "_FOR_ITER",
|
[_FOR_ITER] = "_FOR_ITER",
|
||||||
|
@ -2006,8 +2036,10 @@ const char * const _PyOpcode_uop_name[OPCODE_UOP_NAME_SIZE] = {
|
||||||
[_PUSH_FRAME] = "_PUSH_FRAME",
|
[_PUSH_FRAME] = "_PUSH_FRAME",
|
||||||
[_SPECIALIZE_BINARY_OP] = "_SPECIALIZE_BINARY_OP",
|
[_SPECIALIZE_BINARY_OP] = "_SPECIALIZE_BINARY_OP",
|
||||||
[_BINARY_OP] = "_BINARY_OP",
|
[_BINARY_OP] = "_BINARY_OP",
|
||||||
[_POP_JUMP_IF_FALSE] = "_POP_JUMP_IF_FALSE",
|
[_GUARD_IS_TRUE_POP] = "_GUARD_IS_TRUE_POP",
|
||||||
[_POP_JUMP_IF_TRUE] = "_POP_JUMP_IF_TRUE",
|
[_GUARD_IS_FALSE_POP] = "_GUARD_IS_FALSE_POP",
|
||||||
|
[_GUARD_IS_NONE_POP] = "_GUARD_IS_NONE_POP",
|
||||||
|
[_GUARD_IS_NOT_NONE_POP] = "_GUARD_IS_NOT_NONE_POP",
|
||||||
[_JUMP_TO_TOP] = "_JUMP_TO_TOP",
|
[_JUMP_TO_TOP] = "_JUMP_TO_TOP",
|
||||||
[_SAVE_RETURN_OFFSET] = "_SAVE_RETURN_OFFSET",
|
[_SAVE_RETURN_OFFSET] = "_SAVE_RETURN_OFFSET",
|
||||||
[_INSERT] = "_INSERT",
|
[_INSERT] = "_INSERT",
|
||||||
|
@ -2256,8 +2288,8 @@ const uint8_t _PyOpcode_Caches[256] = {
|
||||||
[LOAD_ATTR] = 9,
|
[LOAD_ATTR] = 9,
|
||||||
[COMPARE_OP] = 1,
|
[COMPARE_OP] = 1,
|
||||||
[JUMP_BACKWARD] = 1,
|
[JUMP_BACKWARD] = 1,
|
||||||
[POP_JUMP_IF_FALSE] = 1,
|
|
||||||
[POP_JUMP_IF_TRUE] = 1,
|
[POP_JUMP_IF_TRUE] = 1,
|
||||||
|
[POP_JUMP_IF_FALSE] = 1,
|
||||||
[POP_JUMP_IF_NONE] = 1,
|
[POP_JUMP_IF_NONE] = 1,
|
||||||
[POP_JUMP_IF_NOT_NONE] = 1,
|
[POP_JUMP_IF_NOT_NONE] = 1,
|
||||||
[FOR_ITER] = 1,
|
[FOR_ITER] = 1,
|
||||||
|
|
|
@ -2610,7 +2610,7 @@ class TestUops(unittest.TestCase):
|
||||||
ex = get_first_executor(testfunc)
|
ex = get_first_executor(testfunc)
|
||||||
self.assertIsNotNone(ex)
|
self.assertIsNotNone(ex)
|
||||||
uops = {opname for opname, _, _ in ex}
|
uops = {opname for opname, _, _ in ex}
|
||||||
self.assertIn("_POP_JUMP_IF_FALSE", uops)
|
self.assertIn("_GUARD_IS_TRUE_POP", uops)
|
||||||
|
|
||||||
def test_pop_jump_if_none(self):
|
def test_pop_jump_if_none(self):
|
||||||
def testfunc(a):
|
def testfunc(a):
|
||||||
|
@ -2625,7 +2625,7 @@ class TestUops(unittest.TestCase):
|
||||||
ex = get_first_executor(testfunc)
|
ex = get_first_executor(testfunc)
|
||||||
self.assertIsNotNone(ex)
|
self.assertIsNotNone(ex)
|
||||||
uops = {opname for opname, _, _ in ex}
|
uops = {opname for opname, _, _ in ex}
|
||||||
self.assertIn("_POP_JUMP_IF_TRUE", uops)
|
self.assertIn("_GUARD_IS_NOT_NONE_POP", uops)
|
||||||
|
|
||||||
def test_pop_jump_if_not_none(self):
|
def test_pop_jump_if_not_none(self):
|
||||||
def testfunc(a):
|
def testfunc(a):
|
||||||
|
@ -2641,7 +2641,7 @@ class TestUops(unittest.TestCase):
|
||||||
ex = get_first_executor(testfunc)
|
ex = get_first_executor(testfunc)
|
||||||
self.assertIsNotNone(ex)
|
self.assertIsNotNone(ex)
|
||||||
uops = {opname for opname, _, _ in ex}
|
uops = {opname for opname, _, _ in ex}
|
||||||
self.assertIn("_POP_JUMP_IF_FALSE", uops)
|
self.assertIn("_GUARD_IS_NONE_POP", uops)
|
||||||
|
|
||||||
def test_pop_jump_if_true(self):
|
def test_pop_jump_if_true(self):
|
||||||
def testfunc(n):
|
def testfunc(n):
|
||||||
|
@ -2656,7 +2656,7 @@ class TestUops(unittest.TestCase):
|
||||||
ex = get_first_executor(testfunc)
|
ex = get_first_executor(testfunc)
|
||||||
self.assertIsNotNone(ex)
|
self.assertIsNotNone(ex)
|
||||||
uops = {opname for opname, _, _ in ex}
|
uops = {opname for opname, _, _ in ex}
|
||||||
self.assertIn("_POP_JUMP_IF_TRUE", uops)
|
self.assertIn("_GUARD_IS_FALSE_POP", uops)
|
||||||
|
|
||||||
def test_jump_backward(self):
|
def test_jump_backward(self):
|
||||||
def testfunc(n):
|
def testfunc(n):
|
||||||
|
@ -2806,7 +2806,7 @@ class TestUops(unittest.TestCase):
|
||||||
ex = get_first_executor(testfunc)
|
ex = get_first_executor(testfunc)
|
||||||
self.assertIsNotNone(ex)
|
self.assertIsNotNone(ex)
|
||||||
uops = {opname for opname, _, _ in ex}
|
uops = {opname for opname, _, _ in ex}
|
||||||
self.assertIn("_POP_JUMP_IF_TRUE", uops)
|
self.assertIn("_GUARD_IS_FALSE_POP", uops)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
14
Python/abstract_interp_cases.c.h
generated
14
Python/abstract_interp_cases.c.h
generated
|
@ -914,12 +914,22 @@
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _POP_JUMP_IF_FALSE: {
|
case _GUARD_IS_TRUE_POP: {
|
||||||
STACK_SHRINK(1);
|
STACK_SHRINK(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _POP_JUMP_IF_TRUE: {
|
case _GUARD_IS_FALSE_POP: {
|
||||||
|
STACK_SHRINK(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _GUARD_IS_NONE_POP: {
|
||||||
|
STACK_SHRINK(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _GUARD_IS_NOT_NONE_POP: {
|
||||||
STACK_SHRINK(1);
|
STACK_SHRINK(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2368,7 +2368,7 @@ dummy_func(
|
||||||
goto enter_tier_one;
|
goto enter_tier_one;
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(POP_JUMP_IF_FALSE, (unused/1, cond -- )) {
|
replaced op(_POP_JUMP_IF_FALSE, (unused/1, cond -- )) {
|
||||||
assert(PyBool_Check(cond));
|
assert(PyBool_Check(cond));
|
||||||
int flag = Py_IsFalse(cond);
|
int flag = Py_IsFalse(cond);
|
||||||
#if ENABLE_SPECIALIZATION
|
#if ENABLE_SPECIALIZATION
|
||||||
|
@ -2377,7 +2377,7 @@ dummy_func(
|
||||||
JUMPBY(oparg * flag);
|
JUMPBY(oparg * flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
inst(POP_JUMP_IF_TRUE, (unused/1, cond -- )) {
|
replaced op(_POP_JUMP_IF_TRUE, (unused/1, cond -- )) {
|
||||||
assert(PyBool_Check(cond));
|
assert(PyBool_Check(cond));
|
||||||
int flag = Py_IsTrue(cond);
|
int flag = Py_IsTrue(cond);
|
||||||
#if ENABLE_SPECIALIZATION
|
#if ENABLE_SPECIALIZATION
|
||||||
|
@ -2396,9 +2396,13 @@ dummy_func(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro(POP_JUMP_IF_NONE) = _IS_NONE + POP_JUMP_IF_TRUE;
|
macro(POP_JUMP_IF_TRUE) = _POP_JUMP_IF_TRUE;
|
||||||
|
|
||||||
macro(POP_JUMP_IF_NOT_NONE) = _IS_NONE + POP_JUMP_IF_FALSE;
|
macro(POP_JUMP_IF_FALSE) = _POP_JUMP_IF_FALSE;
|
||||||
|
|
||||||
|
macro(POP_JUMP_IF_NONE) = _IS_NONE + _POP_JUMP_IF_TRUE;
|
||||||
|
|
||||||
|
macro(POP_JUMP_IF_NOT_NONE) = _IS_NONE + _POP_JUMP_IF_FALSE;
|
||||||
|
|
||||||
inst(JUMP_BACKWARD_NO_INTERRUPT, (--)) {
|
inst(JUMP_BACKWARD_NO_INTERRUPT, (--)) {
|
||||||
/* This bytecode is used in the `yield from` or `await` loop.
|
/* This bytecode is used in the `yield from` or `await` loop.
|
||||||
|
@ -3963,16 +3967,23 @@ dummy_func(
|
||||||
|
|
||||||
///////// Tier-2 only opcodes /////////
|
///////// Tier-2 only opcodes /////////
|
||||||
|
|
||||||
op(_POP_JUMP_IF_FALSE, (flag -- )) {
|
op (_GUARD_IS_TRUE_POP, (flag -- )) {
|
||||||
if (Py_IsFalse(flag)) {
|
DEOPT_IF(Py_IsFalse(flag));
|
||||||
next_uop = current_executor->trace + oparg;
|
assert(Py_IsTrue(flag));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_POP_JUMP_IF_TRUE, (flag -- )) {
|
op (_GUARD_IS_FALSE_POP, (flag -- )) {
|
||||||
if (Py_IsTrue(flag)) {
|
DEOPT_IF(Py_IsTrue(flag));
|
||||||
next_uop = current_executor->trace + oparg;
|
assert(Py_IsFalse(flag));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
op (_GUARD_IS_NONE_POP, (val -- )) {
|
||||||
|
DEOPT_IF(!Py_IsNone(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
op (_GUARD_IS_NOT_NONE_POP, (val -- )) {
|
||||||
|
DEOPT_IF(Py_IsNone(val));
|
||||||
|
Py_DECREF(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_JUMP_TO_TOP, (--)) {
|
op(_JUMP_TO_TOP, (--)) {
|
||||||
|
|
31
Python/executor_cases.c.h
generated
31
Python/executor_cases.c.h
generated
|
@ -3185,22 +3185,37 @@
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _POP_JUMP_IF_FALSE: {
|
case _GUARD_IS_TRUE_POP: {
|
||||||
PyObject *flag;
|
PyObject *flag;
|
||||||
flag = stack_pointer[-1];
|
flag = stack_pointer[-1];
|
||||||
if (Py_IsFalse(flag)) {
|
DEOPT_IF(Py_IsFalse(flag), _GUARD_IS_TRUE_POP);
|
||||||
next_uop = current_executor->trace + oparg;
|
assert(Py_IsTrue(flag));
|
||||||
}
|
|
||||||
STACK_SHRINK(1);
|
STACK_SHRINK(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _POP_JUMP_IF_TRUE: {
|
case _GUARD_IS_FALSE_POP: {
|
||||||
PyObject *flag;
|
PyObject *flag;
|
||||||
flag = stack_pointer[-1];
|
flag = stack_pointer[-1];
|
||||||
if (Py_IsTrue(flag)) {
|
DEOPT_IF(Py_IsTrue(flag), _GUARD_IS_FALSE_POP);
|
||||||
next_uop = current_executor->trace + oparg;
|
assert(Py_IsFalse(flag));
|
||||||
}
|
STACK_SHRINK(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _GUARD_IS_NONE_POP: {
|
||||||
|
PyObject *val;
|
||||||
|
val = stack_pointer[-1];
|
||||||
|
DEOPT_IF(!Py_IsNone(val), _GUARD_IS_NONE_POP);
|
||||||
|
STACK_SHRINK(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _GUARD_IS_NOT_NONE_POP: {
|
||||||
|
PyObject *val;
|
||||||
|
val = stack_pointer[-1];
|
||||||
|
DEOPT_IF(Py_IsNone(val), _GUARD_IS_NOT_NONE_POP);
|
||||||
|
Py_DECREF(val);
|
||||||
STACK_SHRINK(1);
|
STACK_SHRINK(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
36
Python/generated_cases.c.h
generated
36
Python/generated_cases.c.h
generated
|
@ -3435,22 +3435,6 @@
|
||||||
goto enter_tier_one;
|
goto enter_tier_one;
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(POP_JUMP_IF_FALSE) {
|
|
||||||
_Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr;
|
|
||||||
next_instr += 2;
|
|
||||||
INSTRUCTION_STATS(POP_JUMP_IF_FALSE);
|
|
||||||
PyObject *cond;
|
|
||||||
cond = stack_pointer[-1];
|
|
||||||
assert(PyBool_Check(cond));
|
|
||||||
int flag = Py_IsFalse(cond);
|
|
||||||
#if ENABLE_SPECIALIZATION
|
|
||||||
this_instr[1].cache = (this_instr[1].cache << 1) | flag;
|
|
||||||
#endif
|
|
||||||
JUMPBY(oparg * flag);
|
|
||||||
STACK_SHRINK(1);
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
|
|
||||||
TARGET(POP_JUMP_IF_TRUE) {
|
TARGET(POP_JUMP_IF_TRUE) {
|
||||||
_Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr;
|
_Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr;
|
||||||
next_instr += 2;
|
next_instr += 2;
|
||||||
|
@ -3467,6 +3451,22 @@
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TARGET(POP_JUMP_IF_FALSE) {
|
||||||
|
_Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr;
|
||||||
|
next_instr += 2;
|
||||||
|
INSTRUCTION_STATS(POP_JUMP_IF_FALSE);
|
||||||
|
PyObject *cond;
|
||||||
|
cond = stack_pointer[-1];
|
||||||
|
assert(PyBool_Check(cond));
|
||||||
|
int flag = Py_IsFalse(cond);
|
||||||
|
#if ENABLE_SPECIALIZATION
|
||||||
|
this_instr[1].cache = (this_instr[1].cache << 1) | flag;
|
||||||
|
#endif
|
||||||
|
JUMPBY(oparg * flag);
|
||||||
|
STACK_SHRINK(1);
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
|
||||||
TARGET(POP_JUMP_IF_NONE) {
|
TARGET(POP_JUMP_IF_NONE) {
|
||||||
_Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr;
|
_Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr;
|
||||||
next_instr += 2;
|
next_instr += 2;
|
||||||
|
@ -3485,7 +3485,7 @@
|
||||||
Py_DECREF(value);
|
Py_DECREF(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// POP_JUMP_IF_TRUE
|
// _POP_JUMP_IF_TRUE
|
||||||
cond = b;
|
cond = b;
|
||||||
{
|
{
|
||||||
assert(PyBool_Check(cond));
|
assert(PyBool_Check(cond));
|
||||||
|
@ -3517,7 +3517,7 @@
|
||||||
Py_DECREF(value);
|
Py_DECREF(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// POP_JUMP_IF_FALSE
|
// _POP_JUMP_IF_FALSE
|
||||||
cond = b;
|
cond = b;
|
||||||
{
|
{
|
||||||
assert(PyBool_Check(cond));
|
assert(PyBool_Check(cond));
|
||||||
|
|
|
@ -385,7 +385,7 @@ PyTypeObject _PyUOpExecutor_Type = {
|
||||||
.tp_methods = executor_methods,
|
.tp_methods = executor_methods,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* TO DO -- Generate this table */
|
/* TO DO -- Generate these tables */
|
||||||
static const uint16_t
|
static const uint16_t
|
||||||
_PyUop_Replacements[OPCODE_METADATA_SIZE] = {
|
_PyUop_Replacements[OPCODE_METADATA_SIZE] = {
|
||||||
[_ITER_JUMP_RANGE] = _GUARD_NOT_EXHAUSTED_RANGE,
|
[_ITER_JUMP_RANGE] = _GUARD_NOT_EXHAUSTED_RANGE,
|
||||||
|
@ -393,6 +393,18 @@ _PyUop_Replacements[OPCODE_METADATA_SIZE] = {
|
||||||
[_ITER_JUMP_TUPLE] = _GUARD_NOT_EXHAUSTED_TUPLE,
|
[_ITER_JUMP_TUPLE] = _GUARD_NOT_EXHAUSTED_TUPLE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const uint16_t
|
||||||
|
BRANCH_TO_GUARD[4][2] = {
|
||||||
|
[POP_JUMP_IF_FALSE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_TRUE_POP,
|
||||||
|
[POP_JUMP_IF_FALSE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_FALSE_POP,
|
||||||
|
[POP_JUMP_IF_TRUE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_FALSE_POP,
|
||||||
|
[POP_JUMP_IF_TRUE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_TRUE_POP,
|
||||||
|
[POP_JUMP_IF_NONE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_NOT_NONE_POP,
|
||||||
|
[POP_JUMP_IF_NONE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_NONE_POP,
|
||||||
|
[POP_JUMP_IF_NOT_NONE - POP_JUMP_IF_FALSE][0] = _GUARD_IS_NONE_POP,
|
||||||
|
[POP_JUMP_IF_NOT_NONE - POP_JUMP_IF_FALSE][1] = _GUARD_IS_NOT_NONE_POP,
|
||||||
|
};
|
||||||
|
|
||||||
#define TRACE_STACK_SIZE 5
|
#define TRACE_STACK_SIZE 5
|
||||||
|
|
||||||
/* Returns 1 on success,
|
/* Returns 1 on success,
|
||||||
|
@ -528,45 +540,23 @@ top: // Jump here after _PUSH_FRAME or likely branches
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
|
|
||||||
case POP_JUMP_IF_NONE:
|
case POP_JUMP_IF_NONE:
|
||||||
{
|
|
||||||
RESERVE(2, 2);
|
|
||||||
ADD_TO_TRACE(_IS_NONE, 0, 0);
|
|
||||||
opcode = POP_JUMP_IF_TRUE;
|
|
||||||
goto pop_jump_if_bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
case POP_JUMP_IF_NOT_NONE:
|
case POP_JUMP_IF_NOT_NONE:
|
||||||
{
|
|
||||||
RESERVE(2, 2);
|
|
||||||
ADD_TO_TRACE(_IS_NONE, 0, 0);
|
|
||||||
opcode = POP_JUMP_IF_FALSE;
|
|
||||||
goto pop_jump_if_bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
case POP_JUMP_IF_FALSE:
|
case POP_JUMP_IF_FALSE:
|
||||||
case POP_JUMP_IF_TRUE:
|
case POP_JUMP_IF_TRUE:
|
||||||
{
|
{
|
||||||
pop_jump_if_bool:
|
RESERVE(1, 0);
|
||||||
RESERVE(1, 2);
|
|
||||||
max_length -= 2; // Really the start of the stubs
|
|
||||||
int counter = instr[1].cache;
|
int counter = instr[1].cache;
|
||||||
int bitcount = _Py_popcount32(counter);
|
int bitcount = _Py_popcount32(counter);
|
||||||
bool jump_likely = bitcount > 8;
|
int jump_likely = bitcount > 8;
|
||||||
bool jump_sense = opcode == POP_JUMP_IF_TRUE;
|
uint32_t uopcode = BRANCH_TO_GUARD[opcode - POP_JUMP_IF_FALSE][jump_likely];
|
||||||
uint32_t uopcode = jump_sense ^ jump_likely ?
|
|
||||||
_POP_JUMP_IF_TRUE : _POP_JUMP_IF_FALSE;
|
|
||||||
_Py_CODEUNIT *next_instr = instr + 1 + _PyOpcode_Caches[_PyOpcode_Deopt[opcode]];
|
_Py_CODEUNIT *next_instr = instr + 1 + _PyOpcode_Caches[_PyOpcode_Deopt[opcode]];
|
||||||
_Py_CODEUNIT *target_instr = next_instr + oparg;
|
DPRINTF(4, "%s(%d): counter=%x, bitcount=%d, likely=%d, uopcode=%s\n",
|
||||||
_Py_CODEUNIT *stub_target = jump_likely ? next_instr : target_instr;
|
|
||||||
DPRINTF(4, "%s(%d): counter=%x, bitcount=%d, likely=%d, sense=%d, uopcode=%s\n",
|
|
||||||
uop_name(opcode), oparg,
|
uop_name(opcode), oparg,
|
||||||
counter, bitcount, jump_likely, jump_sense, uop_name(uopcode));
|
counter, bitcount, jump_likely, uop_name(uopcode));
|
||||||
ADD_TO_TRACE(uopcode, max_length, 0);
|
ADD_TO_TRACE(uopcode, max_length, 0);
|
||||||
ADD_TO_STUB(max_length, _SET_IP, INSTR_IP(stub_target, code), 0);
|
|
||||||
ADD_TO_STUB(max_length + 1, _EXIT_TRACE, 0, 0);
|
|
||||||
if (jump_likely) {
|
if (jump_likely) {
|
||||||
|
_Py_CODEUNIT *target_instr = next_instr + oparg;
|
||||||
DPRINTF(2, "Jump likely (%x = %d bits), continue at byte offset %d\n",
|
DPRINTF(2, "Jump likely (%x = %d bits), continue at byte offset %d\n",
|
||||||
instr[1].cache, bitcount, 2 * INSTR_IP(target_instr, code));
|
instr[1].cache, bitcount, 2 * INSTR_IP(target_instr, code));
|
||||||
instr = target_instr;
|
instr = target_instr;
|
||||||
|
@ -797,16 +787,13 @@ compute_used(_PyUOpInstruction *buffer, uint32_t *used)
|
||||||
}
|
}
|
||||||
/* All other micro-ops fall through, so i+1 is reachable */
|
/* All other micro-ops fall through, so i+1 is reachable */
|
||||||
SET_BIT(used, i+1);
|
SET_BIT(used, i+1);
|
||||||
switch(opcode) {
|
if (OPCODE_HAS_JUMP(opcode)) {
|
||||||
case NOP:
|
/* Mark target as reachable */
|
||||||
/* Don't count NOPs as used */
|
SET_BIT(used, buffer[i].oparg);
|
||||||
count--;
|
}
|
||||||
UNSET_BIT(used, i);
|
if (opcode == NOP) {
|
||||||
break;
|
count--;
|
||||||
case _POP_JUMP_IF_FALSE:
|
UNSET_BIT(used, i);
|
||||||
case _POP_JUMP_IF_TRUE:
|
|
||||||
/* Mark target as reachable */
|
|
||||||
SET_BIT(used, buffer[i].oparg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue