From 852b4d4bcd12b0b6839a015a262ce976b134f6f3 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Fri, 24 Jun 2022 00:24:49 +0800 Subject: [PATCH] [3.11] gh-93382: Cache result of `PyCode_GetCode` in codeobject (GH-93383) (#93493) Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Co-authored-by: Dennis Sweeney <36520290+sweeneyde@users.noreply.github.com> --- Doc/data/python3.11.abi | 1051 +++++++++-------- Include/cpython/code.h | 1 + ...2-05-31-16-36-30.gh-issue-93382.Jf6gAj.rst | 2 + Objects/codeobject.c | 8 + Programs/test_frozenmain.h | 8 +- Tools/scripts/deepfreeze.py | 1 + 6 files changed, 543 insertions(+), 528 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-05-31-16-36-30.gh-issue-93382.Jf6gAj.rst diff --git a/Doc/data/python3.11.abi b/Doc/data/python3.11.abi index 6e478d78a9e15a..79b3ca3995c246 100644 --- a/Doc/data/python3.11.abi +++ b/Doc/data/python3.11.abi @@ -5858,119 +5858,122 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + - + - + - + - + - + - + - + - + - + - + @@ -7451,93 +7454,93 @@ - - - + + + - - + + - - - - + + + + - - - - + + + + - - - - - - - + + + + + + + - - - + + + - - - + + + - - - - + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + @@ -7591,8 +7594,8 @@ - - + + @@ -8279,7 +8282,7 @@ - + @@ -9255,307 +9258,307 @@ - + - + - + - + - + - + - - + + - - + + - - - - - - - + + + + + + + - - - + + + - - + + - - - + + + - - + + - + - - + + - - + + - + - + - + - + - - - - + + + + - + - - - - - + + + + + - + - - - - - + + + + + - - - - + + + + - + - + - - + + - - - - + + + + - + - - - - + + + + - - - - + + + + - - - + + + - - - - + + + + - + - + - + - + - + - - + + - - + + - - - - + + + + - - - - + + + + - - + + - + - + - + - + - - + + - + - + - - - - + + + + - + - + - - - + + + - - + + - - - - + + + + - - - + + + - - + + - - + + - - + + - - + + - - - + + + @@ -10031,48 +10034,48 @@ - - + + - + - - - + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - - + + - - + + @@ -10104,83 +10107,83 @@ - - + + - - - - + + + + - - - + + + - - - + + + - - + + - - + + - - - + + + - + - - - + + + - - - - + + + + - - - + + + - - + + - - + + - + - - - + + + - - - + + + - - + + @@ -10742,8 +10745,8 @@ - - + + @@ -11101,54 +11104,54 @@ - + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - + + + + - - - - + + + + @@ -11169,32 +11172,32 @@ - + - - + + - - + + - + - - - + + + - + - + @@ -11208,33 +11211,33 @@ - - + + - + - + - - + + - + - + - + - - - + + + @@ -11360,131 +11363,131 @@ - - - - + + + + - - - + + + - - - - + + + + - - + + - - + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - + + + + - - - + + + - + - - - - + + + + - - - + + + - - + + - + - + - - - + + + - - - - + + + + - - + + - - + + - + - - + + - - + + - - + + - + - + - + - + - - + + @@ -13014,7 +13017,7 @@ - + @@ -13085,9 +13088,9 @@ - - - + + + @@ -13171,7 +13174,7 @@ - + @@ -13205,8 +13208,8 @@ - - + + @@ -13238,7 +13241,7 @@ - + @@ -14204,41 +14207,41 @@ - + - + - + - + - + - + - - + + - - + + - - + + - - + + - + @@ -14531,7 +14534,7 @@ - + @@ -14540,7 +14543,7 @@ - + @@ -14785,7 +14788,7 @@ - + @@ -14812,7 +14815,7 @@ - + @@ -14872,7 +14875,7 @@ - + @@ -14916,7 +14919,7 @@ - + @@ -15043,7 +15046,7 @@ - + @@ -15588,7 +15591,7 @@ - + @@ -15602,7 +15605,7 @@ - + @@ -15759,80 +15762,80 @@ - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - + + + - - - - + + + + - - + + - - - + + + @@ -16274,10 +16277,10 @@ - - - - + + + + @@ -16365,7 +16368,7 @@ - + diff --git a/Include/cpython/code.h b/Include/cpython/code.h index d7c9aee46440b5..66cf4eccb8fcc9 100644 --- a/Include/cpython/code.h +++ b/Include/cpython/code.h @@ -89,6 +89,7 @@ typedef uint16_t _Py_CODEUNIT; PyObject *co_qualname; /* unicode (qualname, for reference) */ \ PyObject *co_linetable; /* bytes object that holds location info */ \ PyObject *co_weakreflist; /* to support weakrefs to code objects */ \ + PyObject *_co_code; /* cached co_code object/attribute */ \ char *_co_linearray; /* array of line offsets */ \ /* Scratch space for extra data relating to the code object. \ Type is a void* to keep the format private in codeobject.c to force \ diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-05-31-16-36-30.gh-issue-93382.Jf6gAj.rst b/Misc/NEWS.d/next/Core and Builtins/2022-05-31-16-36-30.gh-issue-93382.Jf6gAj.rst new file mode 100644 index 00000000000000..1fe821edf5a148 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-05-31-16-36-30.gh-issue-93382.Jf6gAj.rst @@ -0,0 +1,2 @@ +Cache the result of :c:func:`PyCode_GetCode` function to restore the O(1) +lookup of the :attr:`~types.CodeType.co_code` attribute. diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 0e914566e30c87..8b9ca890431c6c 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -334,6 +334,7 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con) /* not set */ co->co_weakreflist = NULL; co->co_extra = NULL; + co->_co_code = NULL; co->co_warmup = QUICKENING_INITIAL_WARMUP_VALUE; co->_co_linearray_entry_size = 0; @@ -1421,12 +1422,17 @@ deopt_code(_Py_CODEUNIT *instructions, Py_ssize_t len) PyObject * _PyCode_GetCode(PyCodeObject *co) { + if (co->_co_code != NULL) { + return Py_NewRef(co->_co_code); + } PyObject *code = PyBytes_FromStringAndSize((const char *)_PyCode_CODE(co), _PyCode_NBYTES(co)); if (code == NULL) { return NULL; } deopt_code((_Py_CODEUNIT *)PyBytes_AS_STRING(code), Py_SIZE(co)); + assert(co->_co_code == NULL); + co->_co_code = Py_NewRef(code); return code; } @@ -1585,6 +1591,7 @@ code_dealloc(PyCodeObject *co) Py_XDECREF(co->co_qualname); Py_XDECREF(co->co_linetable); Py_XDECREF(co->co_exceptiontable); + Py_XDECREF(co->_co_code); if (co->co_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject*)co); } @@ -2142,6 +2149,7 @@ _PyStaticCode_Dealloc(PyCodeObject *co) deopt_code(_PyCode_CODE(co), Py_SIZE(co)); co->co_warmup = QUICKENING_INITIAL_WARMUP_VALUE; PyMem_Free(co->co_extra); + Py_CLEAR(co->_co_code); co->co_extra = NULL; if (co->co_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *)co); diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index 1c279134e94dc9..eec2e0cc6048fa 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,7 +1,7 @@ // Auto-generated by Programs/freeze_test_frozenmain.py unsigned char M_test_frozenmain[] = { 227,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0, - 0,0,0,0,0,115,176,0,0,0,151,0,100,0,100,1, + 0,0,0,0,0,243,176,0,0,0,151,0,100,0,100,1, 108,0,90,0,100,0,100,1,108,1,90,1,2,0,101,2, 100,2,166,1,0,0,171,1,0,0,0,0,0,0,0,0, 1,0,2,0,101,2,100,3,101,0,106,3,0,0,0,0, @@ -24,10 +24,10 @@ unsigned char M_test_frozenmain[] = { 32,122,2,58,32,41,7,218,3,115,121,115,218,17,95,116, 101,115,116,105,110,116,101,114,110,97,108,99,97,112,105,218, 5,112,114,105,110,116,218,4,97,114,103,118,218,11,103,101, - 116,95,99,111,110,102,105,103,115,114,2,0,0,0,218,3, + 116,95,99,111,110,102,105,103,115,114,3,0,0,0,218,3, 107,101,121,169,0,243,0,0,0,0,250,18,116,101,115,116, 95,102,114,111,122,101,110,109,97,105,110,46,112,121,250,8, - 60,109,111,100,117,108,101,62,114,17,0,0,0,1,0,0, + 60,109,111,100,117,108,101,62,114,18,0,0,0,1,0,0, 0,115,152,0,0,0,248,240,6,0,1,11,128,10,128,10, 128,10,216,0,24,208,0,24,208,0,24,208,0,24,224,0, 5,128,5,208,6,26,209,0,27,212,0,27,208,0,27,216, @@ -37,6 +37,6 @@ unsigned char M_test_frozenmain[] = { 7,1,42,240,0,7,1,42,128,67,240,14,0,5,10,128, 69,208,10,40,144,67,208,10,40,208,10,40,152,54,160,35, 156,59,208,10,40,208,10,40,209,4,41,212,4,41,208,4, - 41,208,4,41,240,15,7,1,42,240,0,7,1,42,114,15, + 41,208,4,41,240,15,7,1,42,240,0,7,1,42,114,16, 0,0,0, }; diff --git a/Tools/scripts/deepfreeze.py b/Tools/scripts/deepfreeze.py index 50d0b345ed407d..43a7a98fcc503c 100644 --- a/Tools/scripts/deepfreeze.py +++ b/Tools/scripts/deepfreeze.py @@ -279,6 +279,7 @@ def generate_code(self, name: str, code: types.CodeType) -> str: self.write(f".co_name = {co_name},") self.write(f".co_qualname = {co_qualname},") self.write(f".co_linetable = {co_linetable},") + self.write(f"._co_code = NULL,") self.write("._co_linearray = NULL,") self.write(f".co_code_adaptive = {co_code_adaptive},") name_as_code = f"(PyCodeObject *)&{name}"