Original file line numberDiff line numberDiff line change@@ -89,6 +89,7 @@ typedef uint16_t _Py_CODEUNIT;
8989PyObject*co_qualname; /* unicode (qualname, for reference) */ \
9090PyObject*co_linetable; /* bytes object that holds location info */ \
9191PyObject*co_weakreflist; /* to support weakrefs to code objects */ \
92+PyObject*_co_code; /* cached co_code object/attribute */ \
9293char*_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.
Original file line numberDiff line numberDiff line change@@ -334,6 +334,7 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
334334/* not set */
335335co->co_weakreflist=NULL;
336336co->co_extra=NULL;
337+co->_co_code=NULL;
337338338339co->co_warmup=QUICKENING_INITIAL_WARMUP_VALUE;
339340co->_co_linearray_entry_size=0;
@@ -1421,12 +1422,17 @@ deopt_code(_Py_CODEUNIT *instructions, Py_ssize_t len)
14211422PyObject*
14221423_PyCode_GetCode(PyCodeObject*co)
14231424{
1425+if (co->_co_code!=NULL) {
1426+returnPy_NewRef(co->_co_code);
1427+ }
14241428PyObject*code=PyBytes_FromStringAndSize((constchar*)_PyCode_CODE(co),
14251429_PyCode_NBYTES(co));
14261430if (code==NULL) {
14271431returnNULL;
14281432 }
14291433deopt_code((_Py_CODEUNIT*)PyBytes_AS_STRING(code), Py_SIZE(co));
1434+assert(co->_co_code==NULL);
1435+co->_co_code=Py_NewRef(code);
14301436returncode;
14311437}
14321438@@ -1585,6 +1591,7 @@ code_dealloc(PyCodeObject *co)
15851591Py_XDECREF(co->co_qualname);
15861592Py_XDECREF(co->co_linetable);
15871593Py_XDECREF(co->co_exceptiontable);
1594+Py_XDECREF(co->_co_code);
15881595if (co->co_weakreflist!=NULL) {
15891596PyObject_ClearWeakRefs((PyObject*)co);
15901597 }
@@ -2142,6 +2149,7 @@ _PyStaticCode_Dealloc(PyCodeObject *co)
21422149deopt_code(_PyCode_CODE(co), Py_SIZE(co));
21432150co->co_warmup=QUICKENING_INITIAL_WARMUP_VALUE;
21442151PyMem_Free(co->co_extra);
2152+Py_CLEAR(co->_co_code);
21452153co->co_extra=NULL;
21462154if (co->co_weakreflist!=NULL) {
21472155PyObject_ClearWeakRefs((PyObject*)co);
Original file line numberDiff line numberDiff line change@@ -279,6 +279,7 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
279279self.write(f".co_name = {co_name},")
280280self.write(f".co_qualname = {co_qualname},")
281281self.write(f".co_linetable = {co_linetable},")
282+self.write(f"._co_code = NULL,")
282283self.write("._co_linearray = NULL,")
283284self.write(f".co_code_adaptive = {co_code_adaptive},")
284285name_as_code=f"(PyCodeObject *)&{name}"