Skip to content

Commit 1407589

Browse files
gvanrossumpull[bot]
authored andcommitted
GH-98831: Implement array support in cases generator (#100912)
You can now write things like this: ``` inst(BUILD_STRING, (pieces[oparg] -- str)) { ... } inst(LIST_APPEND, (list, unused[oparg-1], v -- list, unused[oparg-1])) { ... } ``` Note that array output effects are only partially supported (they must be named `unused` or correspond to an input effect).
1 parent 416ea17 commit 1407589

File tree

6 files changed

+398
-177
lines changed

6 files changed

+398
-177
lines changed

Python/bytecodes.c

+36-70
Original file line numberDiff line numberDiff line change
@@ -451,16 +451,12 @@ dummy_func(
451451
DISPATCH_INLINED(new_frame);
452452
}
453453

454-
// Alternative: (list, unused[oparg], v -- list, unused[oparg])
455-
inst(LIST_APPEND, (v --)) {
456-
PyObject *list = PEEK(oparg + 1); // +1 to account for v staying on stack
454+
inst(LIST_APPEND, (list, unused[oparg-1], v -- list, unused[oparg-1])) {
457455
ERROR_IF(_PyList_AppendTakeRef((PyListObject *)list, v) < 0, error);
458456
PREDICT(JUMP_BACKWARD);
459457
}
460458

461-
// Alternative: (set, unused[oparg], v -- set, unused[oparg])
462-
inst(SET_ADD, (v --)) {
463-
PyObject *set = PEEK(oparg + 1); // +1 to account for v staying on stack
459+
inst(SET_ADD, (set, unused[oparg-1], v -- set, unused[oparg-1])) {
464460
int err = PySet_Add(set, v);
465461
Py_DECREF(v);
466462
ERROR_IF(err, error);
@@ -532,7 +528,7 @@ dummy_func(
532528
ERROR_IF(res == NULL, error);
533529
}
534530

535-
// stack effect: (__array[oparg] -- )
531+
// This should remain a legacy instruction.
536532
inst(RAISE_VARARGS) {
537533
PyObject *cause = NULL, *exc = NULL;
538534
switch (oparg) {
@@ -1295,40 +1291,25 @@ dummy_func(
12951291
}
12961292
}
12971293

1298-
// stack effect: (__array[oparg] -- __0)
1299-
inst(BUILD_STRING) {
1300-
PyObject *str;
1301-
str = _PyUnicode_JoinArray(&_Py_STR(empty),
1302-
stack_pointer - oparg, oparg);
1303-
if (str == NULL)
1304-
goto error;
1305-
while (--oparg >= 0) {
1306-
PyObject *item = POP();
1307-
Py_DECREF(item);
1294+
inst(BUILD_STRING, (pieces[oparg] -- str)) {
1295+
str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg);
1296+
for (int i = 0; i < oparg; i++) {
1297+
Py_DECREF(pieces[i]);
13081298
}
1309-
PUSH(str);
1299+
ERROR_IF(str == NULL, error);
13101300
}
13111301

1312-
// stack effect: (__array[oparg] -- __0)
1313-
inst(BUILD_TUPLE) {
1314-
STACK_SHRINK(oparg);
1315-
PyObject *tup = _PyTuple_FromArraySteal(stack_pointer, oparg);
1316-
if (tup == NULL)
1317-
goto error;
1318-
PUSH(tup);
1302+
inst(BUILD_TUPLE, (values[oparg] -- tup)) {
1303+
tup = _PyTuple_FromArraySteal(values, oparg);
1304+
ERROR_IF(tup == NULL, error);
13191305
}
13201306

1321-
// stack effect: (__array[oparg] -- __0)
1322-
inst(BUILD_LIST) {
1323-
STACK_SHRINK(oparg);
1324-
PyObject *list = _PyList_FromArraySteal(stack_pointer, oparg);
1325-
if (list == NULL)
1326-
goto error;
1327-
PUSH(list);
1307+
inst(BUILD_LIST, (values[oparg] -- list)) {
1308+
list = _PyList_FromArraySteal(values, oparg);
1309+
ERROR_IF(list == NULL, error);
13281310
}
13291311

1330-
inst(LIST_EXTEND, (iterable -- )) {
1331-
PyObject *list = PEEK(oparg + 1); // iterable is still on the stack
1312+
inst(LIST_EXTEND, (list, unused[oparg-1], iterable -- list, unused[oparg-1])) {
13321313
PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable);
13331314
if (none_val == NULL) {
13341315
if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) &&
@@ -1346,48 +1327,40 @@ dummy_func(
13461327
DECREF_INPUTS();
13471328
}
13481329

1349-
inst(SET_UPDATE, (iterable --)) {
1350-
PyObject *set = PEEK(oparg + 1); // iterable is still on the stack
1330+
inst(SET_UPDATE, (set, unused[oparg-1], iterable -- set, unused[oparg-1])) {
13511331
int err = _PySet_Update(set, iterable);
13521332
DECREF_INPUTS();
13531333
ERROR_IF(err < 0, error);
13541334
}
13551335

1356-
// stack effect: (__array[oparg] -- __0)
1357-
inst(BUILD_SET) {
1358-
PyObject *set = PySet_New(NULL);
1336+
inst(BUILD_SET, (values[oparg] -- set)) {
1337+
set = PySet_New(NULL);
13591338
int err = 0;
1360-
int i;
1361-
if (set == NULL)
1362-
goto error;
1363-
for (i = oparg; i > 0; i--) {
1364-
PyObject *item = PEEK(i);
1339+
for (int i = 0; i < oparg; i++) {
1340+
PyObject *item = values[i];
13651341
if (err == 0)
13661342
err = PySet_Add(set, item);
13671343
Py_DECREF(item);
13681344
}
1369-
STACK_SHRINK(oparg);
13701345
if (err != 0) {
13711346
Py_DECREF(set);
1372-
goto error;
1347+
ERROR_IF(true, error);
13731348
}
1374-
PUSH(set);
13751349
}
13761350

1377-
// stack effect: (__array[oparg*2] -- __0)
1378-
inst(BUILD_MAP) {
1379-
PyObject *map = _PyDict_FromItems(
1380-
&PEEK(2*oparg), 2,
1381-
&PEEK(2*oparg - 1), 2,
1351+
inst(BUILD_MAP, (values[oparg*2] -- map)) {
1352+
map = _PyDict_FromItems(
1353+
values, 2,
1354+
values+1, 2,
13821355
oparg);
13831356
if (map == NULL)
13841357
goto error;
13851358

1386-
while (oparg--) {
1387-
Py_DECREF(POP());
1388-
Py_DECREF(POP());
1359+
for (int i = 0; i < oparg; i++) {
1360+
Py_DECREF(values[i*2]);
1361+
Py_DECREF(values[i*2+1]);
13891362
}
1390-
PUSH(map);
1363+
ERROR_IF(map == NULL, error);
13911364
}
13921365

13931366
inst(SETUP_ANNOTATIONS, (--)) {
@@ -1432,28 +1405,21 @@ dummy_func(
14321405
}
14331406
}
14341407

1435-
// stack effect: (__array[oparg] -- )
1436-
inst(BUILD_CONST_KEY_MAP) {
1437-
PyObject *map;
1438-
PyObject *keys = TOP();
1408+
inst(BUILD_CONST_KEY_MAP, (values[oparg], keys -- map)) {
14391409
if (!PyTuple_CheckExact(keys) ||
14401410
PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) {
14411411
_PyErr_SetString(tstate, PyExc_SystemError,
14421412
"bad BUILD_CONST_KEY_MAP keys argument");
1443-
goto error;
1413+
goto error; // Pop the keys and values.
14441414
}
14451415
map = _PyDict_FromItems(
14461416
&PyTuple_GET_ITEM(keys, 0), 1,
1447-
&PEEK(oparg + 1), 1, oparg);
1448-
if (map == NULL) {
1449-
goto error;
1450-
}
1451-
1452-
Py_DECREF(POP());
1453-
while (oparg--) {
1454-
Py_DECREF(POP());
1417+
values, 1, oparg);
1418+
Py_DECREF(keys);
1419+
for (int i = 0; i < oparg; i++) {
1420+
Py_DECREF(values[i]);
14551421
}
1456-
PUSH(map);
1422+
ERROR_IF(map == NULL, error);
14571423
}
14581424

14591425
inst(DICT_UPDATE, (update --)) {

Python/generated_cases.c.h

+55-47
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/opcode_metadata.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ static const struct {
4545
[BINARY_SUBSCR_TUPLE_INT] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
4646
[BINARY_SUBSCR_DICT] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
4747
[BINARY_SUBSCR_GETITEM] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
48-
[LIST_APPEND] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
49-
[SET_ADD] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
48+
[LIST_APPEND] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
49+
[SET_ADD] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
5050
[STORE_SUBSCR] = { 3, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
5151
[STORE_SUBSCR_LIST_INT] = { 3, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
5252
[STORE_SUBSCR_DICT] = { 3, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
@@ -92,8 +92,8 @@ static const struct {
9292
[BUILD_STRING] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
9393
[BUILD_TUPLE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
9494
[BUILD_LIST] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
95-
[LIST_EXTEND] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
96-
[SET_UPDATE] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
95+
[LIST_EXTEND] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
96+
[SET_UPDATE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
9797
[BUILD_SET] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
9898
[BUILD_MAP] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
9999
[SETUP_ANNOTATIONS] = { 0, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },

0 commit comments

Comments
 (0)