◐ Shell
reader mode source ↗
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
File filter
Conversations
Jump to
Diff view
Apply and reload
Show whitespace
Diff view
Apply and reload
8 changes: 8 additions & 0 deletions Include/internal/pycore_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,17 @@ typedef struct {
unsigned int tp_version_tag;
} _PyOpCodeOpt_LoadAttr;

struct _PyOpcache {
union {
_PyOpcache_LoadGlobal lg;
_PyOpCodeOpt_LoadAttr la;
} u;
char optimized;
Expand Down
159 changes: 156 additions & 3 deletions Python/ceval.c
Original file line number Diff line number Diff line change
@@ -111,7 +111,7 @@ static long dxp[256];
#else
#define OPCACHE_MIN_RUNS 1024 /* create opcache when code executed this time */
#endif
#define OPCODE_CACHE_MAX_TRIES 20
#define OPCACHE_STATS 0 /* Enable stats */

#if OPCACHE_STATS
Expand All @@ -127,6 +127,13 @@ static size_t opcache_attr_hits = 0;
static size_t opcache_attr_misses = 0;
static size_t opcache_attr_deopts = 0;
static size_t opcache_attr_total = 0;
#endif


Expand Down Expand Up @@ -396,6 +403,30 @@ _PyEval_Fini(void)

fprintf(stderr, "-- Opcode cache LOAD_ATTR total = %zd\n",
opcache_attr_total);
#endif
}

Expand Down Expand Up @@ -1358,6 +1389,37 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
if (co->co_opcache != NULL) opcache_attr_total++; \
} while (0)

#else /* OPCACHE_STATS */

#define OPCACHE_STAT_GLOBAL_HIT()
Expand All @@ -1370,6 +1432,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
#define OPCACHE_STAT_ATTR_DEOPT()
#define OPCACHE_STAT_ATTR_TOTAL()

#endif

/* Start of code */
Expand Down Expand Up @@ -3239,7 +3308,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
if (co_opcache->optimized == 0) {
// First time we optimize this opcode. */
OPCACHE_STAT_ATTR_OPT();
co_opcache->optimized = OPCODE_CACHE_MAX_TRIES;
}

la = &co_opcache->u.la;
Expand Down Expand Up @@ -3703,9 +3772,82 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)

case TARGET(LOAD_METHOD): {
/* Designed to work in tandem with CALL_METHOD. */
PyObject *name = GETITEM(names, oparg);
PyObject *obj = TOP();
PyObject *meth = NULL;

int meth_found = _PyObject_GetMethod(obj, name, &meth);

@@ -3722,6 +3864,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
*/
SET_TOP(meth);
PUSH(obj); // self
}
else {
/* meth is not an unbound method (but a regular attr, or
Expand Down
Toggle all file notes Toggle all file annotations