@@ -713,7 +713,7 @@ impl CodeInfo {
713713 // (or NOT_LOCAL if not from LOAD_FAST/LOAD_FAST_LOAD_FAST).
714714 //
715715 // CPython (flowgraph.c optimize_load_fast) pre-fills the stack with
716- // dummy refs for values inherited from predecessor blocks. We take
716+ // dummy refs for values inherited from predecessor blocks. We take
717717 // the simpler approach of aborting the optimisation for the whole
718718 // block on stack underflow.
719719 let mut stack: Vec < usize > = Vec :: new ( ) ;
@@ -724,62 +724,8 @@ impl CodeInfo {
724724 continue ;
725725 } ;
726726
727- // Decompose into (pops, pushes).
728- //
729- // stack_effect() returns pushes − pops, which is ambiguous for
730- // instructions that both pop and push (e.g. BinaryOp: effect=-1
731- // is pop 2 push 1, not pop 1 push 0). We list those explicitly;
732- // the fallback under-pops and under-pushes, which is conservative
733- // (may miss optimisation opportunities but never miscompiles).
734- let effect = instr. stack_effect ( info. arg . into ( ) ) ;
735- let ( pops, pushes) = match instr {
736- // --- pop 2, push 1 ---
737- Instruction :: BinaryOp { .. }
738- | Instruction :: BinaryOpInplaceAddUnicode
739- | Instruction :: CompareOp { .. }
740- | Instruction :: ContainsOp ( _)
741- | Instruction :: IsOp ( _)
742- | Instruction :: ImportName { .. }
743- | Instruction :: FormatWithSpec => ( 2 , 1 ) ,
744-
745- // --- pop 1, push 1 ---
746- Instruction :: UnaryInvert
747- | Instruction :: UnaryNegative
748- | Instruction :: UnaryNot
749- | Instruction :: ToBool
750- | Instruction :: GetIter
751- | Instruction :: GetAIter
752- | Instruction :: FormatSimple
753- | Instruction :: LoadFromDictOrDeref ( _)
754- | Instruction :: LoadFromDictOrGlobals ( _) => ( 1 , 1 ) ,
755-
756- // LoadAttr: pop receiver, push attr.
757- // method=true: push (method, self_or_null) → (1, 2)
758- Instruction :: LoadAttr { idx } => {
759- let ( _, is_method) =
760- rustpython_compiler_core:: bytecode:: decode_load_attr_arg (
761- idx. get ( info. arg ) ,
762- ) ;
763- if is_method { ( 1 , 2 ) } else { ( 1 , 1 ) }
764- }
765-
766- // --- pop 3, push 1 ---
767- Instruction :: BinarySlice => ( 3 , 1 ) ,
768-
769- // --- variable pops, push 1 ---
770- Instruction :: Call { nargs } => ( nargs. get ( info. arg ) as usize + 2 , 1 ) ,
771- Instruction :: CallKw { nargs } => ( nargs. get ( info. arg ) as usize + 3 , 1 ) ,
772-
773- // --- conservative fallback ---
774- // under-pops (≤ actual pops) and under-pushes (≤ actual pushes),
775- // which keeps extra refs on the stack → marks them unconsumed →
776- // prevents optimisation. Safe but may miss opportunities.
777- _ => {
778- let p = if effect < 0 { ( -effect) as usize } else { 0 } ;
779- let q = if effect > 0 { effect as usize } else { 0 } ;
780- ( p, q)
781- }
782- } ;
727+ let stack_effect_info = instr. stack_effect_info ( info. arg . into ( ) ) ;
728+ let ( pushes, pops) = ( stack_effect_info. pushed ( ) , stack_effect_info. popped ( ) ) ;
783729
784730 // Pop values from stack
785731 for _ in 0 ..pops {
0 commit comments