Python 3.6-inspired instruction size cleanup

Revise and generalize for Python 3.6+ instructions vs < 3.6 instuctions.
Used more of the generalized methods in xdis and remove some (but not
all) of the magic numbers.

This is a lot of changes, but not all of the refactoring needed. Much
crap still remains. Also, there are still bugs in handling 3.6 bytecodes.
This commit is contained in:
rocky
2017-10-29 11:46:28 -04:00
parent 5e7632c33e
commit 5df09540b5
4 changed files with 131 additions and 89 deletions

View File

@@ -18,6 +18,7 @@ from uncompyle6 import PYTHON3, IS_PYPY
from uncompyle6.scanners.tok import Token
from xdis.bytecode import op_size
from xdis.magics import py_str2float
from xdis.util import code2num
# The byte code versions we support
PYTHON_VERSIONS = (1.5,
@@ -85,7 +86,8 @@ class Scanner(object):
return True
if self.code[offset] != self.opc.JUMP_ABSOLUTE:
return False
return offset < self.get_target(offset)
# FIXME 0 isn't always correct
return offset < self.get_target(offset, 0)
def get_target(self, pos, op=None):
if op is None:
@@ -95,6 +97,10 @@ class Scanner(object):
target += pos + 3
return target
# FIXME: the below can be removed after xdis version 3.6.1 has been released
def extended_arg_val(self, val):
return val << self.opc.EXTENDED_ARG_SHIFT
def get_argument(self, pos):
arg = self.code[pos+1] + self.code[pos+2] * 256
return arg
@@ -169,13 +175,20 @@ class Scanner(object):
result_offset = None
current_distance = len(code)
extended_arg = 0
for offset in self.op_range(start, end):
op = code[offset]
if op == self.opc.EXTENDED_ARG:
arg = code2num(code, offset+1) | extended_arg
extended_arg = self.extended_arg_val(arg)
continue
if op in instr:
if target is None:
result_offset = offset
else:
dest = self.get_target(offset)
dest = self.get_target(offset, extended_arg)
if dest == target:
current_distance = 0
result_offset = offset
@@ -204,17 +217,31 @@ class Scanner(object):
instr = [instr]
result = []
extended_arg = 0
for offset in self.op_range(start, end):
op = code[offset]
if op == self.opc.EXTENDED_ARG:
arg = code2num(code, offset+1) | extended_arg
extended_arg = self.extended_arg_val(arg)
continue
if op in instr:
if target is None:
result.append(offset)
else:
t = self.get_target(offset)
t = self.get_target(offset, extended_arg)
if include_beyond_target and t >= target:
result.append(offset)
elif t == target:
result.append(offset)
pass
pass
pass
extended_arg = 0
pass
return result
def op_range(self, start, end):