]> granicus.if.org Git - python/commitdiff
Modify name conversion to be (hopefully) a bit more efficient.
authorJeremy Hylton <jeremy@alum.mit.edu>
Wed, 29 Aug 2001 18:09:50 +0000 (18:09 +0000)
committerJeremy Hylton <jeremy@alum.mit.edu>
Wed, 29 Aug 2001 18:09:50 +0000 (18:09 +0000)
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.

Lib/compiler/pyassem.py
Tools/compiler/compiler/pyassem.py

index 3063b5b253b5b636933150125d4890f5937ab1d3..0cdc6ea5ae0c9c8186a91950a9cc25e50245da6a 100644 (file)
@@ -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):
index 3063b5b253b5b636933150125d4890f5937ab1d3..0cdc6ea5ae0c9c8186a91950a9cc25e50245da6a 100644 (file)
@@ -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):