[pypy-svn] r6299 - in pypy/branch/pypy-genc/translator: . test

arigo at codespeak.net arigo at codespeak.net
Mon Sep 6 15:53:14 CEST 2004


Author: arigo
Date: Mon Sep  6 15:53:14 2004
New Revision: 6299

Modified:
   pypy/branch/pypy-genc/translator/test/test_ctrans.py
   pypy/branch/pypy-genc/translator/typer.py
Log:
Some more tweaking reference counters.  The resulting C code looks reasonable
now -- it tries hard to minimize the Py_{INC,DEC}REF().

Moved a couple of private tests to test_ctrans.py.  I'll try to figure out
later why you cannot call two test functions 'fn' without the two Translator
instances getting confused.

 --This line, and those below, will be ignored--

M    translator/test/test_ctrans.py
M    translator/typer.py


Modified: pypy/branch/pypy-genc/translator/test/test_ctrans.py
==============================================================================
--- pypy/branch/pypy-genc/translator/test/test_ctrans.py	(original)
+++ pypy/branch/pypy-genc/translator/test/test_ctrans.py	Mon Sep  6 15:53:14 2004
@@ -131,5 +131,24 @@
         call_five = self.getcompiled(snippet.call_five)
         self.assertEquals(call_five(), [5])
 
+    def test_class_defaultattr(self):
+        class K:
+            n = "hello"
+        def class_defaultattr():
+            k = K()
+            k.n += " world"
+            return k.n
+        fn = self.getcompiled(class_defaultattr)
+        self.assertEquals(fn(), "hello world")
+
+    def test_tuple_repr(self):
+        def tuple_repr(x=int, y=object):
+            z = x, y
+            while x:
+                x = x-1
+            return z
+        fn = self.getcompiled(tuple_repr)
+        self.assertEquals(fn(6,'a'), (6,'a'))
+
 if __name__ == '__main__':
     testit.main()

Modified: pypy/branch/pypy-genc/translator/typer.py
==============================================================================
--- pypy/branch/pypy-genc/translator/typer.py	(original)
+++ pypy/branch/pypy-genc/translator/typer.py	Mon Sep  6 15:53:14 2004
@@ -220,8 +220,7 @@
             if to == hltype:
                 yield frm
 
-    def operation(self, opname, args, result=None, errlabel=None,
-                  resulttype=None):
+    def operation(self, opname, args, result=None, errlabel=None):
         "Helper to build the LLOps for a single high-level operation."
         # get the hltypes of the input arguments
         for v in args:
@@ -230,7 +229,7 @@
         directions = [self.convert_from] * len(args)
         # append the hltype of the result
         if result:
-            self.makevar(result, resulttype)
+            self.makevar(result)
             args_t.append(self.hltypes[result])
             directions.append(self.convert_to)
         # enumerate possible signatures until we get a match
@@ -246,13 +245,15 @@
             # correctly extend 'lloperations'.
             if retry:
                 try:
-                    self.operation(opname, args, result, errlabel, resulttype)
+                    self.operation(opname, args, result, errlabel)
                     return
                 except RuntimeError:   # infinite recursion
                     pass
             raise TypingError([opname] + args_t)
-        # check if the answer has an existing well-known answer
-        if resulttype is not None:  # if we are allowed to patch self.llreprs
+        # check for some operations that have an existing well-known answer
+        # that doesn't involve side-effects, so that we can just provide
+        # this answer and not generate any LLOp.
+        if result:
             if llname == 'copy':
                 # patch self.llreprs and we're done
                 llrepr = []
@@ -270,7 +271,8 @@
         for v, v_t, s_t in zip(args, args_t, sig):
             if v_t != s_t:
                 tmp = Variable()
-                self.operation('convert', [v], tmp, resulttype=s_t)
+                self.makevar(tmp, hltype=s_t)
+                self.operation('convert', [v], tmp)
                 v = tmp
             llargs += self.llreprs[v]
         # generate an error label if the operation can fail
@@ -299,39 +301,44 @@
         # generate the exit.args -> target.inputargs copying operations
         to_release_copy = self.to_release
         try:
-            # copy the data, performing any necessary conversion
+            # convert the exit.args to the type expected by the target.inputargs
+            exitargs = []
+            for v, w in zip(exit.args, exit.target.inputargs):
+                self.makevar(v)
+                if self.hltypes[v] != self.hltypes[w]:
+                    tmp = Variable()
+                    self.makevar(tmp, hltype=self.hltypes[w])
+                    self.operation('convert', [v], tmp)
+                    v = tmp
+                exitargs.append(v)
+            # move the data from exit.args to target.inputargs
             # See also remove_direct_loops() for why we don't worry about
-            # the order of the operations
+            # the order of the move operations
             current_refcnt = {}
             needed_refcnt = {}
-            for v, w in zip(exit.args, exit.target.inputargs):
-                self.makevar(v)
-                if self.hltypes[v] == self.hltypes[w]:  # fast case
-                    for x, y in zip(self.llreprs[v], self.llreprs[w]):
-                        self.blockops.append(LLOp('move', [x, y]))
-                    needed_refcnt.setdefault(v, 0)
-                    needed_refcnt[v] += 1
-                else:
-                    self.operation('convert', [v], w)
-                    needed_refcnt.setdefault(w, 0)
-                    needed_refcnt[w] += 1
-            # list all variables that go out of scope: as needing by default
-            # no reference
+            for v, w in zip(exitargs, exit.target.inputargs):
+                for x, y in zip(self.llreprs[v], self.llreprs[w]):
+                    self.blockops.append(LLOp('move', [x, y]))
+                    needed_refcnt.setdefault(x, 0)
+                    needed_refcnt[x] += 1
+            # list all variables that go out of scope: by default
+            # they need no reference, but have one reference.
             for node in self.to_release.getbranch():
-                current_refcnt[node.var] = 1
-                needed_refcnt.setdefault(node.var, 0)
+                for x in self.llreprs[node.var]:
+                    current_refcnt[x] = 1
+                    needed_refcnt.setdefault(x, 0)
             # now adjust all reference counters: first increfs, then decrefs
             # (in case a variable to decref points to the same objects than
             #  another variable to incref).
-            for v, needed in needed_refcnt.items():
-                current_refcnt.setdefault(v, 0)
-                while current_refcnt[v] < needed:
-                    self.blockops.append(LLOp('incref', self.llreprs[v]))
-                    current_refcnt[v] += 1
-            for v, needed in needed_refcnt.items():
-                while current_refcnt[v] > needed:
-                    self.blockops.append(LLOp('decref', self.llreprs[v]))
-                    current_refcnt[v] -= 1
+            for x, needed in needed_refcnt.items():
+                current_refcnt.setdefault(x, 0)
+                while current_refcnt[x] < needed:
+                    self.blockops.append(LLOp('incref', [x]))
+                    current_refcnt[x] += 1
+            for x, needed in needed_refcnt.items():
+                while current_refcnt[x] > needed:
+                    self.blockops.append(LLOp('decref', [x]))
+                    current_refcnt[x] -= 1
             # finally jump to the target block
             self.blockops.append(LLOp('goto', [], self.blockname[exit.target]))
         finally:



More information about the Pypy-commit mailing list