Iterate over the instructions in a bytecode string. Generates a sequence of Instruction namedtuples giving the details of each opcode.
(code, linestarts=None, line_offset=0, co_positions=None,
original_code=None, arg_resolver=None)
| 758 | 'END_ASYNC_FOR') # Not really a jump, but it has a "target" |
| 759 | |
| 760 | def _get_instructions_bytes(code, linestarts=None, line_offset=0, co_positions=None, |
| 761 | original_code=None, arg_resolver=None): |
| 762 | """Iterate over the instructions in a bytecode string. |
| 763 | |
| 764 | Generates a sequence of Instruction namedtuples giving the details of each |
| 765 | opcode. |
| 766 | |
| 767 | """ |
| 768 | # Use the basic, unadaptive code for finding labels and actually walking the |
| 769 | # bytecode, since replacements like ENTER_EXECUTOR and INSTRUMENTED_* can |
| 770 | # mess that logic up pretty badly: |
| 771 | original_code = original_code or code |
| 772 | co_positions = co_positions or iter(()) |
| 773 | |
| 774 | starts_line = False |
| 775 | local_line_number = None |
| 776 | line_number = None |
| 777 | for offset, start_offset, op, arg in _unpack_opargs(original_code): |
| 778 | if linestarts is not None: |
| 779 | starts_line = offset in linestarts |
| 780 | if starts_line: |
| 781 | local_line_number = linestarts[offset] |
| 782 | if local_line_number is not None: |
| 783 | line_number = local_line_number + line_offset |
| 784 | else: |
| 785 | line_number = None |
| 786 | positions = Positions(*next(co_positions, ())) |
| 787 | deop = _deoptop(op) |
| 788 | op = code[offset] |
| 789 | |
| 790 | if arg_resolver: |
| 791 | argval, argrepr = arg_resolver.get_argval_argrepr(op, arg, offset) |
| 792 | else: |
| 793 | argval, argrepr = arg, repr(arg) |
| 794 | |
| 795 | caches = _get_cache_size(_all_opname[deop]) |
| 796 | # Advance the co_positions iterator: |
| 797 | for _ in range(caches): |
| 798 | next(co_positions, ()) |
| 799 | |
| 800 | if caches: |
| 801 | cache_info = [] |
| 802 | cache_offset = offset |
| 803 | for name, size in _cache_format[opname[deop]].items(): |
| 804 | data = code[cache_offset + 2: cache_offset + 2 + 2 * size] |
| 805 | cache_offset += size * 2 |
| 806 | cache_info.append((name, size, data)) |
| 807 | else: |
| 808 | cache_info = None |
| 809 | |
| 810 | label = arg_resolver.get_label_for_offset(offset) if arg_resolver else None |
| 811 | yield Instruction(_all_opname[op], op, arg, argval, argrepr, |
| 812 | offset, start_offset, starts_line, line_number, |
| 813 | label, positions, cache_info) |
| 814 | |
| 815 | |
| 816 | def disassemble(co, lasti=-1, *, file=None, show_caches=False, adaptive=False, |
no test coverage detected
searching dependent graphs…