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

``