Optimisation for bytecode 2.5/2.6 restructuration

This commit is contained in:
Mysterie
2012-09-20 16:37:37 +02:00
parent 1e2b896134
commit c3a874220f
2 changed files with 94 additions and 76 deletions

View File

@@ -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.

View File

@@ -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]