-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New Instruction ToBool,PopJumpIfFalse #6112
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughRenames conditional-jump variants to PopJumpIfTrue/PopJumpIfFalse, adds a unit Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant BC as Bytecode
participant Frame as ExecutingFrame
participant Stack
participant VM as VM/Runtime
rect rgba(230,240,255,0.6)
note over BC,Frame: ToBool execution
Frame->>Stack: pop value
Frame->>VM: try_to_bool(value)
VM-->>Frame: bool_obj
Frame->>Stack: push bool_obj
end
rect rgba(240,230,255,0.6)
note over BC,Frame: PopJumpIfTrue / PopJumpIfFalse execution
Frame->>Stack: pop value
Frame->>VM: try_to_bool(value)
VM-->>Frame: bool_result
alt pop result matches jump condition
Frame->>Frame: jump to target label
else
Frame->>Frame: continue (value discarded)
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Poem
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
vm/src/frame.rs (2)
1240-1242
: Avoid duplicating jump logic; reuse existing jump_if here.PopJumpIfFalse currently calls pop_jump_if, which is identical to jump_if. You can dispatch directly to jump_if to reduce duplication and keep all “pop-and-jump” semantics in one place.
Apply this diff to the match arm:
- bytecode::Instruction::PopJumpIfFalse { target } => { - self.pop_jump_if(vm, target.get(arg), false) - } + bytecode::Instruction::PopJumpIfFalse { target } => + self.jump_if(vm, target.get(arg), false),
1877-1893
: pop_jump_if duplicates jump_if; consider removing or documenting divergence intent.The implementation is bit-for-bit identical to jump_if (pop TOS, to-bool, jump on flag). Unless you plan to diverge semantics later, remove it to prevent drift.
Apply this diff to remove the helper:
- #[inline] - fn pop_jump_if( - &mut self, - vm: &VirtualMachine, - target: bytecode::Label, - flag: bool, - ) -> FrameResult { - // PopJumpIf{True,False} - // Pop TOS, convert to bool, jump if matches flag - let obj = self.pop_value(); - let value = obj.try_to_bool(vm)?; - if value == flag { - self.jump(target); - } - // If not jumping, the value is already popped - Ok(None) - }If you prefer keeping both for readability, add a brief comment in pop_jump_if stating it intentionally mirrors jump_if today.
📜 Review details
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
compiler/core/src/bytecode.rs
(7 hunks)vm/src/frame.rs
(3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.rs
: Follow the default rustfmt code style (cargo fmt
to format)
Always run clippy to lint code (cargo clippy
) before completing tasks. Fix any warnings or lints that are introduced by your changes
Follow Rust best practices for error handling and memory management
Use the macro system (pyclass
,pymodule
,pyfunction
, etc.) when implementing Python functionality in Rust
Files:
vm/src/frame.rs
compiler/core/src/bytecode.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: Run snippets and cpython tests (windows-latest)
- GitHub Check: Check Rust code with rustfmt and clippy
- GitHub Check: Run rust tests (ubuntu-latest)
- GitHub Check: Run snippets and cpython tests (macos-latest)
- GitHub Check: Ensure compilation on various targets
- GitHub Check: Run rust tests (windows-latest)
- GitHub Check: Run rust tests (macos-latest)
- GitHub Check: Run tests under miri
- GitHub Check: Run snippets and cpython tests on wasm-wasi
🔇 Additional comments (7)
vm/src/frame.rs (1)
1086-1091
: ToBool execution path looks correct (pop -> truthy -> push bool).Net stack effect is 0 and consistent with other truthiness sites (e.g., UnaryOperator::Not, jump_if). No issues spotted.
compiler/core/src/bytecode.rs (6)
528-528
: Re-enabling ToBool in the enum is fine.Matches VM support and printing paths; no API fallout.
1264-1264
: Including PopJumpIfFalse in label_arg is correct.Ensures disassembler/CFG find jump targets.
1338-1338
: ToBool stack effect = 0 is consistent with VM.Good alignment with execution (pop + push).
1349-1349
: PopJumpIfFalse stack effect = -1 matches VM’s single-pop semantics.If you adopt Option B (two-pop), remember to update this to -2.
1541-1541
: Disassembly formatting for ToBool is wired correctly.No issues.
1557-1557
: Disassembly formatting for PopJumpIfFalse is wired correctly.Will display target like other jumps.
compiler/core/src/bytecode.rs
Outdated
/// Pop the top of the stack, then pop the next value and jump if it is false. | ||
PopJumpIfFalse { | ||
target: Arg<Label>, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Docstring contradicts implementation and stack effect for PopJumpIfFalse.
Comment says “pop TOS, then pop the next value and jump if it is false” (two pops), but:
- VM pops once and branches on that value.
- stack_effect() treats PopJumpIfFalse as -1 (one pop).
Align the doc or the semantics; otherwise future maintainers will miscompile/optimize around wrong assumptions.
Option A (recommended): Fix the doc to match current behavior.
- /// Pop the top of the stack, then pop the next value and jump if it is false.
+ /// Pop the top of the stack and jump if it is false.
Option B (if two-pop semantics are intended): change stack effect to -2 and update VM to pop twice.
- JumpIfTrue { .. } | JumpIfFalse { .. } | PopJumpIfFalse { .. } => -1,
+ JumpIfTrue { .. } | JumpIfFalse { .. } => -1,
+ PopJumpIfFalse { .. } => -2,
…and in vm/src/frame.rs adjust PopJumpIfFalse to pop/ignore one value, then pop/branch on the next.
🏁 Script executed:
#!/bin/bash
set -e
echo "=== Inspecting stack_effect() in compiler/core/src/bytecode.rs ==="
rg -n -C10 'fn stack_effect' compiler/core/src/bytecode.rs || true
echo
echo "=== Occurrences of PopJumpIfFalse in the repository ==="
rg -n -C5 'PopJumpIfFalse' --glob '*.rs' || true
Length of output: 14203
🏁 Script executed:
#!/bin/bash
set -e
echo "=== Searching definition of pop_jump_if in vm/src/frame.rs ==="
rg -n 'fn pop_jump_if' -C5 vm/src/frame.rs || true
echo
echo "=== Inspecting pop_jump_if implementation ==="
sed -n '1230,1300p' vm/src/frame.rs || true
echo
echo "=== Searching helper methods related to pop_jump_if ==="
rg -n -C5 'pop_jump_if\|jump_if' -C5 vm/src/frame.rs || true
Length of output: 3864
🏁 Script executed:
#!/bin/bash
set -e
echo "=== Showing pop_jump_if implementation (lines 1870-1940) ==="
sed -n '1870,1940p' vm/src/frame.rs || true
Length of output: 2362
Align PopJumpIfFalse docstring with implementation
The current docstring implies two pops, but both stack_effect()
(which returns –1) and the VM’s pop_jump_if
method only pop the top-of-stack once. Update the doc to match one-pop semantics:
• File: compiler/core/src/bytecode.rs
Location: the doc comment on the PopJumpIfFalse
variant
Suggested change:
--- a/compiler/core/src/bytecode.rs
+++ b/compiler/core/src/bytecode.rs
@@ -558,1 +558,1 @@
- /// Pop the top of the stack, then pop the next value and jump if it is false.
+ /// Pop the top of the stack and jump if it is false.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
/// Pop the top of the stack, then pop the next value and jump if it is false. | |
PopJumpIfFalse { | |
target: Arg<Label>, | |
}, | |
/// Pop the top of the stack and jump if it is false. | |
PopJumpIfFalse { | |
target: Arg<Label>, | |
}, |
🤖 Prompt for AI Agents
In compiler/core/src/bytecode.rs around lines 558 to 561, the docstring for the
PopJumpIfFalse variant incorrectly states that two values are popped; update the
comment to reflect the actual one-pop semantics used by stack_effect() and the
VM's pop_jump_if (i.e., it pops the top-of-stack once and jumps if that value is
false), so change the docstring wording to say it pops the top value and jumps
if that value is false.
847482e
to
75a138a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
compiler/core/src/bytecode.rs (1)
461-471
: Ensure bytecode changes are accompanied by a marshal‐format bumpIt looks like you’ve inserted
ToBool
into the middle of theInstruction
enum without updating the marshal protocol version or assigning explicit discriminants. BecauseInstruction
is#[repr(u8)]
and we transmute incoming bytes up toLAST_INSTRUCTION
, adding a new variant shifts all downstream opcodes, breaking any previously serialized bytecode.Please address this before landing:
• compiler/core/src/bytecode.rs
– You’ve added
rust ToBool,
mid‐enum, which shifts all subsequent discriminants. Verify thatLAST_INSTRUCTION
remains pointing at the true final variant (currentlyExtendedArg
), and consider assigning an explicit value toToBool
(or to all new variants) to preserve existing opcode numbers if backward‐compatibility across marshal versions is required.• compiler/core/src/marshal.rs
– The marshal format version is still
rust pub const FORMAT_VERSION: u32 = 4;
Bump this to a new value (e.g.5
) so that the VM rejects older bytecode rather than mis‐decoding it.
Suggested diff:
diff --- a/compiler/core/src/marshal.rs +++ b/compiler/core/src/marshal.rs @@ -4,7 +4,7 @@ pub const FORMAT_VERSION: u32 = 4; #[derive(Debug)] pub enum MarshalError { - /// Invalid Bytecode + /// Invalid Bytecode
becomes
diff pub const FORMAT_VERSION: u32 = 5;
These steps will prevent subtle, hard‐to‐debug mismatches when loading marshaled code across versions.
♻️ Duplicate comments (1)
compiler/core/src/bytecode.rs (1)
551-556
: Docstrings for PopJumpIfTrue/PopJumpIfFalse now match one-pop behaviorThis aligns the documentation with the VM implementation and stack_effect (-1). Thanks for fixing the earlier inconsistency.
🧹 Nitpick comments (4)
jit/src/instructions.rs (1)
291-303
: PopJumpIfTrue: mirrors semantics correctly
- Pops the condition, converts to boolean, true → target, false → fallthrough. Matches POP_JUMP_IF_TRUE behavior.
- Fallthrough is established by switching to else_block post-branch.
Apply the same variable rename for consistency:
- let then_block = self.get_or_create_block(target.get(arg)); + let target_block = self.get_or_create_block(target.get(arg)); let else_block = self.builder.create_block(); self.builder .ins() - .brif(val, then_block, &[], else_block, &[]); + .brif(val, target_block, &[], else_block, &[]);vm/src/frame.rs (2)
1086-1091
: ToBool runtime semantics are correct; consider avoiding pop/push with replace_topNet stack effect is 0 and matches bytecode::Instruction::ToBool. Minor micro-optimization: replace TOS in-place to avoid an extra pop/push pair.
Apply this diff:
bytecode::Instruction::ToBool => { - let obj = self.pop_value(); - let bool_val = obj.try_to_bool(vm)?; - self.push_value(vm.ctx.new_bool(bool_val).into()); + let tos_bool = self.top_value().to_owned().try_to_bool(vm)?; + self.replace_top(vm.ctx.new_bool(tos_bool).into()); Ok(None) }
712-720
: Remove stale commented-out ToBool match armThis dead, commented block now duplicates the live ToBool case and can confuse future edits. Please remove it.
Apply this diff:
- // bytecode::Instruction::ToBool => { - // dbg!("Shouldn't be called outside of match statements for now") - // let value = self.pop_value(); - // // call __bool__ - // let result = value.try_to_bool(vm)?; - // self.push_value(vm.ctx.new_bool(result).into()); - // Ok(None) - // }compiler/core/src/bytecode.rs (1)
528-528
: New ToBool opcode: placement and naming look fine; add a brief doc commentThe unit variant is added consistently, and downstream code handles it. Consider a short doc comment to clarify that it converts TOS to a concrete bool object and leaves it on TOS (stack effect 0).
Apply this diff:
- ToBool, + /// Convert TOS to a boolean (via __bool__ or __len__), push the bool object back (net 0). + ToBool,
📜 Review details
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (8)
compiler/codegen/src/snapshots/rustpython_codegen__compile__tests__if_ands.snap
is excluded by!**/*.snap
compiler/codegen/src/snapshots/rustpython_codegen__compile__tests__if_mixed.snap
is excluded by!**/*.snap
compiler/codegen/src/snapshots/rustpython_codegen__compile__tests__if_ors.snap
is excluded by!**/*.snap
compiler/codegen/src/snapshots/rustpython_codegen__compile__tests__nested_double_async_with.snap
is excluded by!**/*.snap
compiler/codegen/src/snapshots/rustpython_compiler_core__compile__tests__if_ands.snap
is excluded by!**/*.snap
compiler/codegen/src/snapshots/rustpython_compiler_core__compile__tests__if_mixed.snap
is excluded by!**/*.snap
compiler/codegen/src/snapshots/rustpython_compiler_core__compile__tests__if_ors.snap
is excluded by!**/*.snap
compiler/codegen/src/snapshots/rustpython_compiler_core__compile__tests__nested_double_async_with.snap
is excluded by!**/*.snap
📒 Files selected for processing (4)
compiler/codegen/src/compile.rs
(3 hunks)compiler/core/src/bytecode.rs
(7 hunks)jit/src/instructions.rs
(2 hunks)vm/src/frame.rs
(3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.rs
: Follow the default rustfmt code style (cargo fmt
to format)
Always run clippy to lint code (cargo clippy
) before completing tasks. Fix any warnings or lints that are introduced by your changes
Follow Rust best practices for error handling and memory management
Use the macro system (pyclass
,pymodule
,pyfunction
, etc.) when implementing Python functionality in Rust
Files:
compiler/codegen/src/compile.rs
vm/src/frame.rs
jit/src/instructions.rs
compiler/core/src/bytecode.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
- GitHub Check: Run snippets and cpython tests on wasm-wasi
- GitHub Check: Check the WASM package and demo
- GitHub Check: Check Rust code with rustfmt and clippy
- GitHub Check: Ensure compilation on various targets
- GitHub Check: Run tests under miri
- GitHub Check: Run rust tests (macos-latest)
- GitHub Check: Run snippets and cpython tests (windows-latest)
- GitHub Check: Run snippets and cpython tests (ubuntu-latest)
- GitHub Check: Run rust tests (ubuntu-latest)
- GitHub Check: Run snippets and cpython tests (macos-latest)
- GitHub Check: Run rust tests (windows-latest)
🔇 Additional comments (10)
jit/src/instructions.rs (1)
278-290
: PopJumpIfFalse logic is correct – no JIT‐side ToBool support neededVerified that the JIT compiler never actually emits
Instruction::ToBool
(the sole reference incompiler/codegen/src/compile.rs
is commented out), so adding a handler for it isn’t necessary at this time. The only remaining suggestion is the optional rename for clarity:• In
jit/src/instructions.rs
at lines 278–290, renamethen_block
totarget_block
(and update its use in.brif
) in both thePopJumpIfFalse
andPopJumpIfTrue
arms:- let then_block = self.get_or_create_block(target.get(arg)); + let target_block = self.get_or_create_block(target.get(arg)); let else_block = self.builder.create_block(); self.builder - .ins() - .brif(val, else_block, &[], then_block, &[]); + .ins() + .brif(val, else_block, &[], target_block, &[]); …compiler/codegen/src/compile.rs (3)
2029-2033
: try/except: switching to PopJumpIfFalse fixes stack disciplineUsing PopJumpIfFalse after ExceptionMatch ensures the temporary boolean is consumed on either path. This prevents a stray bool on the success path before binding “as name” or popping the exception. Good alignment with the new POP_JUMP* contract.
Please double-check that TestOperation::ExceptionMatch leaves only the original exception and a single boolean on stack before this jump; no other sites in this handler depend on the boolean staying on the stack.
3119-3123
: Pattern engine: PopJumpIfFalse is the right choice for fail pathsAdopting PopJumpIfFalse in jump_to_fail_pop is correct: failure consumes the condition result before transferring to the cleanup label, which simplifies the required pops at the failure targets.
4399-4411
: compile_jump_if: updated to PopJumpIfTrue/False—confirm no callers expect the test value to remainConverting both branches to POP_JUMP variants is the right move and matches the new bytecode. Since POP_JUMP* consumes the test, ensure all call sites (if/elif/while, assert, comp generators) do not rely on the test value remaining on the stack. A quick scan of the surrounding control-flow builders suggests they do not.
If you want a safety net, run snapshot tests around:
- if/elif/else nesting
- while with complex expressions
- assert with and without message
Existing insta snapshots (e.g., test_if_ors/ands/mixed) are good coverage; adding one for while would be helpful.
vm/src/frame.rs (2)
1850-1855
: Helper pop_jump_if(): clear factoring; semantics match CPython truthinessGood consolidation. It pops once, converts via try_to_bool, and conditionally jumps—exactly what PopJumpIf{True,False} require. No issues spotted.
1236-1241
: All staleJumpIfTrue
/JumpIfFalse
variants have been removedVerification via ripgrep confirms zero occurrences of the old
JumpIfTrue
orJumpIfFalse
variants in the repository. The newPopJumpIfTrue
/PopJumpIfFalse
instructions are consistently wired across all relevant crates:
- vm/src/frame.rs: dispatch cases for
PopJumpIfTrue
andPopJumpIfFalse
(lines 1236–1241)- jit/src/instructions.rs: implementations for both variants (lines 278–293)
- compiler/codegen/src/compile.rs: emission and
jump_to_fail_pop
calls usingPopJumpIfTrue
/PopJumpIfFalse
throughout control‐flow compilation- compiler/core/src/bytecode.rs: enum definitions and matching arms exclusively reference
PopJumpIfTrue
,PopJumpIfFalse
,JumpIfTrueOrPop
, andJumpIfFalseOrPop
- Snapshot files under both
compiler/codegen
andcompiler/core
confirm test coverage uses only the new variantsNo residual references to the old
JumpIfTrue
/JumpIfFalse
remain.compiler/core/src/bytecode.rs (4)
1257-1260
: Include PopJumpIf{True,False} in label_arg()Label extraction updated appropriately; keeps disassembly and control-flow analysis correct.
1334-1334
: Stack effect for ToBool = 0 is correctRuntime pops and pushes a bool object back; net zero. Matches VM implementation.
1345-1345
: Stack effect for PopJumpIf{True,False} = -1 is correctMatches single-pop branching semantics used by vm::frame::ExecutingFrame::pop_jump_if.
1536-1536
: Disassembly formatting covers ToBool and PopJumpIf{True,False}fmt_dis outputs are wired; no issues.
Also applies to: 1549-1551
Summary by CodeRabbit
New Features
Chores