From c3a874220fcebf7241d40d234d325ac3273ff3ae Mon Sep 17 00:00:00 2001 From: Mysterie Date: Thu, 20 Sep 2012 16:37:37 +0200 Subject: [PATCH] Optimisation for bytecode 2.5/2.6 restructuration --- uncompyle2/Scanner25.py | 92 ++++++++++++++++++++++------------------- uncompyle2/Scanner26.py | 78 +++++++++++++++++++--------------- 2 files changed, 94 insertions(+), 76 deletions(-) diff --git a/uncompyle2/Scanner25.py b/uncompyle2/Scanner25.py index 66af8299..8bd50b12 100755 --- a/uncompyle2/Scanner25.py +++ b/uncompyle2/Scanner25.py @@ -85,21 +85,18 @@ class Scanner: ret = self.getOpcodeToDel(i) if ret != None: toDel += ret - if toDel: # degeu a revoir / repenser (tout faire d'un coup? chaud) + if toDel: toDel = sorted(list(set(toDel))) delta = 0 + self.restructCode(toDel) for x in toDel: if self.code[x-delta] >= dis.HAVE_ARGUMENT: self.code.pop(x-delta) - self.restructCode(x-delta) self.code.pop(x-delta) - self.restructCode(x-delta) self.code.pop(x-delta) - self.restructCode(x-delta) delta += 3 else: self.code.pop(x-delta) - self.restructCode(x-delta) delta += 1 # mapping adresses of prev instru @@ -110,8 +107,7 @@ class Scanner: if op >= HAVE_ARGUMENT: self.prev.append(i) self.prev.append(i) - - j = 0 + j = 0 linestarts = self.linestarts self.lines = [] linetuple = namedtuple('linetuple', ['l_no', 'next']) @@ -247,7 +243,7 @@ class Scanner: rv.append(Token(opname, oparg, pattr, offset, linestart = offset in linestartoffsets)) else: rv.append(Token(replace[offset], oparg, pattr, offset, linestart = offset in linestartoffsets)) - + if self.showasm: out = self.out # shortcut for t in rv: @@ -280,7 +276,7 @@ class Scanner: toDel = [i+opsize,i+opsize+1] nameDel = self.get_argument(i+opsize+1) start = i+opsize+1 - end = start + end = start # del LOAD_NAME x while end < len(self.code): end = self.first_instr(end, len(self.code), (LOAD_NAME,LOAD_FAST)) @@ -304,7 +300,7 @@ class Scanner: raise 'TODO' self.code[start+1] = target & 0xFF self.code[start+2] = (target >> 8) & 0xFF - start += self.op_size(PJIF) + start += self.op_size(PJIF) # del DELETE_NAME x start = end while end < len(self.code): @@ -333,7 +329,7 @@ class Scanner: chckDel -= self.op_size(LOAD_NAME) assert self.code[chckDel] in (LOAD_NAME, LOAD_FAST) toDel += [chckDel] - + allStore = self.all_instr(0, i, (STORE_NAME,STORE_FAST)) chckStore = -1 for store in allStore: @@ -365,11 +361,11 @@ class Scanner: self.toChange.append(chckStore) return toDel return None - + def restructRelativeJump(self): """ change relative JUMP_IF_FALSE/TRUE to absolut jump - and remap the target of PJIF/PJIT + and remap the target of PJIF/PJIT """ for i in self.op_range(0, len(self.code)): if(self.code[i] in (PJIF,PJIT)): @@ -389,40 +385,52 @@ class Scanner: raise 'A gerer' self.code[i+1] = target & 0xFF self.code[i+2] = (target >> 8) & 0xFF - - def restructCode(self, i): + + def restructCode(self, listDel): """ - restruct linestarts and jump destination after removing a POP_TOP + restruct linestarts and jump destination after removing bad opcode """ + result = list() - for item in self.linestarts: - if i < item[0]: - result.append((item[0]-1, item[1])) - else: - result.append((item[0], item[1])) + for block in self.linestarts: + startBlock = 0 + for toDel in listDel: + if toDel < block[0]: + startBlock -= self.op_size(self.code[toDel]) + else: + break + result.append((block[0]+startBlock, block[1])) self.linestarts = result for change in self.toChange: - if change > i: - self.toChange[self.toChange.index(change)] -= 1 - for x in self.op_range(0, len(self.code)): - op = self.code[x] - if op >= HAVE_ARGUMENT: - if op in dis.hasjrel: - if x < i and self.get_target(x) > i: - if self.code[x+1]-1 < 0: - self.code[x+2] -= 1 - self.code[x+1] = self.code[x+1]+255 - else: - self.code[x+1] -= 1 - elif op in dis.hasjabs: - if i < self.get_target(x): - if self.code[x+1]-1 < 0: - self.code[x+2] -= 1 - self.code[x+1] = self.code[x+1]+255 - else: - self.code[x+1] -= 1 - + for toDel in listDel: + if change > toDel: + self.toChange[self.toChange.index(change)] -= self.op_size(self.code[toDel]) + else: + break + + for jmp in self.op_range(0, len(self.code)): + op = self.code[jmp] + if op in dis.hasjrel+dis.hasjabs: # jmp + offset = 0 + jmpTarget = self.get_target(jmp) + for toDel in listDel: + if toDel < jmpTarget: + if op in dis.hasjabs: + offset-=self.op_size(self.code[toDel]) + elif jmp < toDel: + offset-=self.op_size(self.code[toDel]) + else: + break + self.restructJump(jmp, offset) + + def restructJump(self, pos, offset): + target = self.get_argument(pos) + offset + if target > 0xFFFF: + raise 'A gerer' + self.code[pos+2] = (target >> 8) & 0xFF + self.code[pos+1] = target & 0xFF + def get_target(self, pos, op=None): if op is None: op = self.code[pos] @@ -434,7 +442,7 @@ class Scanner: def get_argument(self, pos): target = self.code[pos+1] + self.code[pos+2] * 256 return target - + def first_instr(self, start, end, instr, target=None, exact=True): """ Find the first in the block from start to end. diff --git a/uncompyle2/Scanner26.py b/uncompyle2/Scanner26.py index 49088be4..314d81e9 100755 --- a/uncompyle2/Scanner26.py +++ b/uncompyle2/Scanner26.py @@ -76,6 +76,7 @@ class Scanner: names = co.co_names varnames = co.co_varnames self.names = names + print self.linestarts # add instruction to remonde in "toDel" list toDel = [] # add instruction to change in "toChange" list @@ -85,21 +86,18 @@ class Scanner: ret = self.getOpcodeToDel(i) if ret != None: toDel += ret - if toDel: # degeu a revoir / repenser (tout faire d'un coup? chaud) + if toDel: toDel = sorted(list(set(toDel))) delta = 0 + self.restructCode(toDel) for x in toDel: if self.code[x-delta] >= dis.HAVE_ARGUMENT: self.code.pop(x-delta) - self.restructCode(x-delta) self.code.pop(x-delta) - self.restructCode(x-delta) self.code.pop(x-delta) - self.restructCode(x-delta) delta += 3 else: self.code.pop(x-delta) - self.restructCode(x-delta) delta += 1 # mapping adresses of prev instru @@ -110,9 +108,10 @@ class Scanner: if op >= HAVE_ARGUMENT: self.prev.append(i) self.prev.append(i) - - j = 0 + + j = 0 linestarts = self.linestarts + print self.linestarts self.lines = [] linetuple = namedtuple('linetuple', ['l_no', 'next']) linestartoffsets = {a for (a, _) in linestarts} @@ -383,40 +382,51 @@ class Scanner: raise 'A gerer' self.code[i+1] = target & 0xFF self.code[i+2] = (target >> 8) & 0xFF - - def restructCode(self, i): + + def restructCode(self, listDel): """ restruct linestarts and jump destination after removing a POP_TOP """ result = list() - for item in self.linestarts: - if i < item[0]: - result.append((item[0]-1, item[1])) - else: - result.append((item[0], item[1])) + for block in self.linestarts: + startBlock = 0 + for toDel in listDel: + if toDel < block[0]: + startBlock -= self.op_size(self.code[toDel]) + else: + break + result.append((block[0]+startBlock, block[1])) self.linestarts = result for change in self.toChange: - if change > i: - self.toChange[self.toChange.index(change)] -= 1 - for x in self.op_range(0, len(self.code)): - op = self.code[x] - if op >= HAVE_ARGUMENT: - if op in dis.hasjrel: - if x < i and self.get_target(x) > i: - if self.code[x+1]-1 < 0: - self.code[x+2] -= 1 - self.code[x+1] = self.code[x+1]+255 - else: - self.code[x+1] -= 1 - elif op in dis.hasjabs: - if i < self.get_target(x): - if self.code[x+1]-1 < 0: - self.code[x+2] -= 1 - self.code[x+1] = self.code[x+1]+255 - else: - self.code[x+1] -= 1 - + for toDel in listDel: + if change > toDel: + self.toChange[self.toChange.index(change)] -= self.op_size(self.code[toDel]) + else: + break + + for jmp in self.op_range(0, len(self.code)): + op = self.code[jmp] + if op in dis.hasjrel+dis.hasjabs: # jmp + offset = 0 + jmpTarget = self.get_target(jmp) + for toDel in listDel: + if toDel < jmpTarget: + if op in dis.hasjabs: + offset-=self.op_size(self.code[toDel]) + elif jmp < toDel: + offset-=self.op_size(self.code[toDel]) + else: + break + self.restructJump(jmp, offset) + + def restructJump(self, pos, offset): + target = self.get_argument(pos) + offset + if target > 0xFFFF: + raise 'A gerer' + self.code[pos+2] = (target >> 8) & 0xFF + self.code[pos+1] = target & 0xFF + def get_target(self, pos, op=None): if op is None: op = self.code[pos]