8000 bpo-46841: Quicken code in-place by brandtbucher · Pull Request #31888 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content
8000

bpo-46841: Quicken code in-place #31888

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
Mar 21, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6ca0d42
Move bytecode into the code object
brandtbucher Mar 10, 2022
a77a124
Clean things up a bit
brandtbucher Mar 10, 2022
975b8d1
Bump the magic number
brandtbucher Mar 10, 2022
40ddf39
co_bytecode -> _co_code
brandtbucher Mar 10, 2022
bfcba6d
Generate specialization table
brandtbucher Mar 10, 2022
0376822
Clean things up a bit
brandtbucher Mar 10, 2022
3e77b8d
Pack code objects more efficiently
brandtbucher Mar 10, 2022
0a598a7
Fix typo
brandtbucher Mar 10, 2022
2fda3b8
More cleanup
brandtbucher Mar 11, 2022
42810dd
Try a different approach
brandtbucher Mar 11, 2022
7df4934
Clean up the diff
brandtbucher Mar 11, 2022
5fa0ca2
Support equality comparisons again
brandtbucher Mar 11, 2022
1fc2282
Never un-quicken!
brandtbucher Mar 11, 2022
b40e300
More renaming and cleanup
brandtbucher Mar 11, 2022
af27670
Revert marshal format changes
brandtbucher Mar 11, 2022
629bf8b
More cleanup
brandtbucher Mar 11, 2022
59cda59
Clean up the diff
brandtbucher Mar 11, 2022
73c33c1
Catch up with main
brandtbucher Mar 12, 2022
ecfb193
Miscellaneous cleanup
brandtbucher Mar 14, 2022
824b2da
Remove outdated comment
brandtbucher Mar 14, 2022
8164f41
Properly skip over EXTENDED_ARG instructions
brandtbucher Mar 14, 2022
932a3f2
Make sure that f_lasti is always valid
brandtbucher Mar 14, 2022
c0c5498
Add some comments
brandtbucher Mar 14, 2022
f62a395
Catch up with main
brandtbucher Mar 14, 2022
e7464a3
Check opargs during size calculations
brandtbucher Mar 14, 2022
4f51fdd
Add another TODO
brandtbucher Mar 14, 2022
75bd375
Clean up formatting
brandtbucher Mar 15, 2022
d6d5128
Fix compiler warning
brandtbucher Mar 15, 2022
82145c1
Simplify calculation of instr_prev
brandtbucher Mar 15, 2022
ca176ac
_Py_Quicken -> _PyCode_Quicken
brandtbucher Mar 15, 2022
1e06bb5
Revert expensive f_lasti changes
brandtbucher Mar 15, 2022
e70819f
Naming is hard
brandtbucher Mar 16, 2022
001eb53
Catch up with main
brandtbucher Mar 16, 2022
6b96204
make patchcheck
brandtbucher Mar 16, 2022
3087025
blurb add
brandtbucher Mar 16, 2022
6f3bc38
Reuse the PyCodeObject definition for deepfreeze
brandtbucher Mar 16, 2022
c8054b9
Clean up TODO
brandtbucher Mar 18, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Miscellaneous cleanup
  • Loading branch information
brandtbucher committed Mar 14, 2022
commit ecfb193e11b6fb8408cc7ed132c2984aac8810b2
40 changes: 25 additions & 15 deletions Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ frame_getback(PyFrameObject *f, void *closure)
return res;
}

/* Given the index of the effective opcode,
scan back to construct the oparg with EXTENDED_ARG */
// XXX This is broken!
// Given the index of the effective opcode, scan back to construct the oparg
// with EXTENDED_ARG. This only works correctly with *unquickened* code,
// obtained via a call to _PyCode_GetCode!
static unsigned int
get_arg(const _Py_CODEUNIT *codestr, Py_ssize_t i)
{
Expand Down Expand Up @@ -171,18 +171,17 @@ top_of_stack(int64_t stack)
static int64_t *
mark_stacks(PyCodeObject *code_obj, int len)
{
// XXX: this is one big TODO!!!
PyObject *xxx = _PyCode_GetCode(code_obj);
if (xxx == NULL) {
PyObject *co_code = _PyCode_GetCode(code_obj);
if (co_code == NULL) {
return NULL;
}
_Py_CODEUNIT *code = (_Py_CODEUNIT *)PyBytes_AS_STRING(xxx);
_Py_CODEUNIT *code = (_Py_CODEUNIT *)PyBytes_AS_STRING(co_code);
int64_t *stacks = PyMem_New(int64_t, len+1);
int i, j, opcode;

if (stacks == NULL) {
PyErr_NoMemory();
Py_DECREF(xxx);
Py_DECREF(co_code);
return NULL;
}
for (int i = 1; i <= len; i++) {
Expand Down Expand Up @@ -310,7 +309,7 @@ mark_stacks(PyCodeObject *code_obj, int len)
}
}
}
Py_DECREF(xxx);
Py_DECREF(co_code);
return stacks;
}

Expand Down Expand Up @@ -845,15 +844,23 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code,
static int
_PyFrame_OpAlreadyRan(_PyInterpreterFrame *frame, int opcode, int oparg)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might be able to remove this entirely, as there should be no way to trace before the first RESUME.
So don't worry too much if it appears a bit broken.

{
// XXX: Does this handle EXTENDED_ARGs/CACHEs?
// This only works when opcode is a non-quickened form:
assert(_PyOpcode_Deopt[opcode] == opcode);
int check_oparg = 0;
for (int i = 0; i < frame->f_lasti; i++) {
_Py_CODEUNIT instruction = _PyCode_CODE(frame->f_code)[i];
int deopt = _PyOpcode_Deopt[_Py_OPCODE(instruction)];
instruction = _Py_MAKECODEUNIT(deopt, oparg);
if (instruction == _Py_MAKECODEUNIT(opcode, oparg)) {
int check_opcode = _PyOpcode_Deopt[_Py_OPCODE(instruction)];
check_oparg |= _Py_OPARG(instruction);
if (check_opcode == opcode && check_oparg == oparg) {
return 1;
}
i += _PyOpcode_Caches[deopt];
if (check_opcode == EXTENDED_ARG) {
check_oparg <<= 8;
}
else {
check_oparg = 0;
}
i += _PyOpcode_Caches[check_opcode];
}
return 0;
}
Expand All @@ -872,7 +879,10 @@ _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame) {
}
co = frame->f_code;
fast = _PyFrame_GetLocalsArray(frame);
if (frame->f_lasti < 0 && _Py_OPCODE(_PyCode_CODE(co)[0]) == COPY_FREE_VARS) {
// COPY_FREE_VARS has no quickened forms, so no need to use _PyOpcode_Deopt
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should (in theory) be able to assert frame->f_lasti >= 0 here.

// here:
if (frame->f_lasti < 0 && _Py_OPCODE(_PyCode_CODE(co)[0]) == COPY_FREE_VARS)
{
/* Free vars have not been initialized -- Do that */
PyCodeObject *co = frame->f_code;
PyObject *closure = frame->f_func->func_closure;
Expand Down
2 changes: 2 additions & 0 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -8949,6 +8949,8 @@ super_init_without_args(_PyInterpreterFrame *cframe, PyCodeObject *co,
// "firstarg" is a cell here unless (very unlikely) super()
// was called from the C-API before the first MAKE_CELL op.
if (cframe->f_lasti >= 0) {
// MAKE_CELL and COPY_FREE_VARS have no quickened forms, so no need
// to use _PyOpcode_Deopt here:
assert(_Py_OPCODE(_PyCode_CODE(co)[0]) == MAKE_CELL ||
_Py_OPCODE(_PyCode_CODE(co)[0]) == COPY_FREE_VARS);
assert(PyCell_Check(firstarg));
Expand Down
3 changes: 2 additions & 1 deletion Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -6706,7 +6706,6 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
then call the trace function if we're tracing source lines.
*/
initialize_trace_info(&tstate->trace_info, frame);
// XXX: Is this broken?
int prev = _PyCode_CODE(frame->f_code)[instr_prev];
int lastline;
if (_PyOpcode_Deopt[_Py_OPCODE(prev)] == RESUME && _Py_OPARG(prev) == 0) {
Expand All @@ -6724,6 +6723,8 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
/* Trace backward edges (except in 'yield from') or if line number has changed */
int trace = line != lastline ||
(frame->f_lasti < instr_prev &&
// SEND has no quickened forms, so no need to use _PyOpcode_Deopt
// here:
_Py_OPCODE(_PyCode_CODE(frame->f_code)[frame->f_lasti]) != SEND);
if (trace) {
result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None);
Expand Down
5 changes: 3 additions & 2 deletions Tools/scripts/deepfreeze.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,9 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
self.write(f".co_endlinetable = {co_endlinetable},")
self.write(f".co_columntable = {co_columntable},")
self.write(f"._co_code = {make_string_literal(code.co_code)},")
self.deallocs.append(f"_PyStaticCode_Dealloc((PyCodeObject *)&{name});")
self.interns.append(f"_PyStaticCode_InternStrings((PyCodeObject *)&{name})")
cast = f"(PyCodeObject *)&{name}"
self.deallocs.append(f"_PyStaticCode_Dealloc({cast});")
self.interns.append(f"_PyStaticCode_InternStrings({cast})")
return f"& {name}.ob_base.ob_base"

def generate_tuple(self, name: str, t: Tuple[object, ...]) -> str:
Expand Down
0