[pypy-commit] pypy callfamily: Move some methods to FunctionRepr and simplify FunctionsPBCRepr

rlamy noreply at buildbot.pypy.org
Wed Oct 7 02:45:38 CEST 2015


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: callfamily
Changeset: r80007:09379b1fc493
Date: 2015-10-06 21:12 +0100
http://bitbucket.org/pypy/pypy/changeset/09379b1fc493/

Log:	Move some methods to FunctionRepr and simplify FunctionsPBCRepr

diff --git a/rpython/rtyper/rpbc.py b/rpython/rtyper/rpbc.py
--- a/rpython/rtyper/rpbc.py
+++ b/rpython/rtyper/rpbc.py
@@ -175,27 +175,23 @@
 
 
 class FunctionsPBCRepr(CanBeNull, Repr):
-    """Representation selected for a PBC of function(s)."""
+    """Representation selected for a PBC of functions."""
 
     def __init__(self, rtyper, s_pbc):
         self.rtyper = rtyper
         self.s_pbc = s_pbc
         self.callfamily = s_pbc.any_description().getcallfamily()
-        if len(s_pbc.descriptions) == 1 and not s_pbc.can_be_None:
-            # a single function
-            self.lowleveltype = Void
+        llct = get_concrete_calltable(self.rtyper, self.callfamily)
+        self.concretetable = llct.table
+        self.uniquerows = llct.uniquerows
+        if len(llct.uniquerows) == 1:
+            row = llct.uniquerows[0]
+            self.lowleveltype = row.fntype
         else:
-            llct = get_concrete_calltable(self.rtyper, self.callfamily)
-            self.concretetable = llct.table
-            self.uniquerows = llct.uniquerows
-            if len(llct.uniquerows) == 1:
-                row = llct.uniquerows[0]
-                self.lowleveltype = row.fntype
-            else:
-                # several functions, each with several specialized variants.
-                # each function becomes a pointer to a Struct containing
-                # pointers to its variants.
-                self.lowleveltype = self.setup_specfunc()
+            # several functions, each with several specialized variants.
+            # each function becomes a pointer to a Struct containing
+            # pointers to its variants.
+            self.lowleveltype = self.setup_specfunc()
         self.funccache = {}
 
     def setup_specfunc(self):
@@ -227,34 +223,31 @@
             return self.funccache[funcdesc]
         except KeyError:
             pass
-        if self.lowleveltype is Void:
-            result = None
+        llfns = {}
+        found_anything = False
+        for row in self.uniquerows:
+            if funcdesc in row:
+                llfn = row[funcdesc]
+                found_anything = True
+            else:
+                # missing entry -- need a 'null' of the type that matches
+                # this row
+                llfn = self.rtyper.type_system.null_callable(row.fntype)
+            llfns[row.attrname] = llfn
+        if len(self.uniquerows) == 1:
+            if found_anything:
+                result = llfn   # from the loop above
+            else:
+                # extremely rare case, shown only sometimes by
+                # test_bug_callfamily: don't emit NULL, because that
+                # would be interpreted as equal to None...  It should
+                # never be called anyway.
+                result = rffi.cast(self.lowleveltype, ~len(self.funccache))
         else:
-            llfns = {}
-            found_anything = False
-            for row in self.uniquerows:
-                if funcdesc in row:
-                    llfn = row[funcdesc]
-                    found_anything = True
-                else:
-                    # missing entry -- need a 'null' of the type that matches
-                    # this row
-                    llfn = self.rtyper.type_system.null_callable(row.fntype)
-                llfns[row.attrname] = llfn
-            if len(self.uniquerows) == 1:
-                if found_anything:
-                    result = llfn   # from the loop above
-                else:
-                    # extremely rare case, shown only sometimes by
-                    # test_bug_callfamily: don't emit NULL, because that
-                    # would be interpreted as equal to None...  It should
-                    # never be called anyway.
-                    result = rffi.cast(self.lowleveltype, ~len(self.funccache))
-            else:
-                # build a Struct with all the values collected in 'llfns'
-                result = self.create_specfunc()
-                for attrname, llfn in llfns.items():
-                    setattr(result, attrname, llfn)
+            # build a Struct with all the values collected in 'llfns'
+            result = self.create_specfunc()
+            for attrname, llfn in llfns.items():
+                setattr(result, attrname, llfn)
         self.funccache[funcdesc] = result
         return result
 
@@ -263,8 +256,6 @@
             value = value.im_func  # unbound method -> bare function
         elif isinstance(value, staticmethod):
             value = value.__get__(42)  # hackish, get the function wrapped by staticmethod
-        if self.lowleveltype is Void:
-            return None
         if value is None:
             null = self.rtyper.type_system.null_callable(self.lowleveltype)
             return null
@@ -277,15 +268,7 @@
         'index' and 'shape' tells which of its items we are interested in.
         """
         assert v.concretetype == self.lowleveltype
-        if self.lowleveltype is Void:
-            assert len(self.s_pbc.descriptions) == 1
-                                      # lowleveltype wouldn't be Void otherwise
-            funcdesc, = self.s_pbc.descriptions
-            row_of_one_graph = self.callfamily.calltables[shape][index]
-            graph = row_of_one_graph[funcdesc]
-            llfn = self.rtyper.getcallable(graph)
-            return inputconst(typeOf(llfn), llfn)
-        elif len(self.uniquerows) == 1:
+        if len(self.uniquerows) == 1:
             return v
         else:
             # 'v' is a Struct pointer, read the corresponding field
@@ -293,34 +276,6 @@
             cname = inputconst(Void, row.attrname)
             return self.get_specfunc_row(llop, v, cname, row.fntype)
 
-    def get_unique_llfn(self):
-        # try to build a unique low-level function.  Avoid to use
-        # whenever possible!  Doesn't work with specialization, multiple
-        # different call sites, etc.
-        if self.lowleveltype is not Void:
-            raise TyperError("cannot pass multiple functions here")
-        assert len(self.s_pbc.descriptions) == 1
-                                  # lowleveltype wouldn't be Void otherwise
-        funcdesc, = self.s_pbc.descriptions
-        tables = []        # find the simple call in the calltable
-        for shape, table in self.callfamily.calltables.items():
-            if not shape[1] and not shape[2]:
-                tables.append(table)
-        if len(tables) != 1:
-            raise TyperError("cannot pass a function with various call shapes")
-        table, = tables
-        graphs = []
-        for row in table:
-            if funcdesc in row:
-                graphs.append(row[funcdesc])
-        if not graphs:
-            raise TyperError("cannot pass here a function that is not called")
-        graph = graphs[0]
-        if graphs != [graph] * len(graphs):
-            raise TyperError("cannot pass a specialized function here")
-        llfn = self.rtyper.getcallable(graph)
-        return inputconst(typeOf(llfn), llfn)
-
     def get_concrete_llfn(self, s_pbc, args_s, op):
         bk = self.rtyper.annotator.bookkeeper
         funcdesc, = s_pbc.descriptions
@@ -361,7 +316,55 @@
             return hop.llops.convertvar(v, rresult, hop.r_result)
 
 class FunctionRepr(FunctionsPBCRepr):
-    pass
+    """Repr for a constant function"""
+    def __init__(self, rtyper, s_pbc):
+        self.rtyper = rtyper
+        self.s_pbc = s_pbc
+        self.callfamily = s_pbc.any_description().getcallfamily()
+        self.lowleveltype = Void
+
+    def convert_desc(self, funcdesc):
+        return None
+
+    def convert_const(self, value):
+        return None
+
+    def convert_to_concrete_llfn(self, v, shape, index, llop):
+        """Convert the variable 'v' to a variable referring to a concrete
+        low-level function.  In case the call table contains multiple rows,
+        'index' and 'shape' tells which of its items we are interested in.
+        """
+        assert v.concretetype == self.lowleveltype
+        funcdesc, = self.s_pbc.descriptions
+        row_of_one_graph = self.callfamily.calltables[shape][index]
+        graph = row_of_one_graph[funcdesc]
+        llfn = self.rtyper.getcallable(graph)
+        return inputconst(typeOf(llfn), llfn)
+
+    def get_unique_llfn(self):
+        # try to build a unique low-level function.  Avoid to use
+        # whenever possible!  Doesn't work with specialization, multiple
+        # different call sites, etc.
+        funcdesc, = self.s_pbc.descriptions
+        tables = []        # find the simple call in the calltable
+        for shape, table in self.callfamily.calltables.items():
+            if not shape[1] and not shape[2]:
+                tables.append(table)
+        if len(tables) != 1:
+            raise TyperError("cannot pass a function with various call shapes")
+        table, = tables
+        graphs = []
+        for row in table:
+            if funcdesc in row:
+                graphs.append(row[funcdesc])
+        if not graphs:
+            raise TyperError("cannot pass here a function that is not called")
+        graph = graphs[0]
+        if graphs != [graph] * len(graphs):
+            raise TyperError("cannot pass a specialized function here")
+        llfn = self.rtyper.getcallable(graph)
+        return inputconst(typeOf(llfn), llfn)
+
 
 class __extend__(pairtype(FunctionsPBCRepr, FunctionsPBCRepr)):
     def convert_from_to((r_fpbc1, r_fpbc2), v, llops):


More information about the pypy-commit mailing list