Detect type of block structures and their boundaries to fix optimized jumps in python2.3+
(self, offset, op, extended_arg)
| 638 | count_SETUP_ += 1 |
| 639 | |
| 640 | def detect_control_flow(self, offset, op, extended_arg): |
| 641 | """ |
| 642 | Detect type of block structures and their boundaries to fix optimized jumps |
| 643 | in python2.3+ |
| 644 | """ |
| 645 | |
| 646 | code = self.code |
| 647 | |
| 648 | # Detect parent structure |
| 649 | parent = self.structs[0] |
| 650 | start = parent["start"] |
| 651 | end = parent["end"] |
| 652 | next_line_byte = end |
| 653 | |
| 654 | # Pick inner-most parent for our offset |
| 655 | for struct in self.structs: |
| 656 | current_start = struct["start"] |
| 657 | current_end = struct["end"] |
| 658 | if (current_start <= offset < current_end) and ( |
| 659 | current_start >= start and current_end <= end |
| 660 | ): |
| 661 | start = current_start |
| 662 | end = current_end |
| 663 | parent = struct |
| 664 | |
| 665 | if op == self.opc.SETUP_LOOP: |
| 666 | # We categorize loop types: 'for', 'while', 'while 1' with |
| 667 | # possibly suffixes '-loop' and '-else' |
| 668 | # Try to find the jump_back instruction of the loop. |
| 669 | # It could be a return instruction. |
| 670 | |
| 671 | inst = self.insts[self.offset2inst_index[offset]] |
| 672 | start += instruction_size(op, self.opc) |
| 673 | setup_target = inst.argval |
| 674 | loop_end_offset = self.restrict_to_parent(setup_target, parent) |
| 675 | self.setup_loop_targets[offset] = setup_target |
| 676 | self.setup_loops[setup_target] = offset |
| 677 | |
| 678 | if setup_target != loop_end_offset: |
| 679 | self.fixed_jumps[offset] = loop_end_offset |
| 680 | |
| 681 | if self.lines: |
| 682 | (line_no, next_line_byte) = self.lines[offset] |
| 683 | |
| 684 | # jump_back_offset is the instruction after the SETUP_LOOP |
| 685 | # where we iterate back to. |
| 686 | jump_back_offset = self.last_instr( |
| 687 | start, loop_end_offset, self.opc.JUMP_ABSOLUTE, next_line_byte, False |
| 688 | ) |
| 689 | |
| 690 | if jump_back_offset: |
| 691 | # Account for the fact that < 2.7 has an explicit |
| 692 | # POP_TOP instruction in the equivalate POP_JUMP_IF |
| 693 | # construct |
| 694 | if self.version < (2, 7): |
| 695 | jump_forward_offset = jump_back_offset + 4 |
| 696 | return_val_offset1 = self.prev[ |
| 697 | self.prev[self.prev[loop_end_offset]] |
no test coverage detected