diff options
author | Jeremy Hylton <jeremy@alum.mit.edu> | 2001-08-29 18:09:50 (GMT) |
---|---|---|
committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2001-08-29 18:09:50 (GMT) |
commit | e4e9cd4c01b996430232069970eab9579d71d628 (patch) | |
tree | 7fd388f37150a325aa9b17c239bc7a528b3b4913 /Lib/compiler/pyassem.py | |
parent | 5477f529d6f3b25e51ac6b321a6fe7b28fafe1f4 (diff) | |
download | cpython-e4e9cd4c01b996430232069970eab9579d71d628.zip cpython-e4e9cd4c01b996430232069970eab9579d71d628.tar.gz cpython-e4e9cd4c01b996430232069970eab9579d71d628.tar.bz2 |
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.
Diffstat (limited to 'Lib/compiler/pyassem.py')
-rw-r--r-- | Lib/compiler/pyassem.py | 69 |
1 files changed, 52 insertions, 17 deletions
diff --git a/Lib/compiler/pyassem.py b/Lib/compiler/pyassem.py index 3063b5b..0cdc6ea 100644 --- a/Lib/compiler/pyassem.py +++ b/Lib/compiler/pyassem.py @@ -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): |