[3.11] gh-93382: Cache result of `PyCode_GetCode` in codeobject (GH-9… · python/cpython@852b4d4

GitHub

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}"