From af3d46b35c74d8bdb4f141d72abb86f4cbbc1c3d Mon Sep 17 00:00:00 2001 From: rocky Date: Sat, 24 Jun 2017 06:43:04 -0400 Subject: [PATCH] Use xdis' instruction offset calculation fns.. next_offset, op_size, has_argument --- __pkginfo__.py | 2 +- uncompyle6/scanner.py | 22 ++-------------------- uncompyle6/scanners/scanner2.py | 13 +++++++------ uncompyle6/scanners/scanner3.py | 21 +++++++++++---------- uncompyle6/scanners/scanner30.py | 8 +++++--- uncompyle6/semantics/pysource.py | 27 --------------------------- 6 files changed, 26 insertions(+), 67 deletions(-) diff --git a/__pkginfo__.py b/__pkginfo__.py index 92ed8894..9049f5ec 100644 --- a/__pkginfo__.py +++ b/__pkginfo__.py @@ -40,7 +40,7 @@ entry_points = { ]} ftp_url = None install_requires = ['spark-parser >= 1.6.1, < 1.7.0', - 'xdis >= 3.3.1, < 3.4.0', 'six'] + 'xdis >= 3.4.0, < 3.5.0', 'six'] license = 'MIT' mailing_list = 'python-debugger@googlegroups.com' modname = 'uncompyle6' diff --git a/uncompyle6/scanner.py b/uncompyle6/scanner.py index 67ab4dbf..83e3581b 100755 --- a/uncompyle6/scanner.py +++ b/uncompyle6/scanner.py @@ -16,6 +16,7 @@ import sys from uncompyle6 import PYTHON3, IS_PYPY from uncompyle6.scanners.tok import Token +from xdis.bytecode import op_size # The byte code versions we support PYTHON_VERSIONS = (1.5, @@ -214,9 +215,6 @@ class Scanner(object): result.append(offset) return result - def op_hasArgument(self, op): - return self.op_size(op) > 1 - def op_range(self, start, end): """ Iterate through positions of opcodes, skipping @@ -224,20 +222,7 @@ class Scanner(object): """ while start < end: yield start - start += self.op_size(self.code[start]) - - def next_offset(self, op, offset): - return offset + self.op_size(op) - - def op_size(self, op): - """ - Return size of operator with its arguments - for given opcode . - """ - if op < self.opc.HAVE_ARGUMENT: - return 2 if self.version >= 3.6 else 1 - else: - return 2 if self.version >= 3.6 else 3 + start += op_size(self.code[start], self.opc) def remove_mid_line_ifs(self, ifs): """ @@ -269,9 +254,6 @@ class Scanner(object): self.Token = tokenClass return self.Token -def op_has_argument(op, opc): - return op >= opc.HAVE_ARGUMENT - def parse_fn_counts(argc): return ((argc & 0xFF), (argc >> 8) & 0xFF, (argc >> 16) & 0x7FFF) diff --git a/uncompyle6/scanners/scanner2.py b/uncompyle6/scanners/scanner2.py index b7ad3fe6..6b496a66 100644 --- a/uncompyle6/scanners/scanner2.py +++ b/uncompyle6/scanners/scanner2.py @@ -25,8 +25,9 @@ from __future__ import print_function from collections import namedtuple from array import array -from uncompyle6.scanner import op_has_argument, L65536 +from uncompyle6.scanner import L65536 from xdis.code import iscode +from xdis.bytecode import op_has_argument, op_size from uncompyle6.scanner import Scanner @@ -327,7 +328,7 @@ class Scanner2(Scanner): for i in self.op_range(0, n): op = self.code[i] self.prev.append(i) - if self.op_hasArgument(op): + if op_has_argument(op, self.opc): self.prev.append(i) self.prev.append(i) pass @@ -380,7 +381,7 @@ class Scanner2(Scanner): if elem != code[i]: match = False break - i += self.op_size(code[i]) + i += op_size(code[i], self.opc) if match: i = self.prev[i] @@ -617,7 +618,7 @@ class Scanner2(Scanner): 'start': jump_back+3, 'end': end}) elif op == self.opc.SETUP_EXCEPT: - start = offset + self.op_size(op) + start = offset + op_size(op, self.opc) target = self.get_target(offset, op) end = self.restrict_to_parent(target, parent) if target != end: @@ -641,7 +642,7 @@ class Scanner2(Scanner): setup_except_nest -= 1 elif self.code[end_finally_offset] == self.opc.SETUP_EXCEPT: setup_except_nest += 1 - end_finally_offset += self.op_size(code[end_finally_offset]) + end_finally_offset += op_size(code[end_finally_offset], self.opc) pass # Add the except blocks @@ -842,7 +843,7 @@ class Scanner2(Scanner): else: # We still have the case in 2.7 that the next instruction # is a jump to a SETUP_LOOP target. - next_offset = target + self.op_size(self.code[target]) + next_offset = target + op_size(self.code[target], self.opc) next_op = self.code[next_offset] if self.op_name(next_op) == 'JUMP_FORWARD': jump_target = self.get_target(next_offset, next_op) diff --git a/uncompyle6/scanners/scanner3.py b/uncompyle6/scanners/scanner3.py index 5f29fadf..2974f8d7 100644 --- a/uncompyle6/scanners/scanner3.py +++ b/uncompyle6/scanners/scanner3.py @@ -25,10 +25,11 @@ from __future__ import print_function from collections import namedtuple from array import array -from uncompyle6.scanner import Scanner, op_has_argument +from uncompyle6.scanner import Scanner from xdis.code import iscode -from xdis.bytecode import Bytecode +from xdis.bytecode import Bytecode, op_has_argument, op_size from uncompyle6.scanner import Token, parse_fn_counts +import xdis # Get all the opcodes into globals import xdis.opcodes.opcode_33 as op3 @@ -468,7 +469,7 @@ class Scanner3(Scanner): self.prev = self.prev_op = [0] for offset in self.op_range(0, codelen): op = code[offset] - for _ in range(self.op_size(op)): + for _ in range(op_size(op, self.opc)): self.prev_op.append(offset) def find_jump_targets(self, debug): @@ -518,7 +519,7 @@ class Scanner3(Scanner): oparg = code[offset+1] else: oparg = code[offset+1] + code[offset+2] * 256 - next_offset = self.next_offset(op, offset) + next_offset = xdis.next_offset(op, self.opc, offset) if label is None: if op in op3.hasjrel and op != self.opc.FOR_ITER: @@ -564,7 +565,7 @@ class Scanner3(Scanner): if elem != code[i]: match = False break - i += self.op_size(code[i]) + i += op_size(code[i], self.opc) if match is True: i = self.prev_op[i] @@ -757,7 +758,7 @@ class Scanner3(Scanner): 'start': jump_back+3, 'end': end}) elif op in self.pop_jump_tf: - start = offset + self.op_size(op) + start = offset + op_size(op, self.opc) target = self.get_target(offset) rtarget = self.restrict_to_parent(target, parent) prev_op = self.prev_op @@ -932,9 +933,9 @@ class Scanner3(Scanner): # not from SETUP_EXCEPT next_op = rtarget if code[next_op] == self.opc.POP_BLOCK: - next_op += self.op_size(self.code[next_op]) + next_op += op_size(self.code[next_op], self.opc) if code[next_op] == self.opc.JUMP_ABSOLUTE: - next_op += self.op_size(self.code[next_op]) + next_op += op_size(self.code[next_op], self.opc) if next_op in targets: for try_op in targets[next_op]: come_from_op = code[try_op] @@ -957,12 +958,12 @@ class Scanner3(Scanner): end = self.restrict_to_parent(target, parent) self.fixed_jumps[offset] = end elif op == self.opc.POP_EXCEPT: - next_offset = self.next_offset(op, offset) + next_offset = xdis.next_offset(op, self.opc, offset) target = self.get_target(next_offset) if target > next_offset: next_op = code[next_offset] if (self.opc.JUMP_ABSOLUTE == next_op and - END_FINALLY != code[self.next_offset(next_op, next_offset)]): + END_FINALLY != code[xdis.next_offset(next_op, self.opc, next_offset)]): self.fixed_jumps[next_offset] = target self.except_targets[target] = next_offset diff --git a/uncompyle6/scanners/scanner30.py b/uncompyle6/scanners/scanner30.py index ca86d1dc..38d71810 100644 --- a/uncompyle6/scanners/scanner30.py +++ b/uncompyle6/scanners/scanner30.py @@ -10,6 +10,8 @@ from __future__ import print_function # bytecode verification, verify(), uses JUMP_OPs from here from xdis.opcodes import opcode_30 as opc +from xdis.bytecode import op_size + JUMP_OPs = map(lambda op: opc.opname[op], opc.hasjrel + opc.hasjabs) JUMP_TF = frozenset([opc.JUMP_IF_FALSE, opc.JUMP_IF_TRUE]) @@ -133,7 +135,7 @@ class Scanner30(Scanner3): 'start': jump_back+3, 'end': end}) elif op in JUMP_TF: - start = offset + self.op_size(op) + start = offset + op_size(op, self.opc) target = self.get_target(offset) rtarget = self.restrict_to_parent(target, parent) prev_op = self.prev_op @@ -305,9 +307,9 @@ class Scanner30(Scanner3): # not from SETUP_EXCEPT next_op = rtarget if code[next_op] == self.opc.POP_BLOCK: - next_op += self.op_size(self.code[next_op]) + next_op += op_size(self.code[next_op], self.opc) if code[next_op] == self.opc.JUMP_ABSOLUTE: - next_op += self.op_size(self.code[next_op]) + next_op += op_size(self.code[next_op], self.opc) if next_op in targets: for try_op in targets[next_op]: come_from_op = code[try_op] diff --git a/uncompyle6/semantics/pysource.py b/uncompyle6/semantics/pysource.py index 7b2f8d2c..6d152608 100644 --- a/uncompyle6/semantics/pysource.py +++ b/uncompyle6/semantics/pysource.py @@ -573,33 +573,6 @@ class SourceWalker(GenericASTTraversal, object): node == AST('return_stmt', [AST('ret_expr', [NONE]), Token('RETURN_VALUE')])) - ## The below doesn't work because continue may be the only thing inside an 'else'. For example - # for ... - # if ... - # else: - # continue - # - # def n_continue_stmt(self, node): - # if self.version >= 3.0 and node[0] == 'CONTINUE': - # t = node[0] - # if not t.linestart: - # # Artificially-added "continue" statements derived from JUMP_ABSOLUTE - # # don't have line numbers associated with them. - # # If this is a CONTINUE is to the same target as a JUMP_ABSOLUTE following it, - # # then the "continue" can be suppressed. - # op, offset = t.op, t.offset - # next_offset = self.scanner.next_offset(op, offset) - # scanner = self.scanner - # code = scanner.code - # if next_offset < len(code): - # next_inst = code[next_offset] - # if (scanner.opc.opname[next_inst] == 'JUMP_ABSOLUTE' - # and t.pattr == code[next_offset+1]): - # # Suppress "continue" - # import pdb; pdb.set_trace() - # self.prune() - # self.default(node) - def n_return_stmt(self, node): if self.params['isLambda']: self.preorder(node[0])