[pypy-svn] r66365 - in pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp: . test

arigo at codespeak.net arigo at codespeak.net
Sat Jul 18 19:01:34 CEST 2009


Author: arigo
Date: Sat Jul 18 19:01:33 2009
New Revision: 66365

Added:
   pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimizefindnode.py
      - copied, changed from r66363, pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimizeloop.py
   pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimizefindnode.py
      - copied, changed from r66363, pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimizeloop.py
Removed:
   pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimizeloop.py
   pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimizeloop.py
Modified:
   pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/specnode.py
Log:
Reorganize things a bit yet another time.
Start on the BridgeSpecializationFinder; only one test passing.


Copied: pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimizefindnode.py (from r66363, pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimizeloop.py)
==============================================================================
--- pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimizeloop.py	(original)
+++ pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimizefindnode.py	Sat Jul 18 19:01:33 2009
@@ -1,7 +1,9 @@
-from pypy.jit.metainterp.specnode import prebuiltNotSpecNode
+from pypy.jit.metainterp.specnode import SpecNode
+from pypy.jit.metainterp.specnode import NotSpecNode, prebuiltNotSpecNode
 from pypy.jit.metainterp.specnode import FixedClassSpecNode
 from pypy.jit.metainterp.specnode import VirtualInstanceSpecNode
 from pypy.jit.metainterp.history import AbstractValue
+from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.metainterp.optimize import av_newdict, _findall, sort_descrs
 
 # ____________________________________________________________
@@ -42,6 +44,18 @@
                 for box in deps:
                     box.mark_escaped()
 
+    def set_unique_nodes(self):
+        if (self.escaped or self.fromstart or self.knownclsbox is None
+            or self.unique != UNIQUE_UNKNOWN):
+            # this node is not suitable for being a virtual, or we
+            # encounter it more than once when doing the recursion
+            self.unique = UNIQUE_NO
+        else:
+            self.unique = UNIQUE_YES
+            if self.curfields is not None:
+                for subnode in self.curfields.values():
+                    subnode.set_unique_nodes()
+
     def __repr__(self):
         flags = ''
         if self.escaped:     flags += 'e'
@@ -49,8 +63,11 @@
         if self.knownclsbox: flags += 'c'
         return "<InstanceNode (%s)>" % (flags,)
 
+# ____________________________________________________________
+# General find_nodes_xxx() interface, for both loops and bridges
 
-class PerfectSpecializationFinder(object):
+class NodeFinder(object):
+    """Abstract base class."""
     node_escaped = InstanceNode(escaped=True)
 
     def __init__(self):
@@ -59,15 +76,8 @@
     def getnode(self, box):
         return self.nodes.get(box, self.node_escaped)
 
-    def find_nodes(self, loop):
-        inputnodes = []
-        for box in loop.inputargs:
-            instnode = InstanceNode(escaped=False, fromstart=True)
-            inputnodes.append(instnode)
-            self.nodes[box] = instnode
-        self.inputnodes = inputnodes
-        #
-        for op in loop.operations:
+    def find_nodes(self, operations):
+        for op in operations:
             opnum = op.opnum
             for value, func in find_nodes_ops:
                 if opnum == value:
@@ -134,11 +144,38 @@
         instnode.knownclsbox = clsbox
 
     def find_nodes_JUMP(self, op):
-        """Build the list of specnodes based on the result
-        computed by this PerfectSpecializationFinder.
-        """
+        # only set up the 'unique' field of the InstanceNodes;
+        # real handling comes later (build_result_specnodes() for loops).
         for box in op.args:
-            self.find_unique_nodes(self.getnode(box))
+            self.getnode(box).set_unique_nodes()
+
+    def find_nodes_FAIL(self, op):
+        xxx
+
+find_nodes_ops = _findall(NodeFinder, 'find_nodes_')
+
+# ____________________________________________________________
+# Perfect specialization -- for loops only
+
+class PerfectSpecializationFinder(NodeFinder):
+
+    def find_nodes_loop(self, loop):
+        self.setup_input_nodes(loop.inputargs)
+        self.find_nodes(loop.operations)
+        self.build_result_specnodes(loop.operations[-1])
+
+    def setup_input_nodes(self, inputargs):
+        inputnodes = []
+        for box in inputargs:
+            instnode = InstanceNode(escaped=False, fromstart=True)
+            inputnodes.append(instnode)
+            self.nodes[box] = instnode
+        self.inputnodes = inputnodes
+
+    def build_result_specnodes(self, op):
+        # Build the list of specnodes based on the result
+        # computed by NodeFinder.find_nodes().
+        assert op.opnum == rop.JUMP
         specnodes = []
         assert len(self.inputnodes) == len(op.args)
         for i in range(len(op.args)):
@@ -147,19 +184,6 @@
             specnodes.append(self.intersect(inputnode, exitnode))
         self.specnodes = specnodes
 
-    def find_unique_nodes(self, exitnode):
-        if (exitnode.escaped or exitnode.fromstart
-            or exitnode.knownclsbox is None
-            or exitnode.unique != UNIQUE_UNKNOWN):
-            # the exitnode is not suitable for being a virtual, or we
-            # encounter it more than once when doing the recursion
-            exitnode.unique = UNIQUE_NO
-        else:
-            exitnode.unique = UNIQUE_YES
-            if exitnode.curfields is not None:
-                for subnode in exitnode.curfields.values():
-                    self.find_unique_nodes(subnode)
-
     def intersect(self, inputnode, exitnode):
         assert inputnode.fromstart
         if exitnode.unique == UNIQUE_NO or inputnode.escaped:
@@ -198,4 +222,56 @@
                 fields.append((ofs, specnode))
         return VirtualInstanceSpecNode(exitnode.knownclsbox, fields)
 
-find_nodes_ops = _findall(PerfectSpecializationFinder, 'find_nodes_')
+# ____________________________________________________________
+# A subclass of NodeFinder for bridges only
+
+class __extend__(SpecNode):
+    def make_instance_node(self):
+        raise NotImplementedError
+    def matches_instance_node(self, exitnode):
+        raise NotImplementedError
+
+class __extend__(NotSpecNode):
+    def make_instance_node(self):
+        return NodeFinder.node_escaped
+    def matches_instance_node(self, exitnode):
+        return True
+
+class __extend__(FixedClassSpecNode):
+    def make_instance_node(self):
+        instnode = InstanceNode(escaped=True)
+        instnode.knownclsbox = self.known_class
+        return instnode
+    def matches_instance_node(self, exitnode):
+        xxx
+
+class __extend__(VirtualInstanceSpecNode):
+    def make_instance_node(self):
+        instnode = InstanceNode(escaped=False)
+        instnode.curfields = av_newdict()
+        for ofs, subspecnode in self.fields:
+            instnode.curfields[ofs] = subspecnode.make_instance_node()
+        return instnode
+    def matches_instance_node(self, exitnode):
+        if exitnode.unique == UNIQUE_NO:
+            return False
+        else:
+            xxx
+
+class BridgeSpecializationFinder(NodeFinder):
+
+    def setup_bridge_input_nodes(self, specnodes, inputargs):
+        assert len(specnodes) == len(inputargs)
+        for i in range(len(inputargs)):
+            instnode = specnodes[i].make_instance_node()
+            box = inputargs[i]
+            self.nodes[box] = instnode
+
+    def bridge_matches(self, jump_op, nextloop_specnodes):
+        assert jump_op.opnum == rop.JUMP
+        assert len(jump_op.args) == len(nextloop_specnodes)
+        for i in range(len(nextloop_specnodes)):
+            exitnode = self.getnode(jump_op.args[i])
+            if not nextloop_specnodes[i].matches_instance_node(exitnode):
+                return False
+        return True

Modified: pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/specnode.py
==============================================================================
--- pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/specnode.py	(original)
+++ pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/specnode.py	Sat Jul 18 19:01:33 2009
@@ -1,6 +1,8 @@
+from pypy.tool.pairtype import extendabletype
 
 
 class SpecNode(object):
+    __metaclass__ = extendabletype     # extended in optimizefindnode.py
     __slots__ = ()
 
     def extract_runtime_data(self, cpu, valuebox, resultlist):

Copied: pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimizefindnode.py (from r66363, pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimizeloop.py)
==============================================================================
--- pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimizeloop.py	(original)
+++ pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimizefindnode.py	Sat Jul 18 19:01:33 2009
@@ -8,7 +8,8 @@
 from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr,
                                          Const, ConstAddr, TreeLoop, BoxObj,
                                          ConstObj, AbstractDescr)
-from pypy.jit.metainterp.optimizeloop import PerfectSpecializationFinder
+from pypy.jit.metainterp.optimizefindnode import PerfectSpecializationFinder
+from pypy.jit.metainterp.optimizefindnode import BridgeSpecializationFinder
 from pypy.jit.metainterp.optimize import sort_descrs
 from pypy.jit.metainterp.specnode import NotSpecNode, prebuiltNotSpecNode
 from pypy.jit.metainterp.specnode import FixedClassSpecNode
@@ -135,7 +136,7 @@
         equaloplists(optimized.operations,
                      self.parse(expected).operations)
 
-    def assert_specnodes(self, specnodes, text):
+    def unpack_specnodes(self, text):
         #
         def constclass(cls_vtable):
             if self.type_system == 'lltype':
@@ -156,6 +157,10 @@
                    'Fixed': makeFixed,
                    'Virtual': makeVirtual}
         lst = eval('[' + text + ']', self.namespace, context)
+        return lst
+
+    def check_specnodes(self, specnodes, text):
+        lst = self.unpack_specnodes(text)
         assert len(specnodes) == len(lst)
         for x, y in zip(specnodes, lst):
             assert x._equals(y)
@@ -164,9 +169,8 @@
     def find_nodes(self, ops, spectext, boxkinds=None):
         loop = self.parse(ops, boxkinds=boxkinds)
         perfect_specialization_finder = PerfectSpecializationFinder()
-        perfect_specialization_finder.find_nodes(loop)
-        assert self.assert_specnodes(perfect_specialization_finder.specnodes,
-                                     spectext)
+        perfect_specialization_finder.find_nodes_loop(loop)
+        self.check_specnodes(perfect_specialization_finder.specnodes, spectext)
         return (loop.getboxes(), perfect_specialization_finder.getnode)
 
     def test_find_nodes_simple(self):
@@ -481,6 +485,35 @@
                     nextdescr=Virtual(node_vtable,
                                       nextdescr=Virtual(node_vtable)))''')
 
+    # ------------------------------
+    # Bridge tests
+
+    def find_bridge(self, ops, inputspectext, outputspectext, boxkinds=None,
+                    mismatch=False):
+        inputspecnodes = self.unpack_specnodes(inputspectext)
+        outputspecnodes = self.unpack_specnodes(outputspectext)
+        bridge = self.parse(ops, boxkinds=boxkinds)
+        bridge_specialization_finder = BridgeSpecializationFinder()
+        bridge_specialization_finder.setup_bridge_input_nodes(inputspecnodes,
+                                                              bridge.inputargs)
+        bridge_specialization_finder.find_nodes(bridge.operations)
+        matches = bridge_specialization_finder.bridge_matches(
+            bridge.operations[-1],
+            outputspecnodes)
+        if mismatch:
+            assert not matches
+        else:
+            assert matches
+
+    def test_bridge_simple(self):
+        ops = """
+        [i0]
+        i1 = int_add(i0, 1)
+        jump(i1)
+        """
+        self.find_bridge(ops, 'Not', 'Not')
+        self.find_bridge(ops, 'Not', 'Virtual(node_vtable)', mismatch=True)
+
 
 class TestLLtype(BaseTestOptimize, LLtypeMixin):
     pass



More information about the Pypy-commit mailing list