mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
Modify name conversion to be (hopefully) a bit more efficient.
Use a dictionary instead of a list to map objects to their offsets in a const/name tuple of a code object. XXX The conversion is perhaps incomplete, in that we shouldn't have to do the list2dict to start.
This commit is contained in:
parent
5477f529d6
commit
e4e9cd4c01
2 changed files with 104 additions and 34 deletions
|
@ -15,6 +15,17 @@ def xxx_sort(l):
|
|||
l.sort(sorter)
|
||||
return l
|
||||
|
||||
def list2dict(l):
|
||||
d = {}
|
||||
for i in range(len(l)):
|
||||
d[l[i]] = i
|
||||
return d
|
||||
|
||||
def dict2list(d):
|
||||
l = [(v, k) for k, v in d.items()]
|
||||
l.sort()
|
||||
return [k for v, k in l]
|
||||
|
||||
class FlowGraph:
|
||||
def __init__(self):
|
||||
self.current = self.entry = Block()
|
||||
|
@ -326,13 +337,14 @@ DONE = "DONE"
|
|||
class PyFlowGraph(FlowGraph):
|
||||
super_init = FlowGraph.__init__
|
||||
|
||||
def __init__(self, name, filename, args=(), optimized=0):
|
||||
def __init__(self, name, filename, args=(), optimized=0, klass=None):
|
||||
self.super_init()
|
||||
self.name = name
|
||||
self.filename = filename
|
||||
self.docstring = None
|
||||
self.args = args # XXX
|
||||
self.argcount = getArgCount(args)
|
||||
self.klass = klass
|
||||
if optimized:
|
||||
self.flags = CO_OPTIMIZED | CO_NEWLOCALS
|
||||
else:
|
||||
|
@ -445,14 +457,25 @@ class PyFlowGraph(FlowGraph):
|
|||
assert self.stage == FLAT
|
||||
self.consts.insert(0, self.docstring)
|
||||
self.sort_cellvars()
|
||||
|
||||
self.c_varnames = list2dict(self.varnames)
|
||||
self.c_names = list2dict(self.names)
|
||||
self.c_consts = list2dict(self.consts)
|
||||
self.c_closure = list2dict(self.closure)
|
||||
|
||||
for i in range(len(self.insts)):
|
||||
t = self.insts[i]
|
||||
if len(t) == 2:
|
||||
opname = t[0]
|
||||
oparg = t[1]
|
||||
opname, oparg = t
|
||||
conv = self._converters.get(opname, None)
|
||||
if conv:
|
||||
self.insts[i] = opname, conv(self, oparg)
|
||||
|
||||
self.varnames = dict2list(self.c_varnames)
|
||||
self.names = dict2list(self.c_names)
|
||||
self.consts = dict2list(self.c_consts)
|
||||
self.closure = dict2list(self.c_closure)
|
||||
|
||||
self.stage = CONV
|
||||
|
||||
def sort_cellvars(self):
|
||||
|
@ -468,12 +491,23 @@ class PyFlowGraph(FlowGraph):
|
|||
self.cellvars = self.cellvars + cells.keys()
|
||||
self.closure = self.cellvars + self.freevars
|
||||
|
||||
def _lookupName(self, name, list):
|
||||
def _lookupName(self, name, dict):
|
||||
i = dict.get(name, None)
|
||||
if i is None:
|
||||
i = dict[name] = len(dict)
|
||||
return i
|
||||
|
||||
def XXX_lookupName(self, name, list):
|
||||
"""Return index of name in list, appending if necessary"""
|
||||
# XXX It should be possible to replace this with some
|
||||
# dictionary operations, but not sure how
|
||||
t = type(name)
|
||||
for i in range(len(list)):
|
||||
# must do a comparison on type first to prevent UnicodeErrors
|
||||
if t == type(list[i]) and list[i] == name:
|
||||
# must do a comparison on type first to prevent UnicodeErrors
|
||||
# not clear that a dictionary would work, because we could
|
||||
# get UnicodeErrors on lookups
|
||||
elt = list[i]
|
||||
if isinstance(elt, t) and elt == name:
|
||||
return i
|
||||
end = len(list)
|
||||
list.append(name)
|
||||
|
@ -483,20 +517,21 @@ class PyFlowGraph(FlowGraph):
|
|||
def _convert_LOAD_CONST(self, arg):
|
||||
if hasattr(arg, 'getCode'):
|
||||
arg = arg.getCode()
|
||||
return self._lookupName(arg, self.consts)
|
||||
return self._lookupName(arg, self.c_consts)
|
||||
|
||||
def _convert_LOAD_FAST(self, arg):
|
||||
self._lookupName(arg, self.names)
|
||||
return self._lookupName(arg, self.varnames)
|
||||
self._lookupName(arg, self.c_names)
|
||||
return self._lookupName(arg, self.c_varnames)
|
||||
_convert_STORE_FAST = _convert_LOAD_FAST
|
||||
_convert_DELETE_FAST = _convert_LOAD_FAST
|
||||
|
||||
def _convert_LOAD_NAME(self, arg):
|
||||
return self._lookupName(arg, self.names)
|
||||
return self._lookupName(arg, self.c_names)
|
||||
|
||||
def _convert_NAME(self, arg):
|
||||
self._lookupName(arg, self.varnames)
|
||||
return self._lookupName(arg, self.names)
|
||||
if self.klass is None:
|
||||
self._lookupName(arg, self.c_varnames)
|
||||
return self._lookupName(arg, self.c_names)
|
||||
_convert_STORE_NAME = _convert_NAME
|
||||
_convert_DELETE_NAME = _convert_NAME
|
||||
_convert_IMPORT_NAME = _convert_NAME
|
||||
|
@ -509,15 +544,15 @@ class PyFlowGraph(FlowGraph):
|
|||
_convert_DELETE_GLOBAL = _convert_NAME
|
||||
|
||||
def _convert_DEREF(self, arg):
|
||||
self._lookupName(arg, self.names)
|
||||
self._lookupName(arg, self.varnames)
|
||||
return self._lookupName(arg, self.closure)
|
||||
self._lookupName(arg, self.c_names)
|
||||
self._lookupName(arg, self.c_varnames)
|
||||
return self._lookupName(arg, self.c_closure)
|
||||
_convert_LOAD_DEREF = _convert_DEREF
|
||||
_convert_STORE_DEREF = _convert_DEREF
|
||||
|
||||
def _convert_LOAD_CLOSURE(self, arg):
|
||||
self._lookupName(arg, self.varnames)
|
||||
return self._lookupName(arg, self.closure)
|
||||
self._lookupName(arg, self.c_varnames)
|
||||
return self._lookupName(arg, self.c_closure)
|
||||
|
||||
_cmp = list(dis.cmp_op)
|
||||
def _convert_COMPARE_OP(self, arg):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue