FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Use `stack_effect_info` for getting pop&push count by ShaharNaveh · Pull Request #6913 · RustPython/RustPython · GitHub

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .rs  (1) .snap  (1) All 2 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
60 changes: 3 additions & 57 deletions crates/codegen/src/ir.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ impl CodeInfo {
// (or NOT_LOCAL if not from LOAD_FAST/LOAD_FAST_LOAD_FAST).
//
// CPython (flowgraph.c optimize_load_fast) pre-fills the stack with
// dummy refs for values inherited from predecessor blocks. We take
// dummy refs for values inherited from predecessor blocks. We take
// the simpler approach of aborting the optimisation for the whole
// block on stack underflow.
let mut stack: Vec<usize> = Vec::new();
Expand All @@ -724,62 +724,8 @@ impl CodeInfo {
continue;
};

// Decompose into (pops, pushes).
//
// stack_effect() returns pushes − pops, which is ambiguous for
// instructions that both pop and push (e.g. BinaryOp: effect=-1
// is pop 2 push 1, not pop 1 push 0). We list those explicitly;
// the fallback under-pops and under-pushes, which is conservative
// (may miss optimisation opportunities but never miscompiles).
let effect = instr.stack_effect(info.arg.into());
let (pops, pushes) = match instr {
// --- pop 2, push 1 ---
Instruction::BinaryOp { .. }
| Instruction::BinaryOpInplaceAddUnicode
| Instruction::CompareOp { .. }
| Instruction::ContainsOp(_)
| Instruction::IsOp(_)
| Instruction::ImportName { .. }
| Instruction::FormatWithSpec => (2, 1),

// --- pop 1, push 1 ---
Instruction::UnaryInvert
| Instruction::UnaryNegative
| Instruction::UnaryNot
| Instruction::ToBool
| Instruction::GetIter
| Instruction::GetAIter
| Instruction::FormatSimple
| Instruction::LoadFromDictOrDeref(_)
| Instruction::LoadFromDictOrGlobals(_) => (1, 1),

// LoadAttr: pop receiver, push attr.
// method=true: push (method, self_or_null) → (1, 2)
Instruction::LoadAttr { idx } => {
let (_, is_method) =
rustpython_compiler_core::bytecode::decode_load_attr_arg(
idx.get(info.arg),
);
if is_method { (1, 2) } else { (1, 1) }
}

// --- pop 3, push 1 ---
Instruction::BinarySlice => (3, 1),

// --- variable pops, push 1 ---
Instruction::Call { nargs } => (nargs.get(info.arg) as usize + 2, 1),
Instruction::CallKw { nargs } => (nargs.get(info.arg) as usize + 3, 1),

// --- conservative fallback ---
// under-pops (≤ actual pops) and under-pushes (≤ actual pushes),
// which keeps extra refs on the stack → marks them unconsumed →
// prevents optimisation. Safe but may miss opportunities.
_ => {
let p = if effect < 0 { (-effect) as usize } else { 0 };
let q = if effect > 0 { effect as usize } else { 0 };
(p, q)
}
};
let stack_effect_info = instr.stack_effect_info(info.arg.into());
let (pushes, pops) = (stack_effect_info.pushed(), stack_effect_info.popped());

// Pop values from stack
for _ in 0..pops {
Expand Down

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


Back | FazBrowse Home | New Git URL