Skip to content

Commit d52ffc1

Browse files
Fidget-Spinnerkumaraditya303sweeneyde
authored
gh-93382: Cache result of PyCode_GetCode in codeobject (GH-93383)
Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Co-authored-by: Dennis Sweeney <36520290+sweeneyde@users.noreply.github.com>
1 parent d8f40ea commit d52ffc1

File tree

5 files changed

+21
-4
lines changed

5 files changed

+21
-4
lines changed

Include/cpython/code.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ typedef uint16_t _Py_CODEUNIT;
8888
PyObject *co_qualname; /* unicode (qualname, for reference) */ \
8989
PyObject *co_linetable; /* bytes object that holds location info */ \
9090
PyObject *co_weakreflist; /* to support weakrefs to code objects */ \
91+
void *_co_code; /* cached co_code object/attribute */ \
9192
/* Scratch space for extra data relating to the code object. \
9293
Type is a void* to keep the format private in codeobject.c to force \
9394
people to go through the proper APIs. */ \
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Speed up the :c:func:`PyCode_GetCode` function which also improves accessing the :attr:`~types.CodeType.co_code` attribute in Python.

Objects/codeobject.c

Lines changed: 7 additions & 0 deletions
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
memcpy(_PyCode_CODE(co), PyBytes_AS_STRING(con->code),
@@ -1367,12 +1368,17 @@ deopt_code(_Py_CODEUNIT *instructions, Py_ssize_t len)
13671368
PyObject *
13681369
_PyCode_GetCode(PyCodeObject *co)
13691370
{
1371+
if (co->_co_code != NULL) {
1372+
return Py_NewRef(co->_co_code);
1373+
}
13701374
PyObject *code = PyBytes_FromStringAndSize((const char *)_PyCode_CODE(co),
13711375
_PyCode_NBYTES(co));
13721376
if (code == NULL) {
13731377
return NULL;
13741378
}
13751379
deopt_code((_Py_CODEUNIT *)PyBytes_AS_STRING(code), Py_SIZE(co));
1380+
assert(co->_co_code == NULL);
1381+
co->_co_code = (void *)Py_NewRef(code);
13761382
return code;
13771383
}
13781384

@@ -1531,6 +1537,7 @@ code_dealloc(PyCodeObject *co)
15311537
Py_XDECREF(co->co_qualname);
15321538
Py_XDECREF(co->co_linetable);
15331539
Py_XDECREF(co->co_exceptiontable);
1540+
Py_XDECREF(co->_co_code);
15341541
if (co->co_weakreflist != NULL) {
15351542
PyObject_ClearWeakRefs((PyObject*)co);
15361543
}

Objects/frameobject.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,22 +458,30 @@ _PyFrame_GetState(PyFrameObject *frame)
458458
static void
459459
add_load_fast_null_checks(PyCodeObject *co)
460460
{
461+
int changed = 0;
461462
_Py_CODEUNIT *instructions = _PyCode_CODE(co);
462463
for (Py_ssize_t i = 0; i < Py_SIZE(co); i++) {
463464
switch (_Py_OPCODE(instructions[i])) {
464465
case LOAD_FAST:
465466
case LOAD_FAST__LOAD_FAST:
466467
case LOAD_FAST__LOAD_CONST:
468+
changed = 1;
467469
_Py_SET_OPCODE(instructions[i], LOAD_FAST_CHECK);
468470
break;
469471
case LOAD_CONST__LOAD_FAST:
472+
changed = 1;
470473
_Py_SET_OPCODE(instructions[i], LOAD_CONST);
471474
break;
472475
case STORE_FAST__LOAD_FAST:
476+
changed = 1;
473477
_Py_SET_OPCODE(instructions[i], STORE_FAST);
474478
break;
475479
}
476480
}
481+
if (changed) {
482+
// invalidate cached co_code object
483+
Py_CLEAR(co->_co_code);
484+
}
477485
}
478486

479487
/* Setter for f_lineno - you can set f_lineno from within a trace function in

Programs/test_frozenmain.h

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy