|
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" |
@@ -252,9 +254,56 @@ PyCode_New(int argcount, int posonlyargcount, int kwonlyargcount, |
252 | 254 | co->co_zombieframe = NULL; |
253 | 255 | co->co_weakreflist = NULL; |
254 | 256 | co->co_extra = NULL; |
| 257 | + |
| 258 | + co->co_opcache_map = NULL; |
| 259 | + co->co_opcache = NULL; |
| 260 | + co->co_opcache_flag = 0; |
| 261 | + co->co_opcache_size = 0; |
255 | 262 | return co; |
256 | 263 | } |
257 | 264 |
|
| 265 | +int |
| 266 | +_PyCode_InitOpcache(PyCodeObject *co) |
| 267 | +{ |
| 268 | + Py_ssize_t co_size = PyBytes_Size(co->co_code) / sizeof(_Py_CODEUNIT); |
| 269 | + co->co_opcache_map = (unsigned char *)PyMem_Calloc(co_size, 1); |
| 270 | + if (co->co_opcache_map == NULL) { |
| 271 | + return -1; |
| 272 | + } |
| 273 | + |
| 274 | + _Py_CODEUNIT *opcodes = (_Py_CODEUNIT*)PyBytes_AS_STRING(co->co_code); |
| 275 | + Py_ssize_t opts = 0; |
| 276 | + |
| 277 | + for (Py_ssize_t i = 0; i < co_size;) { |
| 278 | + unsigned char opcode = _Py_OPCODE(opcodes[i]); |
| 279 | + i++; // 'i' is now aligned to (next_instr - first_instr) |
| 280 | + |
| 281 | + // TODO: LOAD_METHOD, LOAD_ATTR |
| 282 | + if (opcode == LOAD_GLOBAL) { |
| 283 | + co->co_opcache_map[i] = ++opts; |
| 284 | + if (opts > 254) { |
| 285 | + break; |
| 286 | + } |
| 287 | + } |
| 288 | + } |
| 289 | + |
| 290 | + if (opts) { |
| 291 | + co->co_opcache = (_PyOpcache *)PyMem_Calloc(opts, sizeof(_PyOpcache)); |
| 292 | + if (co->co_opcache == NULL) { |
| 293 | + PyMem_FREE(co->co_opcache_map); |
| 294 | + return -1; |
| 295 | + } |
| 296 | + } |
| 297 | + else { |
| 298 | + PyMem_FREE(co->co_opcache_map); |
| 299 | + co->co_opcache_map = NULL; |
| 300 | + co->co_opcache = NULL; |
| 301 | + } |
| 302 | + |
| 303 | + co->co_opcache_size = opts; |
| 304 | + return 0; |
| 305 | +} |
| 306 | + |
258 | 307 | PyCodeObject * |
259 | 308 | PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) |
260 | 309 | { |
@@ -485,6 +534,15 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw) |
485 | 534 | static void |
486 | 535 | code_dealloc(PyCodeObject *co) |
487 | 536 | { |
| 537 | + if (co->co_opcache != NULL) { |
| 538 | + PyMem_FREE(co->co_opcache); |
| 539 | + } |
| 540 | + if (co->co_opcache_map != NULL) { |
| 541 | + PyMem_FREE(co->co_opcache_map); |
| 542 | + } |
| 543 | + co->co_opcache_flag = 0; |
| 544 | + co->co_opcache_size = 0; |
| 545 | + |
488 | 546 | if (co->co_extra != NULL) { |
489 | 547 | PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); |
490 | 548 | _PyCodeObjectExtra *co_extra = co->co_extra; |
@@ -531,6 +589,13 @@ code_sizeof(PyCodeObject *co, PyObject *Py_UNUSED(args)) |
531 | 589 | res += sizeof(_PyCodeObjectExtra) + |
532 | 590 | (co_extra->ce_size-1) * sizeof(co_extra->ce_extras[0]); |
533 | 591 | } |
| 592 | + if (co->co_opcache != NULL) { |
| 593 | + assert(co->co_opcache_map != NULL); |
| 594 | + // co_opcache_map |
| 595 | + res += PyBytes_GET_SIZE(co->co_code) / sizeof(_Py_CODEUNIT); |
| 596 | + // co_opcache |
| 597 | + res += co->co_opcache_size * sizeof(_PyOpcache); |
| 598 | + } |
534 | 599 | return PyLong_FromSsize_t(res); |
535 | 600 | } |
536 | 601 |
|
|
0 commit comments