From 78a7dddc20634d987a9520854956f9f8e0290252 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Tue, 20 Jan 2026 03:33:44 +0900 Subject: [PATCH 1/4] Align ForIter behavior (incomplete) --- crates/codegen/src/compile.rs | 5 +++++ crates/compiler-core/src/bytecode/instruction.rs | 8 +++----- crates/vm/src/frame.rs | 8 +++----- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/crates/codegen/src/compile.rs b/crates/codegen/src/compile.rs index a72e425e290..c41c2584523 100644 --- a/crates/codegen/src/compile.rs +++ b/crates/codegen/src/compile.rs @@ -4929,6 +4929,9 @@ impl Compiler { if is_async { emit!(self, Instruction::EndAsyncFor); + } else { + // Pop the iterator after loop ends + emit!(self, Instruction::PopTop); } self.compile_statements(orelse)?; @@ -7367,6 +7370,8 @@ impl Compiler { if is_async { emit!(self, Instruction::EndAsyncFor); emit!(self, Instruction::PopTop); + } else { + emit!(self, Instruction::PopTop); } } diff --git a/crates/compiler-core/src/bytecode/instruction.rs b/crates/compiler-core/src/bytecode/instruction.rs index 41f86dca39b..040e46a5d89 100644 --- a/crates/compiler-core/src/bytecode/instruction.rs +++ b/crates/compiler-core/src/bytecode/instruction.rs @@ -584,11 +584,9 @@ impl InstructionMetadata for Instruction { Self::FormatSimple => 0, Self::FormatWithSpec => -1, Self::ForIter { .. } => { - if jump { - -1 - } else { - 1 - } + // jump=False: push next value (+1) + // jump=True: iterator stays on stack, no change (0) + if jump { 0 } else { 1 } } Self::IsOp(_) => -1, Self::ContainsOp(_) => -1, diff --git a/crates/vm/src/frame.rs b/crates/vm/src/frame.rs index ea9177a3d7c..f6faf6f49cb 100644 --- a/crates/vm/src/frame.rs +++ b/crates/vm/src/frame.rs @@ -2380,15 +2380,13 @@ impl ExecutingFrame<'_> { Ok(None) } Ok(PyIterReturn::StopIteration(_)) => { - // Pop iterator from stack: - self.pop_value(); - - // End of for loop + // CPython 3.14: Do NOT pop iterator here + // POP_ITER instruction will handle cleanup after the loop self.jump(target); Ok(None) } Err(next_error) => { - // Pop iterator from stack: + // On error, pop iterator and propagate self.pop_value(); Err(next_error) } From d1f15f90883d6559eb9e8175885f2f490cabb911 Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Tue, 20 Jan 2026 10:53:47 +0900 Subject: [PATCH 2/4] Romove JUMP_IF_{TRUE,FALSE}_OR_POP, subscript --- Lib/_opcode_metadata.py | 3 -- crates/codegen/src/compile.rs | 11 ++---- .../compiler-core/src/bytecode/instruction.rs | 34 ------------------- crates/stdlib/src/opcode.rs | 2 -- crates/vm/src/frame.rs | 32 ----------------- 5 files changed, 3 insertions(+), 79 deletions(-) diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py index 3345870e4ec..2b18ad4d652 100644 --- a/Lib/_opcode_metadata.py +++ b/Lib/_opcode_metadata.py @@ -218,13 +218,10 @@ 'BUILD_CONST_KEY_MAP': 215, 'BREAK': 216, 'CONTINUE': 217, - 'JUMP_IF_FALSE_OR_POP': 218, - 'JUMP_IF_TRUE_OR_POP': 219, 'JUMP_IF_NOT_EXC_MATCH': 220, 'LOAD_ASSERTION_ERROR': 221, 'RETURN_CONST': 222, 'SET_EXC_INFO': 223, - 'SUBSCRIPT': 224, 'INSTRUMENTED_END_FOR': 234, 'INSTRUMENTED_POP_ITER': 235, 'INSTRUMENTED_END_SEND': 236, diff --git a/crates/codegen/src/compile.rs b/crates/codegen/src/compile.rs index c41c2584523..93a759c7ff4 100644 --- a/crates/codegen/src/compile.rs +++ b/crates/codegen/src/compile.rs @@ -489,7 +489,7 @@ impl Compiler { match ctx { ast::ExprContext::Load => { emit!(self, Instruction::BuildSlice { argc }); - emit!(self, Instruction::Subscript); + emit!(self, Instruction::BinarySubscr); } ast::ExprContext::Store => { emit!(self, Instruction::BuildSlice { argc }); @@ -503,7 +503,7 @@ impl Compiler { // Emit appropriate instruction based on context match ctx { - ast::ExprContext::Load => emit!(self, Instruction::Subscript), + ast::ExprContext::Load => emit!(self, Instruction::BinarySubscr), ast::ExprContext::Store => emit!(self, Instruction::StoreSubscr), ast::ExprContext::Del => emit!(self, Instruction::DeleteSubscr), ast::ExprContext::Invalid => { @@ -5990,14 +5990,9 @@ impl Compiler { self.compile_addcompare(op); // if comparison result is false, we break with this value; if true, try the next one. - /* emit!(self, Instruction::Copy { index: 1 }); - // emit!(self, Instruction::ToBool); // TODO: Uncomment this emit!(self, Instruction::PopJumpIfFalse { target: cleanup }); emit!(self, Instruction::PopTop); - */ - - emit!(self, Instruction::JumpIfFalseOrPop { target: cleanup }); } self.compile_expression(last_comparator)?; @@ -6208,7 +6203,7 @@ impl Compiler { self.compile_expression(slice)?; emit!(self, Instruction::Copy { index: 2_u32 }); emit!(self, Instruction::Copy { index: 2_u32 }); - emit!(self, Instruction::Subscript); + emit!(self, Instruction::BinarySubscr); AugAssignKind::Subscript } ast::Expr::Attribute(ast::ExprAttribute { value, attr, .. }) => { diff --git a/crates/compiler-core/src/bytecode/instruction.rs b/crates/compiler-core/src/bytecode/instruction.rs index 040e46a5d89..d861b91300a 100644 --- a/crates/compiler-core/src/bytecode/instruction.rs +++ b/crates/compiler-core/src/bytecode/instruction.rs @@ -272,19 +272,12 @@ pub enum Instruction { Continue { target: Arg