From eb791f4a2d306a98d5057856e6442b4913a828f2 Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Wed, 2 Feb 2022 14:05:41 -0800 Subject: [PATCH 1/3] Add a RESUME_QUICK instruction --- Include/opcode.h | 19 ++++++++++--------- Lib/opcode.py | 1 + Python/ceval.c | 24 ++++++++++++------------ Python/opcode_targets.h | 12 ++++++------ Python/specialize.c | 3 +++ 5 files changed, 32 insertions(+), 27 deletions(-) diff --git a/Include/opcode.h b/Include/opcode.h index bce7010ab186b4..58fc62808937f4 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -164,15 +164,16 @@ extern "C" { #define LOAD_METHOD_CLASS 76 #define LOAD_METHOD_MODULE 77 #define LOAD_METHOD_NO_DICT 78 -#define STORE_ATTR_ADAPTIVE 79 -#define STORE_ATTR_INSTANCE_VALUE 80 -#define STORE_ATTR_SLOT 81 -#define STORE_ATTR_WITH_HINT 131 -#define LOAD_FAST__LOAD_FAST 140 -#define STORE_FAST__LOAD_FAST 141 -#define LOAD_FAST__LOAD_CONST 143 -#define LOAD_CONST__LOAD_FAST 150 -#define STORE_FAST__STORE_FAST 153 +#define RESUME_QUICK 79 +#define STORE_ATTR_ADAPTIVE 80 +#define STORE_ATTR_INSTANCE_VALUE 81 +#define STORE_ATTR_SLOT 131 +#define STORE_ATTR_WITH_HINT 140 +#define LOAD_FAST__LOAD_FAST 141 +#define STORE_FAST__LOAD_FAST 143 +#define LOAD_FAST__LOAD_CONST 150 +#define LOAD_CONST__LOAD_FAST 153 +#define STORE_FAST__STORE_FAST 154 #define DO_TRACING 255 #ifdef NEED_OPCODE_JUMP_TABLES static uint32_t _PyOpcode_RelativeJump[8] = { diff --git a/Lib/opcode.py b/Lib/opcode.py index c672aa59f8ec3e..a1f0c6e4326d14 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -278,6 +278,7 @@ def jabs_op(name, op): "LOAD_METHOD_CLASS", "LOAD_METHOD_MODULE", "LOAD_METHOD_NO_DICT", + "RESUME_QUICK", "STORE_ATTR_ADAPTIVE", "STORE_ATTR_INSTANCE_VALUE", "STORE_ATTR_SLOT", diff --git a/Python/ceval.c b/Python/ceval.c index b69d5aa9d32069..da2fd3a4710a27 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1785,9 +1785,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(RESUME) { - assert(tstate->cframe == &cframe); - assert(frame == cframe.current_frame); - int err = _Py_IncrementCountAndMaybeQuicken(frame->f_code); if (err) { if (err < 0) { @@ -1798,6 +1795,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr first_instr = frame->f_code->co_firstinstr; next_instr = first_instr + nexti; } + JUMP_TO_INSTRUCTION(RESUME_QUICK); + } + + TARGET(RESUME_QUICK) { + PREDICTED(RESUME_QUICK); + assert(tstate->cframe == &cframe); + assert(frame == cframe.current_frame); frame->f_state = FRAME_EXECUTING; if (_Py_atomic_load_relaxed(eval_breaker) && oparg < 2) { goto handle_eval_breaker; @@ -2265,7 +2269,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr Py_DECREF(v); if (err != 0) goto error; - PREDICT(JUMP_ABSOLUTE); + PREDICT(JUMP_ABSOLUTE_QUICK); DISPATCH(); } @@ -2277,7 +2281,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr Py_DECREF(v); if (err != 0) goto error; - PREDICT(JUMP_ABSOLUTE); + PREDICT(JUMP_ABSOLUTE_QUICK); DISPATCH(); } @@ -3420,7 +3424,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr if (_PyDict_SetItem_Take2((PyDictObject *)map, key, value) != 0) { goto error; } - PREDICT(JUMP_ABSOLUTE); + PREDICT(JUMP_ABSOLUTE_QUICK); DISPATCH(); } @@ -4057,8 +4061,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(JUMP_ABSOLUTE) { - PREDICTED(JUMP_ABSOLUTE); - assert(oparg < INSTR_OFFSET()); int err = _Py_IncrementCountAndMaybeQuicken(frame->f_code); if (err) { if (err < 0) { @@ -4069,9 +4071,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr first_instr = frame->f_code->co_firstinstr; next_instr = first_instr + nexti; } - JUMPTO(oparg); - CHECK_EVAL_BREAKER(); - DISPATCH(); + JUMP_TO_INSTRUCTION(JUMP_ABSOLUTE_QUICK); } TARGET(JUMP_NO_INTERRUPT) { @@ -4086,6 +4086,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(JUMP_ABSOLUTE_QUICK) { + PREDICTED(JUMP_ABSOLUTE_QUICK); assert(oparg < INSTR_OFFSET()); JUMPTO(oparg); CHECK_EVAL_BREAKER(); @@ -4546,7 +4547,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(KW_NAMES) { assert(call_shape.kwnames == NULL); - assert(oparg < PyTuple_GET_SIZE(consts)); call_shape.kwnames = GETITEM(consts, oparg); DISPATCH(); } diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 1a809ed409d581..f47da2bbb1ef02 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -78,9 +78,9 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_METHOD_CLASS, &&TARGET_LOAD_METHOD_MODULE, &&TARGET_LOAD_METHOD_NO_DICT, + &&TARGET_RESUME_QUICK, &&TARGET_STORE_ATTR_ADAPTIVE, &&TARGET_STORE_ATTR_INSTANCE_VALUE, - &&TARGET_STORE_ATTR_SLOT, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, @@ -130,7 +130,7 @@ static void *opcode_targets[256] = { &&TARGET_POP_JUMP_IF_NOT_NONE, &&TARGET_POP_JUMP_IF_NONE, &&TARGET_RAISE_VARARGS, - &&TARGET_STORE_ATTR_WITH_HINT, + &&TARGET_STORE_ATTR_SLOT, &&TARGET_MAKE_FUNCTION, &&TARGET_BUILD_SLICE, &&TARGET_JUMP_NO_INTERRUPT, @@ -139,21 +139,21 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_DEREF, &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, + &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_LOAD_FAST__LOAD_FAST, - &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_CALL_FUNCTION_EX, - &&TARGET_LOAD_FAST__LOAD_CONST, + &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_EXTENDED_ARG, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, &&TARGET_MAP_ADD, &&TARGET_LOAD_CLASSDEREF, &&TARGET_COPY_FREE_VARS, - &&TARGET_LOAD_CONST__LOAD_FAST, + &&TARGET_LOAD_FAST__LOAD_CONST, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, + &&TARGET_LOAD_CONST__LOAD_FAST, &&TARGET_STORE_FAST__STORE_FAST, - &&_unknown_opcode, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, diff --git a/Python/specialize.c b/Python/specialize.c index 5771a41dcfd2ca..f7ceafe3aa379a 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -395,6 +395,9 @@ optimize(SpecializedCacheOrInstruction *quickened, int len) case JUMP_ABSOLUTE: instructions[i] = _Py_MAKECODEUNIT(JUMP_ABSOLUTE_QUICK, oparg); break; + case RESUME: + instructions[i] = _Py_MAKECODEUNIT(RESUME_QUICK, oparg); + break; case LOAD_FAST: switch(previous_opcode) { case LOAD_FAST: From 6280fcc1c9357874a589deea73a48943c03bf4cc Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Wed, 9 Feb 2022 20:18:45 -0800 Subject: [PATCH 2/3] Clean things up a bit --- Python/ceval.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index 07c9f2af668bf6..1d709d93ef7680 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2218,7 +2218,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr Py_DECREF(v); if (err != 0) goto error; - PREDICT(JUMP_ABSOLUTE_QUICK); + PREDICT(JUMP_ABSOLUTE); DISPATCH(); } @@ -2230,7 +2230,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr Py_DECREF(v); if (err != 0) goto error; - PREDICT(JUMP_ABSOLUTE_QUICK); + PREDICT(JUMP_ABSOLUTE); DISPATCH(); } @@ -3369,7 +3369,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr if (_PyDict_SetItem_Take2((PyDictObject *)map, key, value) != 0) { goto error; } - PREDICT(JUMP_ABSOLUTE_QUICK); + PREDICT(JUMP_ABSOLUTE); DISPATCH(); } @@ -4005,6 +4005,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(JUMP_ABSOLUTE) { + PREDICTED(JUMP_ABSOLUTE); int err = _Py_IncrementCountAndMaybeQuicken(frame->f_code); if (err) { if (err < 0) { @@ -4492,6 +4493,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(KW_NAMES) { assert(call_shape.kwnames == NULL); + assert(oparg < PyTuple_GET_SIZE(consts)); call_shape.kwnames = GETITEM(consts, oparg); DISPATCH(); } From b8fba98647b14924068f0482f15360c0caefeeeb Mon Sep 17 00:00:00 2001 From: Brandt Bucher Date: Wed, 9 Feb 2022 20:21:55 -0800 Subject: [PATCH 3/3] blurb add --- .../Core and Builtins/2022-02-09-20-21-43.bpo-45923.tJ4gDX.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-02-09-20-21-43.bpo-45923.tJ4gDX.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-02-09-20-21-43.bpo-45923.tJ4gDX.rst b/Misc/NEWS.d/next/Core and Builtins/2022-02-09-20-21-43.bpo-45923.tJ4gDX.rst new file mode 100644 index 00000000000000..5ab5d59e50f009 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-02-09-20-21-43.bpo-45923.tJ4gDX.rst @@ -0,0 +1 @@ +Add a quickened form of :opcode:`RESUME` that skips quickening checks.