mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Remove SUBSCRIPT, JUMP_IF_{TRUE,FALSE}_OR_POP (#6810)
* Align ForIter behavior (incomplete)
* Romove JUMP_IF_{TRUE,FALSE}_OR_POP, subscript
* Remove LoadAssetionError
* Update snapshot for ForIter behavior change
This commit is contained in:
4
Lib/_opcode_metadata.py
vendored
4
Lib/_opcode_metadata.py
vendored
@@ -218,13 +218,9 @@ opmap = {
|
||||
'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,
|
||||
|
||||
@@ -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 => {
|
||||
@@ -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)?;
|
||||
|
||||
@@ -5987,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)?;
|
||||
@@ -6205,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, .. }) => {
|
||||
@@ -7367,6 +7365,8 @@ impl Compiler {
|
||||
if is_async {
|
||||
emit!(self, Instruction::EndAsyncFor);
|
||||
emit!(self, Instruction::PopTop);
|
||||
} else {
|
||||
emit!(self, Instruction::PopTop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
---
|
||||
source: crates/codegen/src/compile.rs
|
||||
assertion_line: 8626
|
||||
expression: "compile_exec(\"\\\nasync def test():\n for stop_exc in (StopIteration('spam'), StopAsyncIteration('ham')):\n with self.subTest(type=type(stop_exc)):\n try:\n async with egg():\n raise stop_exc\n except Exception as ex:\n self.assertIs(ex, stop_exc)\n else:\n self.fail(f'{stop_exc} was suppressed')\n\")"
|
||||
---
|
||||
3 0 LOAD_CONST (<code object test at ??? file "source_path", line 1>): 1 0 RESUME (0)
|
||||
@@ -140,7 +141,8 @@ expression: "compile_exec(\"\\\nasync def test():\n for stop_exc in (StopIter
|
||||
126 POP_EXCEPT
|
||||
127 RERAISE (1)
|
||||
>> 128 JUMP_BACKWARD (11)
|
||||
>> 129 RETURN_CONST (None)
|
||||
>> 129 POP_TOP
|
||||
130 RETURN_CONST (None)
|
||||
|
||||
1 MAKE_FUNCTION
|
||||
2 STORE_NAME (0, test)
|
||||
|
||||
@@ -272,19 +272,11 @@ pub enum Instruction {
|
||||
Continue {
|
||||
target: Arg<Label>,
|
||||
} = 217,
|
||||
JumpIfFalseOrPop {
|
||||
target: Arg<Label>,
|
||||
} = 218,
|
||||
JumpIfTrueOrPop {
|
||||
target: Arg<Label>,
|
||||
} = 219,
|
||||
JumpIfNotExcMatch(Arg<Label>) = 220,
|
||||
LoadAssertionError = 221, // Placeholder
|
||||
ReturnConst {
|
||||
idx: Arg<u32>,
|
||||
} = 222,
|
||||
SetExcInfo = 223,
|
||||
Subscript = 224,
|
||||
// CPython 3.14 RESUME (128)
|
||||
Resume {
|
||||
arg: Arg<u32>,
|
||||
@@ -441,17 +433,9 @@ impl TryFrom<u8> for Instruction {
|
||||
u8::from(Self::Continue {
|
||||
target: Arg::marker(),
|
||||
}),
|
||||
u8::from(Self::JumpIfFalseOrPop {
|
||||
target: Arg::marker(),
|
||||
}),
|
||||
u8::from(Self::JumpIfTrueOrPop {
|
||||
target: Arg::marker(),
|
||||
}),
|
||||
u8::from(Self::JumpIfNotExcMatch(Arg::marker())),
|
||||
u8::from(Self::LoadAssertionError),
|
||||
u8::from(Self::ReturnConst { idx: Arg::marker() }),
|
||||
u8::from(Self::SetExcInfo),
|
||||
u8::from(Self::Subscript),
|
||||
];
|
||||
|
||||
if (cpython_start..=cpython_end).contains(&value)
|
||||
@@ -478,8 +462,6 @@ impl InstructionMetadata for Instruction {
|
||||
| Self::JumpIfNotExcMatch(l)
|
||||
| Self::PopJumpIfTrue { target: l }
|
||||
| Self::PopJumpIfFalse { target: l }
|
||||
| Self::JumpIfTrueOrPop { target: l }
|
||||
| Self::JumpIfFalseOrPop { target: l }
|
||||
| Self::ForIter { target: l }
|
||||
| Self::Break { target: l }
|
||||
| Self::Continue { target: l }
|
||||
@@ -525,7 +507,6 @@ impl InstructionMetadata for Instruction {
|
||||
Self::DeleteGlobal(_) => 0,
|
||||
Self::DeleteDeref(_) => 0,
|
||||
Self::LoadFromDictOrDeref(_) => 1,
|
||||
Self::Subscript => -1,
|
||||
Self::StoreSubscr => -3,
|
||||
Self::DeleteSubscr => -2,
|
||||
Self::LoadAttr { .. } => 0,
|
||||
@@ -551,20 +532,6 @@ impl InstructionMetadata for Instruction {
|
||||
Self::Break { .. } => 0,
|
||||
Self::PopJumpIfTrue { .. } => -1,
|
||||
Self::PopJumpIfFalse { .. } => -1,
|
||||
Self::JumpIfTrueOrPop { .. } => {
|
||||
if jump {
|
||||
0
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
}
|
||||
Self::JumpIfFalseOrPop { .. } => {
|
||||
if jump {
|
||||
0
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
}
|
||||
Self::MakeFunction => {
|
||||
// CPython 3.14 style: MakeFunction only pops code object
|
||||
-1 + 1 // pop code, push function
|
||||
@@ -584,11 +551,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,
|
||||
@@ -684,7 +649,6 @@ impl InstructionMetadata for Instruction {
|
||||
Self::EndFor => 0,
|
||||
Self::ExitInitCheck => 0,
|
||||
Self::InterpreterExit => 0,
|
||||
Self::LoadAssertionError => 0,
|
||||
Self::LoadLocals => 0,
|
||||
Self::ReturnGenerator => 0,
|
||||
Self::StoreSlice => 0,
|
||||
@@ -920,9 +884,7 @@ impl InstructionMetadata for Instruction {
|
||||
Self::JumpBackward { target } => w!(JUMP_BACKWARD, target),
|
||||
Self::JumpBackwardNoInterrupt { target } => w!(JUMP_BACKWARD_NO_INTERRUPT, target),
|
||||
Self::JumpForward { target } => w!(JUMP_FORWARD, target),
|
||||
Self::JumpIfFalseOrPop { target } => w!(JUMP_IF_FALSE_OR_POP, target),
|
||||
Self::JumpIfNotExcMatch(target) => w!(JUMP_IF_NOT_EXC_MATCH, target),
|
||||
Self::JumpIfTrueOrPop { target } => w!(JUMP_IF_TRUE_OR_POP, target),
|
||||
Self::ListAppend { i } => w!(LIST_APPEND, i),
|
||||
Self::ListExtend { i } => w!(LIST_EXTEND, i),
|
||||
Self::LoadAttr { idx } => {
|
||||
@@ -994,7 +956,6 @@ impl InstructionMetadata for Instruction {
|
||||
Self::StoreGlobal(idx) => w!(STORE_GLOBAL, name = idx),
|
||||
Self::StoreName(idx) => w!(STORE_NAME, name = idx),
|
||||
Self::StoreSubscr => w!(STORE_SUBSCR),
|
||||
Self::Subscript => w!(SUBSCRIPT),
|
||||
Self::Swap { index } => w!(SWAP, index),
|
||||
Self::ToBool => w!(TO_BOOL),
|
||||
Self::UnpackEx { args } => w!(UNPACK_EX, args),
|
||||
|
||||
@@ -107,9 +107,7 @@ mod opcode {
|
||||
Instruction::Break { .. }
|
||||
| Instruction::Continue { .. }
|
||||
| Instruction::ForIter { .. }
|
||||
| Instruction::JumpIfFalseOrPop { .. }
|
||||
| Instruction::JumpIfNotExcMatch(_)
|
||||
| Instruction::JumpIfTrueOrPop { .. }
|
||||
| Instruction::PopJumpIfFalse { .. }
|
||||
| Instruction::PopJumpIfTrue { .. }
|
||||
| Instruction::Send { .. }
|
||||
|
||||
@@ -1139,9 +1139,6 @@ impl ExecutingFrame<'_> {
|
||||
self.push_value(vm.ctx.new_bool(value).into());
|
||||
Ok(None)
|
||||
}
|
||||
Instruction::JumpIfFalseOrPop { target } => {
|
||||
self.jump_if_or_pop(vm, target.get(arg), false)
|
||||
}
|
||||
Instruction::JumpIfNotExcMatch(target) => {
|
||||
let b = self.pop_value();
|
||||
let a = self.pop_value();
|
||||
@@ -1165,9 +1162,6 @@ impl ExecutingFrame<'_> {
|
||||
self.push_value(vm.ctx.new_bool(value).into());
|
||||
self.pop_jump_if(vm, target.get(arg), false)
|
||||
}
|
||||
Instruction::JumpIfTrueOrPop { target } => {
|
||||
self.jump_if_or_pop(vm, target.get(arg), true)
|
||||
}
|
||||
Instruction::JumpForward { target } => {
|
||||
self.jump(target.get(arg));
|
||||
Ok(None)
|
||||
@@ -1734,7 +1728,6 @@ impl ExecutingFrame<'_> {
|
||||
Ok(None)
|
||||
}
|
||||
Instruction::StoreSubscr => self.execute_store_subscript(vm),
|
||||
Instruction::Subscript => self.execute_subscript(vm),
|
||||
Instruction::Swap { index } => {
|
||||
let len = self.state.stack.len();
|
||||
debug_assert!(len > 0, "stack underflow in SWAP");
|
||||
@@ -2074,14 +2067,6 @@ impl ExecutingFrame<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn execute_subscript(&mut self, vm: &VirtualMachine) -> FrameResult {
|
||||
let b_ref = self.pop_value();
|
||||
let a_ref = self.pop_value();
|
||||
let value = a_ref.get_item(&*b_ref, vm)?;
|
||||
self.push_value(value);
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn execute_store_subscript(&mut self, vm: &VirtualMachine) -> FrameResult {
|
||||
let idx = self.pop_value();
|
||||
let obj = self.pop_value();
|
||||
@@ -2351,23 +2336,6 @@ impl ExecutingFrame<'_> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn jump_if_or_pop(
|
||||
&mut self,
|
||||
vm: &VirtualMachine,
|
||||
target: bytecode::Label,
|
||||
flag: bool,
|
||||
) -> FrameResult {
|
||||
let obj = self.top_value();
|
||||
let value = obj.to_owned().try_to_bool(vm)?;
|
||||
if value == flag {
|
||||
self.jump(target);
|
||||
} else {
|
||||
self.pop_value();
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// The top of stack contains the iterator, lets push it forward
|
||||
fn execute_for_iter(&mut self, vm: &VirtualMachine, target: bytecode::Label) -> FrameResult {
|
||||
let top_of_stack = PyIter::new(self.top_value());
|
||||
@@ -2380,15 +2348,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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user