|
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 |
|
|
0 commit comments