bpo-26219: per opcode cache for LOAD_GLOBAL (GH-12884) · python/cpython@91234a1 (original) (raw)
`@@ -2,7 +2,9 @@
`
2
2
``
3
3
`#include "Python.h"
`
4
4
`#include "code.h"
`
``
5
`+
#include "opcode.h"
`
5
6
`#include "structmember.h"
`
``
7
`+
#include "pycore_code.h"
`
6
8
`#include "pycore_pystate.h"
`
7
9
`#include "pycore_tupleobject.h"
`
8
10
`#include "clinic/codeobject.c.h"
`
`@@ -233,9 +235,56 @@ PyCode_New(int argcount, int posonlyargcount, int kwonlyargcount,
`
233
235
`co->co_zombieframe = NULL;
`
234
236
`co->co_weakreflist = NULL;
`
235
237
`co->co_extra = NULL;
`
``
238
+
``
239
`+
co->co_opcache_map = NULL;
`
``
240
`+
co->co_opcache = NULL;
`
``
241
`+
co->co_opcache_flag = 0;
`
``
242
`+
co->co_opcache_size = 0;
`
236
243
`return co;
`
237
244
`}
`
238
245
``
``
246
`+
int
`
``
247
`+
_PyCode_InitOpcache(PyCodeObject *co)
`
``
248
`+
{
`
``
249
`+
Py_ssize_t co_size = PyBytes_Size(co->co_code) / sizeof(_Py_CODEUNIT);
`
``
250
`+
co->co_opcache_map = (unsigned char *)PyMem_Calloc(co_size, 1);
`
``
251
`+
if (co->co_opcache_map == NULL) {
`
``
252
`+
return -1;
`
``
253
`+
}
`
``
254
+
``
255
`+
_Py_CODEUNIT opcodes = (_Py_CODEUNIT)PyBytes_AS_STRING(co->co_code);
`
``
256
`+
Py_ssize_t opts = 0;
`
``
257
+
``
258
`+
for (Py_ssize_t i = 0; i < co_size;) {
`
``
259
`+
unsigned char opcode = _Py_OPCODE(opcodes[i]);
`
``
260
`+
i++; // 'i' is now aligned to (next_instr - first_instr)
`
``
261
+
``
262
`+
// TODO: LOAD_METHOD, LOAD_ATTR
`
``
263
`+
if (opcode == LOAD_GLOBAL) {
`
``
264
`+
co->co_opcache_map[i] = ++opts;
`
``
265
`+
if (opts > 254) {
`
``
266
`+
break;
`
``
267
`+
}
`
``
268
`+
}
`
``
269
`+
}
`
``
270
+
``
271
`+
if (opts) {
`
``
272
`+
co->co_opcache = (_PyOpcache *)PyMem_Calloc(opts, sizeof(_PyOpcache));
`
``
273
`+
if (co->co_opcache == NULL) {
`
``
274
`+
PyMem_FREE(co->co_opcache_map);
`
``
275
`+
return -1;
`
``
276
`+
}
`
``
277
`+
}
`
``
278
`+
else {
`
``
279
`+
PyMem_FREE(co->co_opcache_map);
`
``
280
`+
co->co_opcache_map = NULL;
`
``
281
`+
co->co_opcache = NULL;
`
``
282
`+
}
`
``
283
+
``
284
`+
co->co_opcache_size = opts;
`
``
285
`+
return 0;
`
``
286
`+
}
`
``
287
+
239
288
`PyCodeObject *
`
240
289
`PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
`
241
290
`{
`
`@@ -458,6 +507,15 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
`
458
507
`static void
`
459
508
`code_dealloc(PyCodeObject *co)
`
460
509
`{
`
``
510
`+
if (co->co_opcache != NULL) {
`
``
511
`+
PyMem_FREE(co->co_opcache);
`
``
512
`+
}
`
``
513
`+
if (co->co_opcache_map != NULL) {
`
``
514
`+
PyMem_FREE(co->co_opcache_map);
`
``
515
`+
}
`
``
516
`+
co->co_opcache_flag = 0;
`
``
517
`+
co->co_opcache_size = 0;
`
``
518
+
461
519
`if (co->co_extra != NULL) {
`
462
520
`PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
`
463
521
`_PyCodeObjectExtra *co_extra = co->co_extra;
`
`@@ -504,6 +562,13 @@ code_sizeof(PyCodeObject *co, PyObject *Py_UNUSED(args))
`
504
562
`res += sizeof(_PyCodeObjectExtra) +
`
505
563
` (co_extra->ce_size-1) * sizeof(co_extra->ce_extras[0]);
`
506
564
` }
`
``
565
`+
if (co->co_opcache != NULL) {
`
``
566
`+
assert(co->co_opcache_map != NULL);
`
``
567
`+
// co_opcache_map
`
``
568
`+
res += PyBytes_GET_SIZE(co->co_code) / sizeof(_Py_CODEUNIT);
`
``
569
`+
// co_opcache
`
``
570
`+
res += co->co_opcache_size * sizeof(_PyOpcache);
`
``
571
`+
}
`
507
572
`return PyLong_FromSsize_t(res);
`
508
573
`}
`
509
574
``