You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-02 16:44:46 +08:00
Optimisation for bytecode 2.5/2.6 restructuration
This commit is contained in:
@@ -85,21 +85,18 @@ class Scanner:
|
|||||||
ret = self.getOpcodeToDel(i)
|
ret = self.getOpcodeToDel(i)
|
||||||
if ret != None:
|
if ret != None:
|
||||||
toDel += ret
|
toDel += ret
|
||||||
if toDel: # degeu a revoir / repenser (tout faire d'un coup? chaud)
|
if toDel:
|
||||||
toDel = sorted(list(set(toDel)))
|
toDel = sorted(list(set(toDel)))
|
||||||
delta = 0
|
delta = 0
|
||||||
|
self.restructCode(toDel)
|
||||||
for x in toDel:
|
for x in toDel:
|
||||||
if self.code[x-delta] >= dis.HAVE_ARGUMENT:
|
if self.code[x-delta] >= dis.HAVE_ARGUMENT:
|
||||||
self.code.pop(x-delta)
|
self.code.pop(x-delta)
|
||||||
self.restructCode(x-delta)
|
|
||||||
self.code.pop(x-delta)
|
self.code.pop(x-delta)
|
||||||
self.restructCode(x-delta)
|
|
||||||
self.code.pop(x-delta)
|
self.code.pop(x-delta)
|
||||||
self.restructCode(x-delta)
|
|
||||||
delta += 3
|
delta += 3
|
||||||
else:
|
else:
|
||||||
self.code.pop(x-delta)
|
self.code.pop(x-delta)
|
||||||
self.restructCode(x-delta)
|
|
||||||
delta += 1
|
delta += 1
|
||||||
|
|
||||||
# mapping adresses of prev instru
|
# mapping adresses of prev instru
|
||||||
@@ -110,8 +107,7 @@ class Scanner:
|
|||||||
if op >= HAVE_ARGUMENT:
|
if op >= HAVE_ARGUMENT:
|
||||||
self.prev.append(i)
|
self.prev.append(i)
|
||||||
self.prev.append(i)
|
self.prev.append(i)
|
||||||
|
j = 0
|
||||||
j = 0
|
|
||||||
linestarts = self.linestarts
|
linestarts = self.linestarts
|
||||||
self.lines = []
|
self.lines = []
|
||||||
linetuple = namedtuple('linetuple', ['l_no', 'next'])
|
linetuple = namedtuple('linetuple', ['l_no', 'next'])
|
||||||
@@ -247,7 +243,7 @@ class Scanner:
|
|||||||
rv.append(Token(opname, oparg, pattr, offset, linestart = offset in linestartoffsets))
|
rv.append(Token(opname, oparg, pattr, offset, linestart = offset in linestartoffsets))
|
||||||
else:
|
else:
|
||||||
rv.append(Token(replace[offset], oparg, pattr, offset, linestart = offset in linestartoffsets))
|
rv.append(Token(replace[offset], oparg, pattr, offset, linestart = offset in linestartoffsets))
|
||||||
|
|
||||||
if self.showasm:
|
if self.showasm:
|
||||||
out = self.out # shortcut
|
out = self.out # shortcut
|
||||||
for t in rv:
|
for t in rv:
|
||||||
@@ -280,7 +276,7 @@ class Scanner:
|
|||||||
toDel = [i+opsize,i+opsize+1]
|
toDel = [i+opsize,i+opsize+1]
|
||||||
nameDel = self.get_argument(i+opsize+1)
|
nameDel = self.get_argument(i+opsize+1)
|
||||||
start = i+opsize+1
|
start = i+opsize+1
|
||||||
end = start
|
end = start
|
||||||
# del LOAD_NAME x
|
# del LOAD_NAME x
|
||||||
while end < len(self.code):
|
while end < len(self.code):
|
||||||
end = self.first_instr(end, len(self.code), (LOAD_NAME,LOAD_FAST))
|
end = self.first_instr(end, len(self.code), (LOAD_NAME,LOAD_FAST))
|
||||||
@@ -304,7 +300,7 @@ class Scanner:
|
|||||||
raise 'TODO'
|
raise 'TODO'
|
||||||
self.code[start+1] = target & 0xFF
|
self.code[start+1] = target & 0xFF
|
||||||
self.code[start+2] = (target >> 8) & 0xFF
|
self.code[start+2] = (target >> 8) & 0xFF
|
||||||
start += self.op_size(PJIF)
|
start += self.op_size(PJIF)
|
||||||
# del DELETE_NAME x
|
# del DELETE_NAME x
|
||||||
start = end
|
start = end
|
||||||
while end < len(self.code):
|
while end < len(self.code):
|
||||||
@@ -333,7 +329,7 @@ class Scanner:
|
|||||||
chckDel -= self.op_size(LOAD_NAME)
|
chckDel -= self.op_size(LOAD_NAME)
|
||||||
assert self.code[chckDel] in (LOAD_NAME, LOAD_FAST)
|
assert self.code[chckDel] in (LOAD_NAME, LOAD_FAST)
|
||||||
toDel += [chckDel]
|
toDel += [chckDel]
|
||||||
|
|
||||||
allStore = self.all_instr(0, i, (STORE_NAME,STORE_FAST))
|
allStore = self.all_instr(0, i, (STORE_NAME,STORE_FAST))
|
||||||
chckStore = -1
|
chckStore = -1
|
||||||
for store in allStore:
|
for store in allStore:
|
||||||
@@ -365,11 +361,11 @@ class Scanner:
|
|||||||
self.toChange.append(chckStore)
|
self.toChange.append(chckStore)
|
||||||
return toDel
|
return toDel
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def restructRelativeJump(self):
|
def restructRelativeJump(self):
|
||||||
"""
|
"""
|
||||||
change relative JUMP_IF_FALSE/TRUE to absolut jump
|
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)):
|
for i in self.op_range(0, len(self.code)):
|
||||||
if(self.code[i] in (PJIF,PJIT)):
|
if(self.code[i] in (PJIF,PJIT)):
|
||||||
@@ -389,40 +385,52 @@ class Scanner:
|
|||||||
raise 'A gerer'
|
raise 'A gerer'
|
||||||
self.code[i+1] = target & 0xFF
|
self.code[i+1] = target & 0xFF
|
||||||
self.code[i+2] = (target >> 8) & 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()
|
result = list()
|
||||||
for item in self.linestarts:
|
for block in self.linestarts:
|
||||||
if i < item[0]:
|
startBlock = 0
|
||||||
result.append((item[0]-1, item[1]))
|
for toDel in listDel:
|
||||||
else:
|
if toDel < block[0]:
|
||||||
result.append((item[0], item[1]))
|
startBlock -= self.op_size(self.code[toDel])
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
result.append((block[0]+startBlock, block[1]))
|
||||||
self.linestarts = result
|
self.linestarts = result
|
||||||
|
|
||||||
for change in self.toChange:
|
for change in self.toChange:
|
||||||
if change > i:
|
for toDel in listDel:
|
||||||
self.toChange[self.toChange.index(change)] -= 1
|
if change > toDel:
|
||||||
for x in self.op_range(0, len(self.code)):
|
self.toChange[self.toChange.index(change)] -= self.op_size(self.code[toDel])
|
||||||
op = self.code[x]
|
else:
|
||||||
if op >= HAVE_ARGUMENT:
|
break
|
||||||
if op in dis.hasjrel:
|
|
||||||
if x < i and self.get_target(x) > i:
|
for jmp in self.op_range(0, len(self.code)):
|
||||||
if self.code[x+1]-1 < 0:
|
op = self.code[jmp]
|
||||||
self.code[x+2] -= 1
|
if op in dis.hasjrel+dis.hasjabs: # jmp
|
||||||
self.code[x+1] = self.code[x+1]+255
|
offset = 0
|
||||||
else:
|
jmpTarget = self.get_target(jmp)
|
||||||
self.code[x+1] -= 1
|
for toDel in listDel:
|
||||||
elif op in dis.hasjabs:
|
if toDel < jmpTarget:
|
||||||
if i < self.get_target(x):
|
if op in dis.hasjabs:
|
||||||
if self.code[x+1]-1 < 0:
|
offset-=self.op_size(self.code[toDel])
|
||||||
self.code[x+2] -= 1
|
elif jmp < toDel:
|
||||||
self.code[x+1] = self.code[x+1]+255
|
offset-=self.op_size(self.code[toDel])
|
||||||
else:
|
else:
|
||||||
self.code[x+1] -= 1
|
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):
|
def get_target(self, pos, op=None):
|
||||||
if op is None:
|
if op is None:
|
||||||
op = self.code[pos]
|
op = self.code[pos]
|
||||||
@@ -434,7 +442,7 @@ class Scanner:
|
|||||||
def get_argument(self, pos):
|
def get_argument(self, pos):
|
||||||
target = self.code[pos+1] + self.code[pos+2] * 256
|
target = self.code[pos+1] + self.code[pos+2] * 256
|
||||||
return target
|
return target
|
||||||
|
|
||||||
def first_instr(self, start, end, instr, target=None, exact=True):
|
def first_instr(self, start, end, instr, target=None, exact=True):
|
||||||
"""
|
"""
|
||||||
Find the first <instr> in the block from start to end.
|
Find the first <instr> in the block from start to end.
|
||||||
|
@@ -76,6 +76,7 @@ class Scanner:
|
|||||||
names = co.co_names
|
names = co.co_names
|
||||||
varnames = co.co_varnames
|
varnames = co.co_varnames
|
||||||
self.names = names
|
self.names = names
|
||||||
|
print self.linestarts
|
||||||
# add instruction to remonde in "toDel" list
|
# add instruction to remonde in "toDel" list
|
||||||
toDel = []
|
toDel = []
|
||||||
# add instruction to change in "toChange" list
|
# add instruction to change in "toChange" list
|
||||||
@@ -85,21 +86,18 @@ class Scanner:
|
|||||||
ret = self.getOpcodeToDel(i)
|
ret = self.getOpcodeToDel(i)
|
||||||
if ret != None:
|
if ret != None:
|
||||||
toDel += ret
|
toDel += ret
|
||||||
if toDel: # degeu a revoir / repenser (tout faire d'un coup? chaud)
|
if toDel:
|
||||||
toDel = sorted(list(set(toDel)))
|
toDel = sorted(list(set(toDel)))
|
||||||
delta = 0
|
delta = 0
|
||||||
|
self.restructCode(toDel)
|
||||||
for x in toDel:
|
for x in toDel:
|
||||||
if self.code[x-delta] >= dis.HAVE_ARGUMENT:
|
if self.code[x-delta] >= dis.HAVE_ARGUMENT:
|
||||||
self.code.pop(x-delta)
|
self.code.pop(x-delta)
|
||||||
self.restructCode(x-delta)
|
|
||||||
self.code.pop(x-delta)
|
self.code.pop(x-delta)
|
||||||
self.restructCode(x-delta)
|
|
||||||
self.code.pop(x-delta)
|
self.code.pop(x-delta)
|
||||||
self.restructCode(x-delta)
|
|
||||||
delta += 3
|
delta += 3
|
||||||
else:
|
else:
|
||||||
self.code.pop(x-delta)
|
self.code.pop(x-delta)
|
||||||
self.restructCode(x-delta)
|
|
||||||
delta += 1
|
delta += 1
|
||||||
|
|
||||||
# mapping adresses of prev instru
|
# mapping adresses of prev instru
|
||||||
@@ -110,9 +108,10 @@ class Scanner:
|
|||||||
if op >= HAVE_ARGUMENT:
|
if op >= HAVE_ARGUMENT:
|
||||||
self.prev.append(i)
|
self.prev.append(i)
|
||||||
self.prev.append(i)
|
self.prev.append(i)
|
||||||
|
|
||||||
j = 0
|
j = 0
|
||||||
linestarts = self.linestarts
|
linestarts = self.linestarts
|
||||||
|
print self.linestarts
|
||||||
self.lines = []
|
self.lines = []
|
||||||
linetuple = namedtuple('linetuple', ['l_no', 'next'])
|
linetuple = namedtuple('linetuple', ['l_no', 'next'])
|
||||||
linestartoffsets = {a for (a, _) in linestarts}
|
linestartoffsets = {a for (a, _) in linestarts}
|
||||||
@@ -383,40 +382,51 @@ class Scanner:
|
|||||||
raise 'A gerer'
|
raise 'A gerer'
|
||||||
self.code[i+1] = target & 0xFF
|
self.code[i+1] = target & 0xFF
|
||||||
self.code[i+2] = (target >> 8) & 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 a POP_TOP
|
||||||
"""
|
"""
|
||||||
result = list()
|
result = list()
|
||||||
for item in self.linestarts:
|
for block in self.linestarts:
|
||||||
if i < item[0]:
|
startBlock = 0
|
||||||
result.append((item[0]-1, item[1]))
|
for toDel in listDel:
|
||||||
else:
|
if toDel < block[0]:
|
||||||
result.append((item[0], item[1]))
|
startBlock -= self.op_size(self.code[toDel])
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
result.append((block[0]+startBlock, block[1]))
|
||||||
self.linestarts = result
|
self.linestarts = result
|
||||||
|
|
||||||
for change in self.toChange:
|
for change in self.toChange:
|
||||||
if change > i:
|
for toDel in listDel:
|
||||||
self.toChange[self.toChange.index(change)] -= 1
|
if change > toDel:
|
||||||
for x in self.op_range(0, len(self.code)):
|
self.toChange[self.toChange.index(change)] -= self.op_size(self.code[toDel])
|
||||||
op = self.code[x]
|
else:
|
||||||
if op >= HAVE_ARGUMENT:
|
break
|
||||||
if op in dis.hasjrel:
|
|
||||||
if x < i and self.get_target(x) > i:
|
for jmp in self.op_range(0, len(self.code)):
|
||||||
if self.code[x+1]-1 < 0:
|
op = self.code[jmp]
|
||||||
self.code[x+2] -= 1
|
if op in dis.hasjrel+dis.hasjabs: # jmp
|
||||||
self.code[x+1] = self.code[x+1]+255
|
offset = 0
|
||||||
else:
|
jmpTarget = self.get_target(jmp)
|
||||||
self.code[x+1] -= 1
|
for toDel in listDel:
|
||||||
elif op in dis.hasjabs:
|
if toDel < jmpTarget:
|
||||||
if i < self.get_target(x):
|
if op in dis.hasjabs:
|
||||||
if self.code[x+1]-1 < 0:
|
offset-=self.op_size(self.code[toDel])
|
||||||
self.code[x+2] -= 1
|
elif jmp < toDel:
|
||||||
self.code[x+1] = self.code[x+1]+255
|
offset-=self.op_size(self.code[toDel])
|
||||||
else:
|
else:
|
||||||
self.code[x+1] -= 1
|
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):
|
def get_target(self, pos, op=None):
|
||||||
if op is None:
|
if op is None:
|
||||||
op = self.code[pos]
|
op = self.code[pos]
|
||||||
|
Reference in New Issue
Block a user