[pypy-svn] r20223 - in pypy/branch/somepbc-refactoring/pypy: annotation rpython rpython/lltypesystem

arigo at codespeak.net arigo at codespeak.net
Thu Nov 24 23:07:40 CET 2005


Author: arigo
Date: Thu Nov 24 23:07:39 2005
New Revision: 20223

Modified:
   pypy/branch/somepbc-refactoring/pypy/annotation/description.py
   pypy/branch/somepbc-refactoring/pypy/annotation/specialize.py
   pypy/branch/somepbc-refactoring/pypy/rpython/lltypesystem/rpbc.py
   pypy/branch/somepbc-refactoring/pypy/rpython/normalizecalls.py
   pypy/branch/somepbc-refactoring/pypy/rpython/rmodel.py
Log:
(pedronis, arigo)

supporting again specialize:memo.  The code is now entierely contained
in one page of specialize.py, which is nice.

However, we have just found out that memoizing with a single PBC argument
is not enough to support multiple spaces, so that nice page will have to
be expanded again...  but probably still only in specialize.py.



Modified: pypy/branch/somepbc-refactoring/pypy/annotation/description.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/annotation/description.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/annotation/description.py	Thu Nov 24 23:07:39 2005
@@ -153,15 +153,19 @@
         self.specializer = specializer
         self._cache = {}     # convenience for the specializer
 
-    def buildgraph(self):
+    def buildgraph(self, alternate_fnobj=None, alternate_name=None):
+        fnobj = alternate_fnobj or self.pyobj
+        name = alternate_name or self.name
         translator = self.bookkeeper.annotator.translator
-        return translator.buildflowgraph(self.pyobj)
+        graph = translator.buildflowgraph(fnobj)
+        graph.name = name
+        return graph
 
-    def cachedgraph(self, key):
+    def cachedgraph(self, key, alternate_fnobj=None, alternate_name=None):
         try:
             return self._cache[key]
         except KeyError:
-            graph = self.buildgraph()
+            graph = self.buildgraph(alternate_fnobj, alternate_name)
             self._cache[key] = graph
             return graph
 
@@ -402,6 +406,10 @@
             raise TypeError("classdict should not contain %r" % (obj,))
         return s_value
 
+    def create_new_attribute(self, name, value):
+        assert name not in self.classdict, "name clash: %r" % (name,)
+        self.classdict[name] = Constant(value)
+
     def find_source_for(self, name):
         if name in self.classdict:
             return self
@@ -484,6 +492,21 @@
             return s_ImpossibleValue
         else:
             return self.bookkeeper.immutablevalue(value)
+    
+    def create_new_attribute(self, name, value):
+        try:
+            self.read_attribute(name)
+        except AttributeError:
+            pass
+        else:
+            raise AssertionError("name clash: %r" % (name,))
+        def extended_read_attribute(attr):
+            if attr == name:
+                return value
+            else:
+                return previous_read_attribute(attr)
+        previous_read_attribute = self.read_attribute
+        self.read_attribute = extended_read_attribute
 
 
 class MethodOfFrozenDesc(Desc):

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	Thu Nov 24 23:07:39 2005
@@ -1,5 +1,6 @@
 # specialization support
 import types
+from pypy.tool.uid import uid
 
 def default_specialize(funcdesc, args_s):
     argnames, vararg, kwarg = funcdesc.signature
@@ -23,48 +24,39 @@
 
 def memo(funcdesc, arglist_s):
     """NOT_RPYTHON"""
-    from pypy.annotation.model import unionof
+    from pypy.annotation.model import unionof, SomePBC, SomeImpossibleValue
     # call the function now, and collect possible results
     func = funcdesc.pyobj
     if func is None:
         raise Exception("memo call: no Python function object to call (%r)" %
                         (funcdesc,))
-    possible_results = []
-    for arglist in possible_arguments(arglist_s):
-        result = func(*arglist)
-        possible_results.append(funcdesc.bookkeeper.immutablevalue(result))
-    return unionof(*possible_results)
-
-def possible_values_of(s):
-    from pypy.annotation.model import SomeBool, SomePBC
-    if s.is_constant():
-        return [s.const]
-    elif isinstance(s, SomePBC):
-        result = []
-        for desc in s.descriptions:
+    if len(arglist_s) != 1:
+        raise Exception("memo call: only one-argument functions supported"
+                        " at the moment (%r)" % (funcdesc,))
+    s = arglist_s[0]
+    if not isinstance(s, SomePBC):
+        if isinstance(s, SomeImpossibleValue):
+            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,))
+    # compute the concrete result and store them directly on the descs,
+    # using a strange attribute name
+    attrname = '$memo_%s_%d' % (funcdesc.name, uid(funcdesc))
+    for desc in s.descriptions:
+        s_result = desc.s_read_attribute(attrname)
+        if isinstance(s_result, SomeImpossibleValue):
+            # first time we see this 'desc'
             if desc.pyobj is None:
-                raise Exception("memo call with a PBC that has no "
+                raise Exception("memo call with a class or PBC that has no "
                                 "corresponding Python object (%r)" % (desc,))
-            result.append(desc.pyobj)
-        return result
-    elif isinstance(s, SomeBool):
-        return [False, True]
-    else:
-        raise ValueError, "memo call with a non-constant arg %r" % (s,)
+            result = func(desc.pyobj)
+            s_result = funcdesc.bookkeeper.immutablevalue(result)
+            desc.create_new_attribute(attrname, result)
+    # get or build the graph of the function that reads this strange attr
+    def memoized(x):
+        return getattr(x, attrname)
+    return funcdesc.cachedgraph('memo', memoized, 'memo_%s' % funcdesc.name)
 
-def possible_arguments(args):
-    # enumerate all tuples (x1,..xn) of concrete values that are contained
-    # in a tuple args=(s1,..sn) of SomeXxx.  Requires that each s be either
-    # a constant or SomePBC.
-    return cartesian_product([possible_values_of(s) for s in args])
-
-def cartesian_product(lstlst):
-    if not lstlst:
-        yield ()
-        return
-    for tuple_tail in cartesian_product(lstlst[1:]):
-        for value in lstlst[0]:
-            yield (value,) + tuple_tail
 
 def argvalue(i):
     def specialize_argvalue(funcdesc, args_s):

Modified: pypy/branch/somepbc-refactoring/pypy/rpython/lltypesystem/rpbc.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/rpython/lltypesystem/rpbc.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/rpython/lltypesystem/rpbc.py	Thu Nov 24 23:07:39 2005
@@ -6,7 +6,7 @@
 from pypy.rpython.lltypesystem.lltype import \
      typeOf, Void, ForwardReference, Struct, Bool, \
      Ptr, malloc, nullptr
-from pypy.rpython.rmodel import Repr, TyperError, inputconst, warning
+from pypy.rpython.rmodel import Repr, TyperError, inputconst, warning, mangle
 from pypy.rpython import robject
 from pypy.rpython import rtuple
 from pypy.rpython.rpbc import SingleFrozenPBCRepr, samesig,\
@@ -44,7 +44,7 @@
             for attr in attrlist:
                 s_value = self.access_set.attrs[attr]
                 r_value = self.rtyper.getrepr(s_value)
-                mangled_name = 'pbc_' + attr
+                mangled_name = mangle('pbc', attr)
                 llfields.append((mangled_name, r_value.lowleveltype))
                 llfieldmap[attr] = mangled_name, r_value
         self.pbc_type.become(Struct('pbc', *llfields))

Modified: pypy/branch/somepbc-refactoring/pypy/rpython/normalizecalls.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/rpython/normalizecalls.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/rpython/normalizecalls.py	Thu Nov 24 23:07:39 2005
@@ -242,39 +242,6 @@
     return conversion
 
 
-def specialize_pbcs_by_memotables(annotator):
-    memo_tables = annotator.bookkeeper.memo_tables
-    access_sets = annotator.getpbcaccesssets()
-    for memo_table in memo_tables: 
-        arglist_s = memo_table.arglist_s 
-        assert len(arglist_s) == 1, "XXX implement >1 arguments" 
-        arg1 = arglist_s[0]
-        assert isinstance(arg1, annmodel.SomePBC)
-
-        if None in arg1.prebuiltinstances:
-            raise TyperError("unsupported: memo call with an argument that can be None")
-        pbcs = arg1.prebuiltinstances.keys()
-        _, _, access_set = access_sets.find(pbcs[0])
-
-        # enforce a structure where we can uniformly access 
-        # our memofield later 
-        for pbc in pbcs[1:]:
-            _, _, access_set = access_sets.union(pbcs[0], pbc)
-        
-        # we can have multiple memo_tables per PBC 
-        i = 0
-        while 1: 
-            fieldname = "memofield_%d" % i
-            if fieldname in access_set.attrs: 
-                i += 1
-                continue
-            memo_table.fieldname = fieldname
-            break
-        access_set.attrs[fieldname] = memo_table.s_result
-        for pbc in pbcs: 
-            value = memo_table.table[(pbc,)] 
-            access_set.values[(pbc, fieldname)] = value 
-
 def merge_classpbc_getattr_into_classdef(rtyper):
     # code like 'some_class.attr' will record an attribute access in the
     # PBC access set of the family of classes of 'some_class'.  If the classes

Modified: pypy/branch/somepbc-refactoring/pypy/rpython/rmodel.py
==============================================================================
--- pypy/branch/somepbc-refactoring/pypy/rpython/rmodel.py	(original)
+++ pypy/branch/somepbc-refactoring/pypy/rpython/rmodel.py	Thu Nov 24 23:07:39 2005
@@ -318,6 +318,14 @@
         has failed already. 
     """
 
+def mangle(prefix, name):
+    """Make a unique identifier from the prefix and the name.  The name
+    is allowed to start with $."""
+    if name.startswith('$'):
+        return '%sinternal_%s' % (prefix, name[1:])
+    else:
+        return '%s_%s' % (prefix, name)
+
 # __________ utilities __________
 from pypy.rpython.typesystem import LowLevelTypeSystem
 getfunctionptr = LowLevelTypeSystem.instance.getcallable



More information about the Pypy-commit mailing list