Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b6cb435

Browse files
authored
gh-121404: split compiler's push/pop_inlined_comprehension_state into codegen and compiler parts (#123021)
1 parent 3950392 commit b6cb435

File tree

1 file changed

+102
-63
lines changed

1 file changed

+102
-63
lines changed

Python/compile.c

Lines changed: 102 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5371,38 +5371,28 @@ typedef struct {
53715371
PyObject *temp_symbols;
53725372
PyObject *fast_hidden;
53735373
jump_target_label cleanup;
5374-
jump_target_label end;
53755374
} inlined_comprehension_state;
53765375

53775376
static int
5378-
push_inlined_comprehension_state(struct compiler *c, location loc,
5379-
PySTEntryObject *entry,
5380-
inlined_comprehension_state *state)
5377+
compiler_tweak_inlined_comprehension_scopes(struct compiler *c, location loc,
5378+
PySTEntryObject *entry,
5379+
inlined_comprehension_state *state)
53815380
{
53825381
int in_class_block = (SYMTABLE_ENTRY(c)->ste_type == ClassBlock) && !c->u->u_in_inlined_comp;
53835382
c->u->u_in_inlined_comp++;
5384-
// iterate over names bound in the comprehension and ensure we isolate
5385-
// them from the outer scope as needed
5383+
53865384
PyObject *k, *v;
53875385
Py_ssize_t pos = 0;
53885386
while (PyDict_Next(entry->ste_symbols, &pos, &k, &v)) {
53895387
long symbol = PyLong_AsLong(v);
5390-
if (symbol == -1 && PyErr_Occurred()) {
5391-
return ERROR;
5392-
}
5388+
assert(symbol >= 0 || PyErr_Occurred());
5389+
RETURN_IF_ERROR(symbol);
53935390
long scope = SYMBOL_TO_SCOPE(symbol);
5394-
PyObject *outv = PyDict_GetItemWithError(SYMTABLE_ENTRY(c)->ste_symbols, k);
5395-
if (outv == NULL) {
5396-
if (PyErr_Occurred()) {
5397-
return ERROR;
5398-
}
5399-
outv = _PyLong_GetZero();
5400-
}
5401-
long outsymbol = PyLong_AsLong(outv);
5402-
if (outsymbol == -1 && PyErr_Occurred()) {
5403-
return ERROR;
5404-
}
5391+
5392+
long outsymbol = _PyST_GetSymbol(SYMTABLE_ENTRY(c), k);
5393+
RETURN_IF_ERROR(outsymbol);
54055394
long outsc = SYMBOL_TO_SCOPE(outsymbol);
5395+
54065396
// If a name has different scope inside than outside the comprehension,
54075397
// we need to temporarily handle it with the right scope while
54085398
// compiling the comprehension. If it's free in the comprehension
@@ -5422,16 +5412,16 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
54225412
// update the symbol to the in-comprehension version and save
54235413
// the outer version; we'll restore it after running the
54245414
// comprehension
5425-
Py_INCREF(outv);
54265415
if (PyDict_SetItem(SYMTABLE_ENTRY(c)->ste_symbols, k, v) < 0) {
5427-
Py_DECREF(outv);
54285416
return ERROR;
54295417
}
5430-
if (PyDict_SetItem(state->temp_symbols, k, outv) < 0) {
5431-
Py_DECREF(outv);
5418+
PyObject *outv = PyLong_FromLong(outsymbol);
5419+
if (outv == NULL) {
54325420
return ERROR;
54335421
}
5422+
int res = PyDict_SetItem(state->temp_symbols, k, outv);
54345423
Py_DECREF(outv);
5424+
RETURN_IF_ERROR(res);
54355425
}
54365426
// locals handling for names bound in comprehension (DEF_LOCAL |
54375427
// DEF_NONLOCAL occurs in assignment expression to nonlocal)
@@ -5442,9 +5432,8 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
54425432
if (PyDict_GetItemRef(c->u->u_metadata.u_fasthidden, k, &orig) < 0) {
54435433
return ERROR;
54445434
}
5445-
int orig_is_true = (orig == Py_True);
5446-
Py_XDECREF(orig);
5447-
if (!orig_is_true) {
5435+
assert(orig == NULL || orig == Py_True || orig == Py_False);
5436+
if (orig != Py_True) {
54485437
if (PyDict_SetItem(c->u->u_metadata.u_fasthidden, k, Py_True) < 0) {
54495438
return ERROR;
54505439
}
@@ -5459,6 +5448,33 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
54595448
}
54605449
}
54615450
}
5451+
}
5452+
}
5453+
return SUCCESS;
5454+
}
5455+
5456+
static int
5457+
codegen_push_inlined_comprehension_locals(struct compiler *c, location loc,
5458+
PySTEntryObject *comp,
5459+
inlined_comprehension_state *state)
5460+
{
5461+
int in_class_block = (SYMTABLE_ENTRY(c)->ste_type == ClassBlock) && !c->u->u_in_inlined_comp;
5462+
PySTEntryObject *outer = SYMTABLE_ENTRY(c);
5463+
// iterate over names bound in the comprehension and ensure we isolate
5464+
// them from the outer scope as needed
5465+
PyObject *k, *v;
5466+
Py_ssize_t pos = 0;
5467+
while (PyDict_Next(comp->ste_symbols, &pos, &k, &v)) {
5468+
long symbol = PyLong_AsLong(v);
5469+
assert(symbol >= 0 || PyErr_Occurred());
5470+
RETURN_IF_ERROR(symbol);
5471+
long scope = SYMBOL_TO_SCOPE(symbol);
5472+
5473+
long outsymbol = _PyST_GetSymbol(outer, k);
5474+
RETURN_IF_ERROR(outsymbol);
5475+
long outsc = SYMBOL_TO_SCOPE(outsymbol);
5476+
5477+
if ((symbol & DEF_LOCAL && !(symbol & DEF_NONLOCAL)) || in_class_block) {
54625478
// local names bound in comprehension must be isolated from
54635479
// outer scope; push existing value (which may be NULL if
54645480
// not defined) on stack
@@ -5496,31 +5512,40 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
54965512
// handler or finally block.
54975513
NEW_JUMP_TARGET_LABEL(c, cleanup);
54985514
state->cleanup = cleanup;
5499-
NEW_JUMP_TARGET_LABEL(c, end);
5500-
state->end = end;
55015515

55025516
// no need to push an fblock for this "virtual" try/finally; there can't
55035517
// be return/continue/break inside a comprehension
55045518
ADDOP_JUMP(c, loc, SETUP_FINALLY, cleanup);
55055519
}
5520+
return SUCCESS;
5521+
}
55065522

5523+
static int
5524+
push_inlined_comprehension_state(struct compiler *c, location loc,
5525+
PySTEntryObject *comp,
5526+
inlined_comprehension_state *state)
5527+
{
5528+
RETURN_IF_ERROR(
5529+
compiler_tweak_inlined_comprehension_scopes(c, loc, comp, state));
5530+
RETURN_IF_ERROR(
5531+
codegen_push_inlined_comprehension_locals(c, loc, comp, state));
55075532
return SUCCESS;
55085533
}
55095534

55105535
static int
55115536
restore_inlined_comprehension_locals(struct compiler *c, location loc,
5512-
inlined_comprehension_state state)
5537+
inlined_comprehension_state *state)
55135538
{
55145539
PyObject *k;
55155540
// pop names we pushed to stack earlier
5516-
Py_ssize_t npops = PyList_GET_SIZE(state.pushed_locals);
5541+
Py_ssize_t npops = PyList_GET_SIZE(state->pushed_locals);
55175542
// Preserve the comprehension result (or exception) as TOS. This
5518-
// reverses the SWAP we did in push_inlined_comprehension_state to get
5519-
// the outermost iterable to TOS, so we can still just iterate
5543+
// reverses the SWAP we did in push_inlined_comprehension_state
5544+
// to get the outermost iterable to TOS, so we can still just iterate
55205545
// pushed_locals in simple reverse order
55215546
ADDOP_I(c, loc, SWAP, npops + 1);
55225547
for (Py_ssize_t i = npops - 1; i >= 0; --i) {
5523-
k = PyList_GetItem(state.pushed_locals, i);
5548+
k = PyList_GetItem(state->pushed_locals, i);
55245549
if (k == NULL) {
55255550
return ERROR;
55265551
}
@@ -5530,43 +5555,47 @@ restore_inlined_comprehension_locals(struct compiler *c, location loc,
55305555
}
55315556

55325557
static int
5533-
pop_inlined_comprehension_state(struct compiler *c, location loc,
5534-
inlined_comprehension_state state)
5558+
codegen_pop_inlined_comprehension_locals(struct compiler *c, location loc,
5559+
inlined_comprehension_state *state)
55355560
{
5536-
c->u->u_in_inlined_comp--;
5537-
PyObject *k, *v;
5538-
Py_ssize_t pos = 0;
5539-
if (state.temp_symbols) {
5540-
while (PyDict_Next(state.temp_symbols, &pos, &k, &v)) {
5541-
if (PyDict_SetItem(SYMTABLE_ENTRY(c)->ste_symbols, k, v)) {
5542-
return ERROR;
5543-
}
5544-
}
5545-
Py_CLEAR(state.temp_symbols);
5546-
}
5547-
if (state.pushed_locals) {
5561+
if (state->pushed_locals) {
55485562
ADDOP(c, NO_LOCATION, POP_BLOCK);
5549-
ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, state.end);
5563+
5564+
NEW_JUMP_TARGET_LABEL(c, end);
5565+
ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, end);
55505566

55515567
// cleanup from an exception inside the comprehension
5552-
USE_LABEL(c, state.cleanup);
5568+
USE_LABEL(c, state->cleanup);
55535569
// discard incomplete comprehension result (beneath exc on stack)
55545570
ADDOP_I(c, NO_LOCATION, SWAP, 2);
55555571
ADDOP(c, NO_LOCATION, POP_TOP);
5556-
if (restore_inlined_comprehension_locals(c, loc, state) < 0) {
5557-
return ERROR;
5558-
}
5572+
RETURN_IF_ERROR(restore_inlined_comprehension_locals(c, loc, state));
55595573
ADDOP_I(c, NO_LOCATION, RERAISE, 0);
55605574

5561-
USE_LABEL(c, state.end);
5562-
if (restore_inlined_comprehension_locals(c, loc, state) < 0) {
5563-
return ERROR;
5575+
USE_LABEL(c, end);
5576+
RETURN_IF_ERROR(restore_inlined_comprehension_locals(c, loc, state));
5577+
Py_CLEAR(state->pushed_locals);
5578+
}
5579+
return SUCCESS;
5580+
}
5581+
5582+
static int
5583+
compiler_revert_inlined_comprehension_scopes(struct compiler *c, location loc,
5584+
inlined_comprehension_state *state)
5585+
{
5586+
if (state->temp_symbols) {
5587+
PyObject *k, *v;
5588+
Py_ssize_t pos = 0;
5589+
while (PyDict_Next(state->temp_symbols, &pos, &k, &v)) {
5590+
if (PyDict_SetItem(SYMTABLE_ENTRY(c)->ste_symbols, k, v)) {
5591+
return ERROR;
5592+
}
55645593
}
5565-
Py_CLEAR(state.pushed_locals);
5594+
Py_CLEAR(state->temp_symbols);
55665595
}
5567-
if (state.fast_hidden) {
5568-
while (PySet_Size(state.fast_hidden) > 0) {
5569-
PyObject *k = PySet_Pop(state.fast_hidden);
5596+
if (state->fast_hidden) {
5597+
while (PySet_Size(state->fast_hidden) > 0) {
5598+
PyObject *k = PySet_Pop(state->fast_hidden);
55705599
if (k == NULL) {
55715600
return ERROR;
55725601
}
@@ -5578,11 +5607,21 @@ pop_inlined_comprehension_state(struct compiler *c, location loc,
55785607
}
55795608
Py_DECREF(k);
55805609
}
5581-
Py_CLEAR(state.fast_hidden);
5610+
Py_CLEAR(state->fast_hidden);
55825611
}
55835612
return SUCCESS;
55845613
}
55855614

5615+
static int
5616+
pop_inlined_comprehension_state(struct compiler *c, location loc,
5617+
inlined_comprehension_state *state)
5618+
{
5619+
c->u->u_in_inlined_comp--;
5620+
RETURN_IF_ERROR(codegen_pop_inlined_comprehension_locals(c, loc, state));
5621+
RETURN_IF_ERROR(compiler_revert_inlined_comprehension_scopes(c, loc, state));
5622+
return SUCCESS;
5623+
}
5624+
55865625
static inline int
55875626
compiler_comprehension_iter(struct compiler *c, location loc,
55885627
comprehension_ty comp)
@@ -5603,7 +5642,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
56035642
expr_ty val)
56045643
{
56055644
PyCodeObject *co = NULL;
5606-
inlined_comprehension_state inline_state = {NULL, NULL, NULL, NO_LABEL, NO_LABEL};
5645+
inlined_comprehension_state inline_state = {NULL, NULL, NULL, NO_LABEL};
56075646
comprehension_ty outermost;
56085647
#ifndef NDEBUG
56095648
int scope_type = c->u->u_scope_type;
@@ -5671,7 +5710,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
56715710
}
56725711

56735712
if (is_inlined) {
5674-
if (pop_inlined_comprehension_state(c, loc, inline_state)) {
5713+
if (pop_inlined_comprehension_state(c, loc, &inline_state)) {
56755714
goto error;
56765715
}
56775716
return SUCCESS;

0 commit comments

Comments
 (0)