diff options
author | Mark Shannon <mark@hotpy.org> | 2021-06-07 17:38:06 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-07 17:38:06 (GMT) |
commit | 001eb520b5757294dc455c900d94b7b153de6cdd (patch) | |
tree | c9d3a3d36e860a9a0591ce6d7d758201e72c2230 /Python/ceval.c | |
parent | 89e50ab36fac6a0e7f1998501f36fcd2872a6604 (diff) | |
download | cpython-001eb520b5757294dc455c900d94b7b153de6cdd.zip cpython-001eb520b5757294dc455c900d94b7b153de6cdd.tar.gz cpython-001eb520b5757294dc455c900d94b7b153de6cdd.tar.bz2 |
bpo-44187: Quickening infrastructure (GH-26264)
* Add co_firstinstr field to code object.
* Implement barebones quickening.
* Use non-quickened bytecode when tracing.
* Add NEWS item
* Add new file to Windows build.
* Don't specialize instructions with EXTENDED_ARG.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 4dff7bd..619eff2 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1343,6 +1343,14 @@ eval_frame_handle_pending(PyThreadState *tstate) #define JUMPTO(x) (next_instr = first_instr + (x)) #define JUMPBY(x) (next_instr += (x)) +/* Get opcode and oparg from original instructions, not quickened form. */ +#define TRACING_NEXTOPARG() do { \ + _Py_CODEUNIT word = ((_Py_CODEUNIT *)PyBytes_AS_STRING(co->co_code))[INSTR_OFFSET()]; \ + opcode = _Py_OPCODE(word); \ + oparg = _Py_OPARG(word); \ + next_instr++; \ + } while (0) + /* OpCode prediction macros Some opcodes tend to come in pairs thus making it possible to predict the second code when the first is run. For example, @@ -1644,15 +1652,23 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) if (PyDTrace_FUNCTION_ENTRY_ENABLED()) dtrace_function_entry(f); + /* Increment the warmup counter and quicken if warm enough + * _Py_Quicken is idempotent so we don't worry about overflow */ + if (!PyCodeObject_IsWarmedUp(co)) { + PyCodeObject_IncrementWarmup(co); + if (PyCodeObject_IsWarmedUp(co)) { + if (_Py_Quicken(co)) { + goto exit_eval_frame; + } + } + } + + names = co->co_names; consts = co->co_consts; fastlocals = f->f_localsptr; + first_instr = co->co_firstinstr; freevars = f->f_localsptr + co->co_nlocals; - assert(PyBytes_Check(co->co_code)); - assert(PyBytes_GET_SIZE(co->co_code) <= INT_MAX); - assert(PyBytes_GET_SIZE(co->co_code) % sizeof(_Py_CODEUNIT) == 0); - assert(_Py_IS_ALIGNED(PyBytes_AS_STRING(co->co_code), sizeof(_Py_CODEUNIT))); - first_instr = (_Py_CODEUNIT *) PyBytes_AS_STRING(co->co_code); /* f->f_lasti refers to the index of the last instruction, unless it's -1 in which case next_instr should be first_instr. @@ -1757,7 +1773,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) tracing_dispatch: f->f_lasti = INSTR_OFFSET(); - NEXTOPARG(); + TRACING_NEXTOPARG(); if (PyDTrace_LINE_ENABLED()) maybe_dtrace_line(f, &trace_info); |