Skip to content

Commit 044cce2

Browse files
committed
Put limited RESUME at start of genexpr for free-threading. Fix up exception handling in genexpr
1 parent b927de4 commit 044cce2

File tree

8 files changed

+27
-12
lines changed

8 files changed

+27
-12
lines changed

Include/internal/pycore_magic_number.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ Known values:
294294
Python 3.15a4 3661 (Lazy imports IMPORT_NAME opcode changes)
295295
Python 3.15a8 3662 (Add counter to RESUME)
296296
Python 3.15a8 3663 (Merge GET_ITER and GET_YIELD_FROM_ITER. Modify SEND to make it a bit more like FOR_ITER)
297-
Python 3.15a8 3664 (Add FOR_ITER_VIRTUAL and GET_ITER specializations)
297+
Python 3.15a8 3665 (Add FOR_ITER_VIRTUAL and GET_ITER specializations)
298298
299299
300300
Python 3.16 will start with 3700
@@ -308,7 +308,7 @@ PC/launcher.c must also be updated.
308308
309309
*/
310310

311-
#define PYC_MAGIC_NUMBER 3664
311+
#define PYC_MAGIC_NUMBER 3665
312312
/* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes
313313
(little-endian) and then appending b'\r\n'. */
314314
#define PYC_MAGIC_NUMBER_TOKEN \

Include/internal/pycore_opcode_utils.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,10 @@ extern "C" {
8282
#define RESUME_AFTER_YIELD 1
8383
#define RESUME_AFTER_YIELD_FROM 2
8484
#define RESUME_AFTER_AWAIT 3
85+
#define RESUME_AT_GEN_EXPR_START 4
8586

86-
#define RESUME_OPARG_LOCATION_MASK 0x3
87-
#define RESUME_OPARG_DEPTH1_MASK 0x4
87+
#define RESUME_OPARG_LOCATION_MASK 0x7
88+
#define RESUME_OPARG_DEPTH1_MASK 0x8
8889

8990
#define GET_ITER_YIELD_FROM 1
9091
#define GET_ITER_YIELD_FROM_NO_CHECK 2

Objects/codeobject.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -574,8 +574,12 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
574574
co->co_tlbc->entries[0] = co->co_code_adaptive;
575575
#endif
576576
int entry_point = 0;
577-
while (entry_point < Py_SIZE(co) &&
578-
_PyCode_CODE(co)[entry_point].op.code != RESUME) {
577+
while (entry_point < Py_SIZE(co)) {
578+
if (_PyCode_CODE(co)[entry_point].op.code == RESUME &&
579+
(_PyCode_CODE(co)[entry_point].op.arg & RESUME_OPARG_LOCATION_MASK) != RESUME_AT_GEN_EXPR_START
580+
) {
581+
break;
582+
}
579583
entry_point++;
580584
}
581585
co->_co_firsttraceable = entry_point;

Python/bytecodes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ dummy_func(
199199
}
200200
}
201201

202-
op(_LOAD_BYTECODE, (--)) {
202+
replaced op(_LOAD_BYTECODE, (--)) {
203203
#ifdef Py_GIL_DISABLED
204204
if (frame->tlbc_index !=
205205
((_PyThreadStateImpl *)tstate)->tlbc_index) {

Python/codegen.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,12 +1224,17 @@ codegen_wrap_in_stopiteration_handler(compiler *c)
12241224
{
12251225
NEW_JUMP_TARGET_LABEL(c, handler);
12261226

1227-
/* Insert SETUP_CLEANUP just before RESUME */
1227+
/* Insert SETUP_CLEANUP just after the initial RETURN_GENERATOR; POP_TOP */
12281228
instr_sequence *seq = INSTR_SEQUENCE(c);
12291229
int resume = 0;
1230-
while (_PyInstructionSequence_GetInstruction(seq, resume).i_opcode != RESUME) {
1230+
while (_PyInstructionSequence_GetInstruction(seq, resume).i_opcode != RETURN_GENERATOR) {
12311231
resume++;
1232+
assert(resume < seq->s_used);
12321233
}
1234+
resume++;
1235+
assert(_PyInstructionSequence_GetInstruction(seq, resume).i_opcode == POP_TOP);
1236+
resume++;
1237+
assert(resume < seq->s_used);
12331238
RETURN_IF_ERROR(
12341239
_PyInstructionSequence_InsertInstruction(
12351240
seq, resume,
@@ -4977,10 +4982,14 @@ codegen_comprehension(compiler *c, expr_ty e, int type,
49774982
RETURN_IF_ERROR(
49784983
_PyInstructionSequence_InsertInstruction(
49794984
INSTR_SEQUENCE(c), 0,
4980-
LOAD_FAST, 0, LOC(outermost->iter)));
4985+
RESUME, RESUME_AT_GEN_EXPR_START, NO_LOCATION));
49814986
RETURN_IF_ERROR(
49824987
_PyInstructionSequence_InsertInstruction(
49834988
INSTR_SEQUENCE(c), 1,
4989+
LOAD_FAST, 0, LOC(outermost->iter)));
4990+
RETURN_IF_ERROR(
4991+
_PyInstructionSequence_InsertInstruction(
4992+
INSTR_SEQUENCE(c), 2,
49844993
outermost->is_async ? GET_AITER : GET_ITER,
49854994
0, LOC(outermost->iter)));
49864995
iter_state = ITERATOR_ON_STACK;

Python/executor_cases.c.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/flowgraph.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,7 @@ label_exception_targets(basicblock *entryblock) {
963963
}
964964
else if (instr->i_opcode == RESUME) {
965965
instr->i_except = handler;
966-
if (instr->i_oparg != RESUME_AT_FUNC_START) {
966+
if (instr->i_oparg != RESUME_AT_FUNC_START && instr->i_oparg != RESUME_AT_GEN_EXPR_START) {
967967
assert(last_yield_except_depth >= 0);
968968
if (last_yield_except_depth == 1) {
969969
instr->i_oparg |= RESUME_OPARG_DEPTH1_MASK;

Python/optimizer.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ _PyUOp_Replacements[MAX_UOP_ID + 1] = {
499499
[_FOR_ITER_VIRTUAL] = _FOR_ITER_VIRTUAL_TIER_TWO,
500500
[_ITER_NEXT_LIST] = _ITER_NEXT_LIST_TIER_TWO,
501501
[_CHECK_PERIODIC_AT_END] = _TIER2_RESUME_CHECK,
502+
[_LOAD_BYTECODE] = _NOP,
502503
};
503504

504505
static const uint8_t

0 commit comments

Comments
 (0)