Analyze bytecode and compute the stack state at each instruction index.
(code: &bytecode::CodeObject<C>)
| 151 | |
| 152 | /// Analyze bytecode and compute the stack state at each instruction index. |
| 153 | pub fn mark_stacks<C: Constant>(code: &bytecode::CodeObject<C>) -> Vec<i64> { |
| 154 | let instructions = &*code.instructions; |
| 155 | let len = instructions.len(); |
| 156 | |
| 157 | let mut stacks = vec![UNINITIALIZED; len + 1]; |
| 158 | stacks[0] = EMPTY_STACK; |
| 159 | |
| 160 | let mut todo = true; |
| 161 | while todo { |
| 162 | todo = false; |
| 163 | |
| 164 | let mut i = 0; |
| 165 | while i < len { |
| 166 | let mut next_stack = stacks[i]; |
| 167 | let mut opcode = instructions[i].op; |
| 168 | let mut oparg: u32 = 0; |
| 169 | |
| 170 | // Accumulate EXTENDED_ARG prefixes |
| 171 | while matches!(opcode, Instruction::ExtendedArg) { |
| 172 | oparg = (oparg << 8) | u32::from(u8::from(instructions[i].arg)); |
| 173 | i += 1; |
| 174 | if i >= len { |
| 175 | break; |
| 176 | } |
| 177 | stacks[i] = next_stack; |
| 178 | opcode = instructions[i].op; |
| 179 | } |
| 180 | if i >= len { |
| 181 | break; |
| 182 | } |
| 183 | oparg = (oparg << 8) | u32::from(u8::from(instructions[i].arg)); |
| 184 | |
| 185 | // De-instrument and de-specialize: get the underlying base instruction |
| 186 | let opcode = opcode.to_base().unwrap_or(opcode).deoptimize(); |
| 187 | |
| 188 | let caches = opcode.cache_entries(); |
| 189 | let next_i = i + 1 + caches; |
| 190 | |
| 191 | if next_stack == UNINITIALIZED { |
| 192 | i = next_i; |
| 193 | continue; |
| 194 | } |
| 195 | |
| 196 | match opcode { |
| 197 | Instruction::PopJumpIfFalse { .. } |
| 198 | | Instruction::PopJumpIfTrue { .. } |
| 199 | | Instruction::PopJumpIfNone { .. } |
| 200 | | Instruction::PopJumpIfNotNone { .. } => { |
| 201 | // Relative forward: target = after_caches + delta |
| 202 | let j = next_i + oparg as usize; |
| 203 | next_stack = pop_value(next_stack); |
| 204 | let target_stack = next_stack; |
| 205 | if j < stacks.len() && stacks[j] == UNINITIALIZED { |
| 206 | stacks[j] = target_stack; |
| 207 | } |
| 208 | if next_i < stacks.len() { |
| 209 | stacks[next_i] = next_stack; |
| 210 | } |
no test coverage detected