[pypy-svn] r20247 - in pypy/branch/somepbc-refactoring/pypy: annotation rpython/test tool translator/test

arigo at codespeak.net arigo at codespeak.net
Fri Nov 25 18:21:03 CET 2005


Author: arigo
Date: Fri Nov 25 18:21:01 2005
New Revision: 20247

Modified:
   pypy/branch/somepbc-refactoring/pypy/annotation/policy.py
   pypy/branch/somepbc-refactoring/pypy/annotation/specialize.py
   pypy/branch/somepbc-refactoring/pypy/rpython/test/test_rpbc.py
   pypy/branch/somepbc-refactoring/pypy/tool/cache.py
   pypy/branch/somepbc-refactoring/pypy/translator/test/test_annrpython.py
Log:
(mwh, arigo, pedronis)

RTemoved support for memo functions with two pbcs args, it did
not solve the case we are interested in: Cache.getorbuild.

Introduced instead a new specialisation methodmemo, it does
memoisation wrt both of the 2 supported and expected
arguments and specialises wrt the type of the first argument.

test_call_memoized_cache passes now.



Modified: pypy/branch/somepbc-refactoring/pypy/annotation/policy.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/annotation/policy.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/annotation/policy.py	Fri Nov 25 18:21:01 2005
@@ -1,6 +1,7 @@
 # base annotation policy for overrides and specialization
-from pypy.annotation.specialize import memo, default_specialize as default
+from pypy.annotation.specialize import default_specialize as default
 from pypy.annotation.specialize import argtype, argvalue
+from pypy.annotation.specialize import memo, methodmemo
 # for some reason, model must be imported first,
 # or we create a cycle.
 from pypy.annotation import model as annmodel
@@ -50,6 +51,7 @@
 
     default_specialize = staticmethod(default)
     specialize__memo = staticmethod(memo)
+    specialize__methodmemo = staticmethod(methodmemo)
     specialize__arg0 = staticmethod(argvalue(0))
     specialize__argtype0 = staticmethod(argtype(0))
     specialize__arg1 = staticmethod(argvalue(1))

Modified: pypy/branch/somepbc-refactoring/pypy/annotation/specialize.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/annotation/specialize.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/annotation/specialize.py	Fri Nov 25 18:21:01 2005
@@ -64,15 +64,10 @@
                 return s    # we will probably get more possible args later
             raise Exception("memo call: argument must be a class or a frozen "
                             "PBC, got %r" % (s,))
-    if len(arglist_s) == 1:
-        return memo_one_argument(funcdesc, *arglist_s)
-    elif len(arglist_s) == 2:
-        return memo_two_arguments(funcdesc, *arglist_s)
-    else:
-        raise Exception("memo call: only 1 or 2 arguments functions supported"
+    if len(arglist_s) != 1:
+        raise Exception("memo call: only 1 argument functions supported"
                         " at the moment (%r)" % (funcdesc,))
-
-def memo_one_argument(funcdesc, s):
+    s, = arglist_s
     from pypy.annotation.model import SomeImpossibleValue
     func = funcdesc.pyobj
     if func is None:
@@ -98,22 +93,39 @@
     return funcdesc.cachedgraph('memo1', alt_name='memo_%s' % funcdesc.name, 
                                          builder=builder)
 
-def memo_two_arguments(funcdesc, s1, s2):
+def methodmemo(funcdesc, arglist_s):
+    """NOT_RPYTHON"""
+    from pypy.annotation.model import SomePBC, SomeImpossibleValue
+    # call the function now, and collect possible results
+    for s in arglist_s:
+        if not isinstance(s, SomePBC):
+            if isinstance(s, SomeImpossibleValue):
+                return s    # we will probably get more possible args later
+            raise Exception("method-memo call: argument must be a class or"
+                            " a frozen PBC, got %r" % (s,))
+    if len(arglist_s) != 2:
+        raise Exception("method-memo call: expected  2 arguments function" 
+                        " at the moment (%r)" % (funcdesc,))
     from pypy.annotation.model import SomeImpossibleValue
     from pypy.annotation.description import FrozenDesc
     func = funcdesc.pyobj
     if func is None:
-        raise Exception("memo call: no Python function object to call (%r)" %
-                        (funcdesc,))
+        raise Exception("method-memo call: no Python function object to call"
+                        " (%r)" % (funcdesc,))
     # compute the concrete results and store them directly on the descs,
     # using a strange attribute name.  The goal is to store in the pbcs of
     # 's1' under the common 'attrname' a reader function; each reader function
     # will read a field 'attrname2' from the pbcs of 's2', where 'attrname2'
-    # differs for each pbc of 's1'.
-    attrname = '$memoreader%d_%s' % (uid(funcdesc), funcdesc.name)
+    # differs for each pbc of 's1'. This is all specialized also
+    # considering the type of s1 to support return value 
+    # polymorphism.
+    s1, s2 = arglist_s
+    s1_type = s1.knowntype
+    memosig = "%d_%d_%s" % (uid(funcdesc), uid(s1_type), funcdesc.name)
+
+    attrname = '$memoreader%s' % memosig 
     for desc1 in s1.descriptions:
-        attrname2 = '$memofield%d_%d_%s' % (uid(funcdesc), uid(desc1),
-                                            funcdesc.name)
+        attrname2 = '$memofield%d_%s' % (uid(desc1), memosig)
         s_reader = desc1.s_read_attribute(attrname)
         if isinstance(s_reader, SomeImpossibleValue):
             # first time we see this 'desc1': sanity-check 'desc1' and
@@ -121,7 +133,8 @@
             assert isinstance(desc1, FrozenDesc), (
                 "XXX not implemented: memo call with a class as first arg")
             if desc1.pyobj is None:
-                raise Exception("memo call with a class or PBC that has no "
+                raise Exception("method-memo call with a class or PBC"
+                                " that has no "
                                 "corresponding Python object (%r)" % (desc1,))
             def reader(y, attrname2=attrname2):
                 return getattr(y, attrname2)
@@ -131,7 +144,8 @@
             if isinstance(s_result, SomeImpossibleValue):
                 # first time we see this 'desc1+desc2' combination
                 if desc2.pyobj is None:
-                    raise Exception("memo call with a class or PBC that has no "
+                    raise Exception("method-memo call with a class or PBC"
+                                  " that has no "
                                   "corresponding Python object (%r)" % (desc2,))
                 # concrete call, to get the concrete result
                 result = func(desc1.pyobj, desc2.pyobj)
@@ -146,7 +160,7 @@
         return reader_fn(y)
     def builder(translator, func):
         return translator.buildflowgraph(memoized)   # instead of 'func'
-    return funcdesc.cachedgraph('memo2', alt_name='memo_%s' % funcdesc.name, 
+    return funcdesc.cachedgraph(s1_type, alt_name='memo_%s' % funcdesc.name, 
                                          builder=builder)
 
 def argvalue(i):

Modified: pypy/branch/somepbc-refactoring/pypy/rpython/test/test_rpbc.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/rpython/test/test_rpbc.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/rpython/test/test_rpbc.py	Fri Nov 25 18:21:01 2005
@@ -260,36 +260,6 @@
     res = interpret(f1, [1]) 
     assert res == 3
     
-def test_call_memoized_function_2():
-    fr1 = Freezing()
-    fr2 = Freezing()
-    br1 = Freezing(); br1.value = 'a'
-    br2 = Freezing(); br2.value = 'b'
-    def getorbuild(key1, key2):
-        a = 1
-        b = 100
-        if key1 is fr1:
-            result = eval("%s+2" % key2.value)
-        else:
-            result = eval("%s+6" % key2.value)
-        return result
-    getorbuild._annspecialcase_ = "specialize:memo"
-
-    def f1(i):
-        if i > 0:
-            fr = fr1
-        else:
-            fr = fr2
-        if i % 2 == 0:
-            br = br1
-        else:
-            br = br2
-        return getorbuild(fr, br)
-
-    for check in [-1, 0, 1, 2]:
-        res = interpret(f1, [check])
-        assert res == f1(check)
-
 def test_call_memoized_cache():
 
     # this test checks that we add a separate field 

Modified: pypy/branch/somepbc-refactoring/pypy/tool/cache.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/tool/cache.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/tool/cache.py	Fri Nov 25 18:21:01 2005
@@ -37,7 +37,7 @@
             result = self._build(key)
             self.content[key] = result
             return result
-    getorbuild._annspecialcase_ = "specialize:memo"
+    getorbuild._annspecialcase_ = "specialize:methodmemo"
 
     def _freeze_(self):
         # needs to be SomePBC, but otherwise we can't really freeze the

Modified: pypy/branch/somepbc-refactoring/pypy/translator/test/test_annrpython.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/translator/test/test_annrpython.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/translator/test/test_annrpython.py	Fri Nov 25 18:21:01 2005
@@ -1780,36 +1780,6 @@
         s = a.build_types(f1, [int])
         assert s.knowntype == int
 
-    def test_call_memoized_function_2(self):
-        fr1 = Freezing()
-        fr2 = Freezing()
-        br1 = Freezing(); br1.value = 'a'
-        br2 = Freezing(); br2.value = 'b'
-        def getorbuild(key1, key2):
-            a = 1
-            b = 100
-            if key1 is fr1:
-                result = eval("%s+2" % key2.value)
-            else:
-                result = eval("%s+6" % key2.value)
-            return result
-        getorbuild._annspecialcase_ = "specialize:memo"
-
-        def f1(i):
-            if i > 0:
-                fr = fr1
-            else:
-                fr = fr2
-            if i % 2 == 0:
-                br = br1
-            else:
-                br = br2
-            return getorbuild(fr, br)
-
-        a = self.RPythonAnnotator()
-        s = a.build_types(f1, [int])
-        assert s.knowntype == int
-
 def g(n):
     return [0,1,2,n]
 



More information about the Pypy-commit mailing list