Skip to content

Commit 4f5e1cb

Browse files
authored
GH-98831: Refactor and fix cases generator (#99526)
Also complete cache effects for BINARY_SUBSCR family.
1 parent b629fdd commit 4f5e1cb

File tree

6 files changed

+405
-308
lines changed

6 files changed

+405
-308
lines changed

Python/bytecodes.c

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,15 @@ do { \
7171

7272
#define inst(name, ...) case name:
7373
#define super(name) static int SUPER_##name
74-
#define family(name) static int family_##name
74+
#define family(name, ...) static int family_##name
7575

7676
#define NAME_ERROR_MSG \
7777
"name '%.200s' is not defined"
7878

7979
// Dummy variables for stack effects.
8080
static PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub;
8181
static PyObject *container, *start, *stop, *v, *lhs, *rhs;
82+
static PyObject *list, *tuple, *dict;
8283

8384
static PyObject *
8485
dummy_func(
@@ -322,7 +323,15 @@ dummy_func(
322323
ERROR_IF(sum == NULL, error);
323324
}
324325

325-
inst(BINARY_SUBSCR, (container, sub -- res)) {
326+
family(binary_subscr, INLINE_CACHE_ENTRIES_BINARY_SUBSCR) = {
327+
BINARY_SUBSCR,
328+
BINARY_SUBSCR_DICT,
329+
BINARY_SUBSCR_GETITEM,
330+
BINARY_SUBSCR_LIST_INT,
331+
BINARY_SUBSCR_TUPLE_INT,
332+
};
333+
334+
inst(BINARY_SUBSCR, (container, sub, unused/4 -- res)) {
326335
_PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)next_instr;
327336
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
328337
assert(cframe.use_tracing == 0);
@@ -336,7 +345,6 @@ dummy_func(
336345
Py_DECREF(container);
337346
Py_DECREF(sub);
338347
ERROR_IF(res == NULL, error);
339-
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
340348
}
341349

342350
inst(BINARY_SLICE, (container, start, stop -- res)) {
@@ -369,11 +377,8 @@ dummy_func(
369377
ERROR_IF(err, error);
370378
}
371379

372-
// stack effect: (__0 -- )
373-
inst(BINARY_SUBSCR_LIST_INT) {
380+
inst(BINARY_SUBSCR_LIST_INT, (list, sub, unused/4 -- res)) {
374381
assert(cframe.use_tracing == 0);
375-
PyObject *sub = TOP();
376-
PyObject *list = SECOND();
377382
DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR);
378383
DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR);
379384

@@ -384,21 +389,15 @@ dummy_func(
384389
Py_ssize_t index = ((PyLongObject*)sub)->ob_digit[0];
385390
DEOPT_IF(index >= PyList_GET_SIZE(list), BINARY_SUBSCR);
386391
STAT_INC(BINARY_SUBSCR, hit);
387-
PyObject *res = PyList_GET_ITEM(list, index);
392+
res = PyList_GET_ITEM(list, index);
388393
assert(res != NULL);
389394
Py_INCREF(res);
390-
STACK_SHRINK(1);
391395
_Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
392-
SET_TOP(res);
393396
Py_DECREF(list);
394-
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
395397
}
396398

397-
// stack effect: (__0 -- )
398-
inst(BINARY_SUBSCR_TUPLE_INT) {
399+
inst(BINARY_SUBSCR_TUPLE_INT, (tuple, sub, unused/4 -- res)) {
399400
assert(cframe.use_tracing == 0);
400-
PyObject *sub = TOP();
401-
PyObject *tuple = SECOND();
402401
DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR);
403402
DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR);
404403

@@ -409,51 +408,39 @@ dummy_func(
409408
Py_ssize_t index = ((PyLongObject*)sub)->ob_digit[0];
410409
DEOPT_IF(index >= PyTuple_GET_SIZE(tuple), BINARY_SUBSCR);
411410
STAT_INC(BINARY_SUBSCR, hit);
412-
PyObject *res = PyTuple_GET_ITEM(tuple, index);
411+
res = PyTuple_GET_ITEM(tuple, index);
413412
assert(res != NULL);
414413
Py_INCREF(res);
415-
STACK_SHRINK(1);
416414
_Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
417-
SET_TOP(res);
418415
Py_DECREF(tuple);
419-
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
420416
}
421417

422-
// stack effect: (__0 -- )
423-
inst(BINARY_SUBSCR_DICT) {
418+
inst(BINARY_SUBSCR_DICT, (dict, sub, unused/4 -- res)) {
424419
assert(cframe.use_tracing == 0);
425-
PyObject *dict = SECOND();
426-
DEOPT_IF(!PyDict_CheckExact(SECOND()), BINARY_SUBSCR);
420+
DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR);
427421
STAT_INC(BINARY_SUBSCR, hit);
428-
PyObject *sub = TOP();
429-
PyObject *res = PyDict_GetItemWithError(dict, sub);
422+
res = PyDict_GetItemWithError(dict, sub);
430423
if (res == NULL) {
431424
if (!_PyErr_Occurred(tstate)) {
432425
_PyErr_SetKeyError(sub);
433426
}
434-
goto error;
427+
Py_DECREF(dict);
428+
Py_DECREF(sub);
429+
ERROR_IF(1, error);
435430
}
436-
Py_INCREF(res);
437-
STACK_SHRINK(1);
438-
Py_DECREF(sub);
439-
SET_TOP(res);
431+
Py_INCREF(res); // Do this before DECREF'ing dict, sub
440432
Py_DECREF(dict);
441-
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
433+
Py_DECREF(sub);
442434
}
443435

444-
// stack effect: (__0 -- )
445-
inst(BINARY_SUBSCR_GETITEM) {
446-
PyObject *sub = TOP();
447-
PyObject *container = SECOND();
448-
_PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)next_instr;
449-
uint32_t type_version = read_u32(cache->type_version);
436+
inst(BINARY_SUBSCR_GETITEM, (container, sub, unused/1, type_version/2, func_version/1 -- unused)) {
450437
PyTypeObject *tp = Py_TYPE(container);
451438
DEOPT_IF(tp->tp_version_tag != type_version, BINARY_SUBSCR);
452439
assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE);
453440
PyObject *cached = ((PyHeapTypeObject *)tp)->_spec_cache.getitem;
454441
assert(PyFunction_Check(cached));
455442
PyFunctionObject *getitem = (PyFunctionObject *)cached;
456-
DEOPT_IF(getitem->func_version != cache->func_version, BINARY_SUBSCR);
443+
DEOPT_IF(getitem->func_version != func_version, BINARY_SUBSCR);
457444
PyCodeObject *code = (PyCodeObject *)getitem->func_code;
458445
assert(code->co_argcount == 2);
459446
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), BINARY_SUBSCR);

Python/generated_cases.c.h

Lines changed: 36 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)