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

6 files changed

lines changed

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.

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);

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