Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3a6f48d
Add FOR_ITER specialization for virtual iterators. Specialize GET_ITER.
markshannon Mar 17, 2026
74b5289
Document new tp_iteritem function slot.
markshannon Apr 1, 2026
4dd6992
Simplify list_iteritem
markshannon Apr 1, 2026
4376246
Make it clearer to MSVC that variable doesn't escape
markshannon Apr 2, 2026
5a81e54
Return a small struct in tp_iteritem to support MSVC tailcalling
markshannon Apr 2, 2026
b927de4
Fix editing slip
markshannon Apr 2, 2026
044cce2
Put limited RESUME at start of genexpr for free-threading. Fix up exc…
markshannon Apr 7, 2026
4ba6ecd
Merge branch 'main' into specialize-iteration-with-jit
markshannon Apr 7, 2026
b08dce2
Merge branch 'main' into specialize-iteration-with-jit
markshannon Apr 8, 2026
830068c
Fix test_dis
markshannon Apr 8, 2026
931084a
Merge branch 'main' into specialize-iteration-with-jit
markshannon Apr 9, 2026
87215d5
Merge branch 'main' into specialize-iteration-with-jit
markshannon Apr 9, 2026
73b9b87
Fix magic number
markshannon Apr 9, 2026
fdef628
Address review comments
markshannon Apr 13, 2026
b8baca5
Merge branch 'main' into specialize-iteration-with-jit
markshannon Apr 13, 2026
b3dc340
Make struct private
markshannon Apr 13, 2026
1c269b6
Try to keep sphinx happy
markshannon Apr 14, 2026
09ecaef
Declare tp_iteritem and iteritemfunc private by adding _ prefix to names
markshannon Apr 14, 2026
92a3a97
Merge branch 'main' into specialize-iteration-with-jit
markshannon Apr 15, 2026
a55ac63
Address code review: Remove struct tag
markshannon Apr 15, 2026
6406871
Merge branch 'main' into specialize-iteration-with-jit
markshannon Apr 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Put limited RESUME at start of genexpr for free-threading. Fix up exc…
…eption handling in genexpr
  • Loading branch information
markshannon committed Apr 7, 2026
commit 044cce2285f08634ec4786fffdae26f23b745da9
4 changes: 2 additions & 2 deletions Include/internal/pycore_magic_number.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ Known values:
Python 3.15a4 3661 (Lazy imports IMPORT_NAME opcode changes)
Python 3.15a8 3662 (Add counter to RESUME)
Python 3.15a8 3663 (Merge GET_ITER and GET_YIELD_FROM_ITER. Modify SEND to make it a bit more like FOR_ITER)
Python 3.15a8 3664 (Add FOR_ITER_VIRTUAL and GET_ITER specializations)
Python 3.15a8 3665 (Add FOR_ITER_VIRTUAL and GET_ITER specializations)


Python 3.16 will start with 3700
Expand All @@ -308,7 +308,7 @@ PC/launcher.c must also be updated.

*/

#define PYC_MAGIC_NUMBER 3664
#define PYC_MAGIC_NUMBER 3665
/* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes
(little-endian) and then appending b'\r\n'. */
#define PYC_MAGIC_NUMBER_TOKEN \
Expand Down
5 changes: 3 additions & 2 deletions Include/internal/pycore_opcode_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,10 @@ extern "C" {
#define RESUME_AFTER_YIELD 1
#define RESUME_AFTER_YIELD_FROM 2
#define RESUME_AFTER_AWAIT 3
#define RESUME_AT_GEN_EXPR_START 4

#define RESUME_OPARG_LOCATION_MASK 0x3
#define RESUME_OPARG_DEPTH1_MASK 0x4
#define RESUME_OPARG_LOCATION_MASK 0x7
#define RESUME_OPARG_DEPTH1_MASK 0x8

#define GET_ITER_YIELD_FROM 1
#define GET_ITER_YIELD_FROM_NO_CHECK 2
Expand Down
8 changes: 6 additions & 2 deletions Objects/codeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,8 +574,12 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
co->co_tlbc->entries[0] = co->co_code_adaptive;
#endif
int entry_point = 0;
while (entry_point < Py_SIZE(co) &&
_PyCode_CODE(co)[entry_point].op.code != RESUME) {
while (entry_point < Py_SIZE(co)) {
if (_PyCode_CODE(co)[entry_point].op.code == RESUME &&
(_PyCode_CODE(co)[entry_point].op.arg & RESUME_OPARG_LOCATION_MASK) != RESUME_AT_GEN_EXPR_START
) {
break;
}
entry_point++;
}
co->_co_firsttraceable = entry_point;
Expand Down
2 changes: 1 addition & 1 deletion Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ dummy_func(
}
}

op(_LOAD_BYTECODE, (--)) {
replaced op(_LOAD_BYTECODE, (--)) {
#ifdef Py_GIL_DISABLED
if (frame->tlbc_index !=
((_PyThreadStateImpl *)tstate)->tlbc_index) {
Expand Down
15 changes: 12 additions & 3 deletions Python/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -1224,12 +1224,17 @@ codegen_wrap_in_stopiteration_handler(compiler *c)
{
NEW_JUMP_TARGET_LABEL(c, handler);

/* Insert SETUP_CLEANUP just before RESUME */
/* Insert SETUP_CLEANUP just after the initial RETURN_GENERATOR; POP_TOP */
instr_sequence *seq = INSTR_SEQUENCE(c);
int resume = 0;
while (_PyInstructionSequence_GetInstruction(seq, resume).i_opcode != RESUME) {
while (_PyInstructionSequence_GetInstruction(seq, resume).i_opcode != RETURN_GENERATOR) {
resume++;
assert(resume < seq->s_used);
}
resume++;
assert(_PyInstructionSequence_GetInstruction(seq, resume).i_opcode == POP_TOP);
resume++;
assert(resume < seq->s_used);
RETURN_IF_ERROR(
_PyInstructionSequence_InsertInstruction(
seq, resume,
Expand Down Expand Up @@ -4977,10 +4982,14 @@ codegen_comprehension(compiler *c, expr_ty e, int type,
RETURN_IF_ERROR(
_PyInstructionSequence_InsertInstruction(
INSTR_SEQUENCE(c), 0,
LOAD_FAST, 0, LOC(outermost->iter)));
RESUME, RESUME_AT_GEN_EXPR_START, NO_LOCATION));
RETURN_IF_ERROR(
_PyInstructionSequence_InsertInstruction(
INSTR_SEQUENCE(c), 1,
LOAD_FAST, 0, LOC(outermost->iter)));
RETURN_IF_ERROR(
_PyInstructionSequence_InsertInstruction(
INSTR_SEQUENCE(c), 2,
outermost->is_async ? GET_AITER : GET_ITER,
0, LOC(outermost->iter)));
iter_state = ITERATOR_ON_STACK;
Expand Down
2 changes: 1 addition & 1 deletion Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Python/flowgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -963,7 +963,7 @@ label_exception_targets(basicblock *entryblock) {
}
else if (instr->i_opcode == RESUME) {
instr->i_except = handler;
if (instr->i_oparg != RESUME_AT_FUNC_START) {
if (instr->i_oparg != RESUME_AT_FUNC_START && instr->i_oparg != RESUME_AT_GEN_EXPR_START) {
assert(last_yield_except_depth >= 0);
if (last_yield_except_depth == 1) {
instr->i_oparg |= RESUME_OPARG_DEPTH1_MASK;
Expand Down
1 change: 1 addition & 0 deletions Python/optimizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ _PyUOp_Replacements[MAX_UOP_ID + 1] = {
[_FOR_ITER_VIRTUAL] = _FOR_ITER_VIRTUAL_TIER_TWO,
[_ITER_NEXT_LIST] = _ITER_NEXT_LIST_TIER_TWO,
[_CHECK_PERIODIC_AT_END] = _TIER2_RESUME_CHECK,
[_LOAD_BYTECODE] = _NOP,
};

static const uint8_t
Expand Down