Skip to content

Commit 852b4d4

Browse files
Fidget-Spinnerkumaraditya303sweeneyde
authored
[3.11] gh-93382: Cache result of PyCode_GetCode in codeobject (GH-93383) (#93493)
Co-authored-by: Kumar Aditya <[email protected]> Co-authored-by: Dennis Sweeney <[email protected]>
1 parent 96a7614 commit 852b4d4

File tree

6 files changed

+543
-528
lines changed

6 files changed

+543
-528
lines changed

Doc/data/python3.11.abi

+527-524
Large diffs are not rendered by default.

Include/cpython/code.h

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ typedef uint16_t _Py_CODEUNIT;
8989
PyObject *co_qualname; /* unicode (qualname, for reference) */ \
9090
PyObject *co_linetable; /* bytes object that holds location info */ \
9191
PyObject *co_weakreflist; /* to support weakrefs to code objects */ \
92+
PyObject *_co_code; /* cached co_code object/attribute */ \
9293
char *_co_linearray; /* array of line offsets */ \
9394
/* Scratch space for extra data relating to the code object. \
9495
Type is a void* to keep the format private in codeobject.c to force \
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Cache the result of :c:func:`PyCode_GetCode` function to restore the O(1)
2+
lookup of the :attr:`~types.CodeType.co_code` attribute.

Objects/codeobject.c

+8
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
334334
/* not set */
335335
co->co_weakreflist = NULL;
336336
co->co_extra = NULL;
337+
co->_co_code = NULL;
337338

338339
co->co_warmup = QUICKENING_INITIAL_WARMUP_VALUE;
339340
co->_co_linearray_entry_size = 0;
@@ -1421,12 +1422,17 @@ deopt_code(_Py_CODEUNIT *instructions, Py_ssize_t len)
14211422
PyObject *
14221423
_PyCode_GetCode(PyCodeObject *co)
14231424
{
1425+
if (co->_co_code != NULL) {
1426+
return Py_NewRef(co->_co_code);
1427+
}
14241428
PyObject *code = PyBytes_FromStringAndSize((const char *)_PyCode_CODE(co),
14251429
_PyCode_NBYTES(co));
14261430
if (code == NULL) {
14271431
return NULL;
14281432
}
14291433
deopt_code((_Py_CODEUNIT *)PyBytes_AS_STRING(code), Py_SIZE(co));
1434+
assert(co->_co_code == NULL);
1435+
co->_co_code = Py_NewRef(code);
14301436
return code;
14311437
}
14321438

@@ -1585,6 +1591,7 @@ code_dealloc(PyCodeObject *co)
15851591
Py_XDECREF(co->co_qualname);
15861592
Py_XDECREF(co->co_linetable);
15871593
Py_XDECREF(co->co_exceptiontable);
1594+
Py_XDECREF(co->_co_code);
15881595
if (co->co_weakreflist != NULL) {
15891596
PyObject_ClearWeakRefs((PyObject*)co);
15901597
}
@@ -2142,6 +2149,7 @@ _PyStaticCode_Dealloc(PyCodeObject *co)
21422149
deopt_code(_PyCode_CODE(co), Py_SIZE(co));
21432150
co->co_warmup = QUICKENING_INITIAL_WARMUP_VALUE;
21442151
PyMem_Free(co->co_extra);
2152+
Py_CLEAR(co->_co_code);
21452153
co->co_extra = NULL;
21462154
if (co->co_weakreflist != NULL) {
21472155
PyObject_ClearWeakRefs((PyObject *)co);

Programs/test_frozenmain.h

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tools/scripts/deepfreeze.py

+1
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
279279
self.write(f".co_name = {co_name},")
280280
self.write(f".co_qualname = {co_qualname},")
281281
self.write(f".co_linetable = {co_linetable},")
282+
self.write(f"._co_code = NULL,")
282283
self.write("._co_linearray = NULL,")
283284
self.write(f".co_code_adaptive = {co_code_adaptive},")
284285
name_as_code = f"(PyCodeObject *)&{name}"

0 commit comments

Comments
 (0)