Skip to content

Commit c579243

Browse files
authored
bpo-46808: remove NEXT_BLOCK() from compile.c (GH-31448)
1 parent 0f41aac commit c579243

File tree

2 files changed

+73
-63
lines changed

2 files changed

+73
-63
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Remove the ``NEXT_BLOCK`` macro from compile.c, and make the compiler automatically generate implicit blocks when they are needed.

Python/compile.c

Lines changed: 72 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,9 @@ struct compiler_unit {
268268
int u_col_offset; /* the offset of the current stmt */
269269
int u_end_lineno; /* the end line of the current stmt */
270270
int u_end_col_offset; /* the end offset of the current stmt */
271+
272+
/* true if we need to create an implicit basicblock before the next instr */
273+
int u_need_new_implicit_block;
271274
};
272275

273276
/* This struct captures the global state of a compilation.
@@ -757,23 +760,13 @@ compiler_new_block(struct compiler *c)
757760
return b;
758761
}
759762

760-
static basicblock *
761-
compiler_next_block(struct compiler *c)
762-
{
763-
basicblock *block = compiler_new_block(c);
764-
if (block == NULL)
765-
return NULL;
766-
c->u->u_curblock->b_next = block;
767-
c->u->u_curblock = block;
768-
return block;
769-
}
770-
771763
static basicblock *
772764
compiler_use_next_block(struct compiler *c, basicblock *block)
773765
{
774766
assert(block != NULL);
775767
c->u->u_curblock->b_next = block;
776768
c->u->u_curblock = block;
769+
c->u->u_need_new_implicit_block = 0;
777770
return block;
778771
}
779772

@@ -1141,6 +1134,37 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
11411134
return stack_effect(opcode, oparg, -1);
11421135
}
11431136

1137+
static int is_end_of_basic_block(struct instr *instr)
1138+
{
1139+
int opcode = instr->i_opcode;
1140+
1141+
return is_jump(instr) ||
1142+
opcode == RETURN_VALUE ||
1143+
opcode == RAISE_VARARGS ||
1144+
opcode == RERAISE;
1145+
}
1146+
1147+
static int
1148+
compiler_use_new_implicit_block_if_needed(struct compiler *c)
1149+
{
1150+
if (c->u->u_need_new_implicit_block) {
1151+
basicblock *b = compiler_new_block(c);
1152+
if (b == NULL) {
1153+
return -1;
1154+
}
1155+
compiler_use_next_block(c, b);
1156+
}
1157+
return 0;
1158+
}
1159+
1160+
static void
1161+
compiler_check_if_end_of_block(struct compiler *c, struct instr *instr)
1162+
{
1163+
if (is_end_of_basic_block(instr)) {
1164+
c->u->u_need_new_implicit_block = 1;
1165+
}
1166+
}
1167+
11441168
/* Add an opcode with no argument.
11451169
Returns 0 on failure, 1 on success.
11461170
*/
@@ -1149,23 +1173,29 @@ static int
11491173
compiler_addop_line(struct compiler *c, int opcode, int line,
11501174
int end_line, int col_offset, int end_col_offset)
11511175
{
1152-
basicblock *b;
1153-
struct instr *i;
1154-
int off;
11551176
assert(!HAS_ARG(opcode) || IS_ARTIFICIAL(opcode));
1156-
off = compiler_next_instr(c->u->u_curblock);
1157-
if (off < 0)
1177+
1178+
if (compiler_use_new_implicit_block_if_needed(c) < 0) {
1179+
return -1;
1180+
}
1181+
1182+
basicblock *b = c->u->u_curblock;
1183+
int off = compiler_next_instr(b);
1184+
if (off < 0) {
11581185
return 0;
1159-
b = c->u->u_curblock;
1160-
i = &b->b_instr[off];
1186+
}
1187+
struct instr *i = &b->b_instr[off];
11611188
i->i_opcode = opcode;
11621189
i->i_oparg = 0;
1163-
if (opcode == RETURN_VALUE)
1190+
if (opcode == RETURN_VALUE) {
11641191
b->b_return = 1;
1192+
}
11651193
i->i_lineno = line;
11661194
i->i_end_lineno = end_line;
11671195
i->i_col_offset = col_offset;
11681196
i->i_end_col_offset = end_col_offset;
1197+
1198+
compiler_check_if_end_of_block(c, i);
11691199
return 1;
11701200
}
11711201

@@ -1377,29 +1407,35 @@ compiler_addop_i_line(struct compiler *c, int opcode, Py_ssize_t oparg,
13771407
int lineno, int end_lineno,
13781408
int col_offset, int end_col_offset)
13791409
{
1380-
struct instr *i;
1381-
int off;
1382-
13831410
/* oparg value is unsigned, but a signed C int is usually used to store
13841411
it in the C code (like Python/ceval.c).
13851412
13861413
Limit to 32-bit signed C int (rather than INT_MAX) for portability.
13871414
13881415
The argument of a concrete bytecode instruction is limited to 8-bit.
13891416
EXTENDED_ARG is used for 16, 24, and 32-bit arguments. */
1417+
13901418
assert(HAS_ARG(opcode));
13911419
assert(0 <= oparg && oparg <= 2147483647);
13921420

1393-
off = compiler_next_instr(c->u->u_curblock);
1394-
if (off < 0)
1421+
if (compiler_use_new_implicit_block_if_needed(c) < 0) {
1422+
return -1;
1423+
}
1424+
1425+
basicblock *b = c->u->u_curblock;
1426+
int off = compiler_next_instr(b);
1427+
if (off < 0) {
13951428
return 0;
1396-
i = &c->u->u_curblock->b_instr[off];
1429+
}
1430+
struct instr *i = &b->b_instr[off];
13971431
i->i_opcode = opcode;
13981432
i->i_oparg = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int);
13991433
i->i_lineno = lineno;
14001434
i->i_end_lineno = end_lineno;
14011435
i->i_col_offset = col_offset;
14021436
i->i_end_col_offset = end_col_offset;
1437+
1438+
compiler_check_if_end_of_block(c, i);
14031439
return 1;
14041440
}
14051441

@@ -1417,15 +1453,19 @@ compiler_addop_i_noline(struct compiler *c, int opcode, Py_ssize_t oparg)
14171453
return compiler_addop_i_line(c, opcode, oparg, -1, 0, 0, 0);
14181454
}
14191455

1420-
static int add_jump_to_block(basicblock *b, int opcode,
1456+
static int add_jump_to_block(struct compiler *c, int opcode,
14211457
int lineno, int end_lineno,
14221458
int col_offset, int end_col_offset,
14231459
basicblock *target)
14241460
{
14251461
assert(HAS_ARG(opcode));
1426-
assert(b != NULL);
14271462
assert(target != NULL);
14281463

1464+
if (compiler_use_new_implicit_block_if_needed(c) < 0) {
1465+
return -1;
1466+
}
1467+
1468+
basicblock *b = c->u->u_curblock;
14291469
int off = compiler_next_instr(b);
14301470
struct instr *i = &b->b_instr[off];
14311471
if (off < 0) {
@@ -1437,32 +1477,23 @@ static int add_jump_to_block(basicblock *b, int opcode,
14371477
i->i_end_lineno = end_lineno;
14381478
i->i_col_offset = col_offset;
14391479
i->i_end_col_offset = end_col_offset;
1480+
1481+
compiler_check_if_end_of_block(c, i);
14401482
return 1;
14411483
}
14421484

14431485
static int
14441486
compiler_addop_j(struct compiler *c, int opcode, basicblock *b)
14451487
{
1446-
return add_jump_to_block(c->u->u_curblock, opcode, c->u->u_lineno,
1488+
return add_jump_to_block(c, opcode, c->u->u_lineno,
14471489
c->u->u_end_lineno, c->u->u_col_offset,
14481490
c->u->u_end_col_offset, b);
14491491
}
14501492

14511493
static int
14521494
compiler_addop_j_noline(struct compiler *c, int opcode, basicblock *b)
14531495
{
1454-
return add_jump_to_block(c->u->u_curblock, opcode, -1, 0, 0, 0, b);
1455-
}
1456-
1457-
/* NEXT_BLOCK() creates an implicit jump from the current block
1458-
to the new block.
1459-
1460-
The returns inside this macro make it impossible to decref objects
1461-
created in the local function. Local objects should use the arena.
1462-
*/
1463-
#define NEXT_BLOCK(C) { \
1464-
if (compiler_next_block((C)) == NULL) \
1465-
return 0; \
1496+
return add_jump_to_block(c, opcode, -1, 0, 0, 0, b);
14661497
}
14671498

14681499
#define ADDOP(C, OP) { \
@@ -2823,12 +2854,10 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
28232854
ADDOP_I(c, COPY, 2);
28242855
ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i));
28252856
ADDOP_JUMP(c, POP_JUMP_IF_FALSE, cleanup);
2826-
NEXT_BLOCK(c);
28272857
}
28282858
VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n));
28292859
ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, n));
28302860
ADDOP_JUMP(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next);
2831-
NEXT_BLOCK(c);
28322861
basicblock *end = compiler_new_block(c);
28332862
if (end == NULL)
28342863
return 0;
@@ -2852,7 +2881,6 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
28522881
/* general implementation */
28532882
VISIT(c, expr, e);
28542883
ADDOP_JUMP(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next);
2855-
NEXT_BLOCK(c);
28562884
return 1;
28572885
}
28582886

@@ -3128,7 +3156,6 @@ compiler_return(struct compiler *c, stmt_ty s)
31283156
ADDOP_LOAD_CONST(c, s->v.Return.value->v.Constant.value);
31293157
}
31303158
ADDOP(c, RETURN_VALUE);
3131-
NEXT_BLOCK(c);
31323159

31333160
return 1;
31343161
}
@@ -3149,7 +3176,6 @@ compiler_break(struct compiler *c)
31493176
return 0;
31503177
}
31513178
ADDOP_JUMP(c, JUMP_ABSOLUTE, loop->fb_exit);
3152-
NEXT_BLOCK(c);
31533179
return 1;
31543180
}
31553181

@@ -3166,7 +3192,6 @@ compiler_continue(struct compiler *c)
31663192
return compiler_error(c, "'continue' not properly in loop");
31673193
}
31683194
ADDOP_JUMP(c, JUMP_ABSOLUTE, loop->fb_block);
3169-
NEXT_BLOCK(c)
31703195
return 1;
31713196
}
31723197

@@ -3348,7 +3373,6 @@ compiler_try_except(struct compiler *c, stmt_ty s)
33483373
compiler_pop_fblock(c, TRY_EXCEPT, body);
33493374
ADDOP_NOLINE(c, POP_BLOCK);
33503375
if (s->v.Try.orelse && asdl_seq_LEN(s->v.Try.orelse)) {
3351-
NEXT_BLOCK(c);
33523376
VISIT_SEQ(c, stmt, s->v.Try.orelse);
33533377
}
33543378
ADDOP_JUMP_NOLINE(c, JUMP_FORWARD, end);
@@ -3374,7 +3398,6 @@ compiler_try_except(struct compiler *c, stmt_ty s)
33743398
if (handler->v.ExceptHandler.type) {
33753399
VISIT(c, expr, handler->v.ExceptHandler.type);
33763400
ADDOP_JUMP(c, JUMP_IF_NOT_EXC_MATCH, except);
3377-
NEXT_BLOCK(c);
33783401
}
33793402
if (handler->v.ExceptHandler.name) {
33803403
basicblock *cleanup_end, *cleanup_body;
@@ -3580,7 +3603,6 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
35803603
if (handler->v.ExceptHandler.type) {
35813604
VISIT(c, expr, handler->v.ExceptHandler.type);
35823605
ADDOP_JUMP(c, JUMP_IF_NOT_EG_MATCH, except);
3583-
NEXT_BLOCK(c);
35843606
}
35853607

35863608
basicblock *cleanup_end = compiler_new_block(c);
@@ -3665,7 +3687,6 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
36653687
ADDOP(c, PREP_RERAISE_STAR);
36663688
ADDOP_I(c, COPY, 1);
36673689
ADDOP_JUMP(c, POP_JUMP_IF_NOT_NONE, reraise);
3668-
NEXT_BLOCK(c);
36693690

36703691
/* Nothing to reraise */
36713692
ADDOP(c, POP_TOP);
@@ -3957,7 +3978,6 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
39573978
}
39583979
}
39593980
ADDOP_I(c, RAISE_VARARGS, (int)n);
3960-
NEXT_BLOCK(c);
39613981
break;
39623982
case Try_kind:
39633983
return compiler_try(c, s);
@@ -4503,7 +4523,6 @@ compiler_compare(struct compiler *c, expr_ty e)
45034523
ADDOP_I(c, COPY, 2);
45044524
ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i));
45054525
ADDOP_JUMP(c, JUMP_IF_FALSE_OR_POP, cleanup);
4506-
NEXT_BLOCK(c);
45074526
}
45084527
VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n));
45094528
ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, n));
@@ -5093,7 +5112,6 @@ compiler_sync_comprehension_generator(struct compiler *c,
50935112
depth++;
50945113
compiler_use_next_block(c, start);
50955114
ADDOP_JUMP(c, FOR_ITER, anchor);
5096-
NEXT_BLOCK(c);
50975115
}
50985116
VISIT(c, expr, gen->target);
50995117

@@ -5103,7 +5121,6 @@ compiler_sync_comprehension_generator(struct compiler *c,
51035121
expr_ty e = (expr_ty)asdl_seq_GET(gen->ifs, i);
51045122
if (!compiler_jump_if(c, e, if_cleanup, 0))
51055123
return 0;
5106-
NEXT_BLOCK(c);
51075124
}
51085125

51095126
if (++gen_index < asdl_seq_LEN(generators))
@@ -5198,7 +5215,6 @@ compiler_async_comprehension_generator(struct compiler *c,
51985215
expr_ty e = (expr_ty)asdl_seq_GET(gen->ifs, i);
51995216
if (!compiler_jump_if(c, e, if_cleanup, 0))
52005217
return 0;
5201-
NEXT_BLOCK(c);
52025218
}
52035219

52045220
depth++;
@@ -5410,7 +5426,6 @@ compiler_with_except_finish(struct compiler *c, basicblock * cleanup) {
54105426
if (exit == NULL)
54115427
return 0;
54125428
ADDOP_JUMP(c, POP_JUMP_IF_TRUE, exit);
5413-
NEXT_BLOCK(c);
54145429
ADDOP_I(c, RERAISE, 2);
54155430
compiler_use_next_block(c, cleanup);
54165431
POP_EXCEPT_AND_RERAISE(c);
@@ -6149,7 +6164,6 @@ jump_to_fail_pop(struct compiler *c, pattern_context *pc, int op)
61496164
Py_ssize_t pops = pc->on_top + PyList_GET_SIZE(pc->stores);
61506165
RETURN_IF_FALSE(ensure_fail_pop(c, pc, pops));
61516166
ADDOP_JUMP(c, op, pc->fail_pop[pops]);
6152-
NEXT_BLOCK(c);
61536167
return 1;
61546168
}
61556169

@@ -6159,7 +6173,6 @@ emit_and_reset_fail_pop(struct compiler *c, pattern_context *pc)
61596173
{
61606174
if (!pc->fail_pop_size) {
61616175
assert(pc->fail_pop == NULL);
6162-
NEXT_BLOCK(c);
61636176
return 1;
61646177
}
61656178
while (--pc->fail_pop_size) {
@@ -6662,7 +6675,6 @@ compiler_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc)
66626675
}
66636676
assert(control);
66646677
if (!compiler_addop_j(c, JUMP_FORWARD, end) ||
6665-
!compiler_next_block(c) ||
66666678
!emit_and_reset_fail_pop(c, pc))
66676679
{
66686680
goto error;
@@ -8136,10 +8148,7 @@ assemble(struct compiler *c, int addNone)
81368148
PyCodeObject *co = NULL;
81378149
PyObject *consts = NULL;
81388150

8139-
/* Make sure every block that falls off the end returns None.
8140-
XXX NEXT_BLOCK() isn't quite right, because if the last
8141-
block ends with a jump or return b_next shouldn't set.
8142-
*/
8151+
/* Make sure every block that falls off the end returns None. */
81438152
if (!c->u->u_curblock->b_return) {
81448153
UNSET_LOC(c);
81458154
if (addNone)

0 commit comments

Comments
 (0)