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

antocuni at codespeak.net antocuni at codespeak.net
Fri Jun 19 18:06:32 CEST 2009


Author: antocuni
Date: Fri Jun 19 18:06:31 2009
New Revision: 65832

Modified:
   pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize3.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize3.py
Log:
port one test from test_optimize.py.  Add support for rebuilding virtuals that
escape from failing guards



Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize3.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize3.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize3.py	Fri Jun 19 18:06:31 2009
@@ -1,6 +1,7 @@
 from pypy.rlib.objectmodel import r_dict
 from pypy.jit.metainterp.resoperation import rop, ResOperation
-from pypy.jit.metainterp.history import Const, Box, AbstractValue
+from pypy.jit.metainterp.history import Const, Box, AbstractValue,\
+     AbstractDescr, ConstObj
 from pypy.jit.metainterp.optimize import av_eq, av_hash, sort_descrs
 from pypy.jit.metainterp.specnode3 import VirtualInstanceSpecNode, \
      NotSpecNode, FixedClassSpecNode
@@ -150,11 +151,12 @@
         self.values = None  # box --> InstanceValue
         
 
-    def _init(self, loop):
+    def _init(self, loop, cpu):
         self.spec._init(loop)
         self.fixedops = {}
         self.values = {}
         self.loop = loop
+        self.cpu = cpu
 
     def newval(self, *args, **kwds): # XXX RPython
         val = InstanceValue(*args, **kwds)
@@ -178,8 +180,8 @@
         assert not isinstance(box, Const)
         self.values[box] = self.newval(box)
 
-    def optimize_loop(self, loop):
-        self._init(loop)
+    def optimize_loop(self, loop, cpu):
+        self._init(loop, cpu)
         self.spec.find_nodes()
         self.spec.intersect_input_and_output()
         newinputargs = self.spec.newinputargs()
@@ -254,14 +256,36 @@
                     break
             else:
                 return None
-        op.args = self.new_arguments(op)
         assert len(op.suboperations) == 1
         op_fail = op.suboperations[0]
-        op_fail.args = self.new_arguments(op_fail)
-        # modification in place. Reason for this is explained in mirror
-        # in optimize.py
-        op.suboperations = [op_fail]
-        return op
+        assert op_fail.opnum == rop.FAIL
+        oplist = self.rebuild_ops(op_fail)
+        op_fail.args = self.new_arguments(op_fail) # modify in place, see optimize.py
+        newop = op.clone()
+        newop.args = self.new_arguments(newop)
+        newop.suboperations = oplist + [op_fail]
+
+        return newop
+
+    def rebuild_ops(self, op):
+        oplist = []
+        memo = {}
+        for box in op.args:
+            if isinstance(box, Const) or box not in self.spec.nodes:
+                continue
+            node = self.spec.getnode(box)
+            self.rebuild_box(oplist, memo, node, box)
+        return oplist
+
+    def rebuild_box(self, oplist, memo, node, box):
+        if not isinstance(box, Box):
+            return box
+        if box in memo:
+            return box
+        memo[box] = None
+        for opt in self.optlist:
+            opt.rebuild_box(self, oplist, memo, node, box)
+        return box
 
 
 # -------------------------------------------------------------------
@@ -328,6 +352,9 @@
     def handle_default_op(self, spec, op):
         return op
 
+    def rebuild_box(self, oplist, node, box):
+        pass
+
 
 class OptimizeGuards(AbstractOptimization):
 
@@ -475,6 +502,47 @@
 
     # ---------------------------------------
 
+    def _new_obj(self, cpu, clsbox, resbox):
+##         if isinstance(clsbox, FixedList):
+##             ad = clsbox.arraydescr
+##             sizebox = ConstInt(node.cursize)
+##             op = ResOperation(rop.NEW_ARRAY, [sizebox], box,
+##                               descr=ad)
+        if cpu.is_oo and isinstance(clsbox, ConstObj):
+            # it's probably a ootype new
+            cls = clsbox.getobj()
+            typedescr = cpu.class_sizes[cls]
+            return ResOperation(rop.NEW_WITH_VTABLE, [clsbox], resbox,
+                                descr=typedescr)
+        else:
+            assert not cpu.is_oo
+            vtable = clsbox.getint()
+            if cpu.translate_support_code:
+                vtable_addr = cpu.cast_int_to_adr(vtable)
+                size = cpu.class_sizes[vtable_addr]
+            else:
+                size = cpu.class_sizes[vtable]
+            return ResOperation(rop.NEW_WITH_VTABLE, [clsbox], resbox,
+                                descr=size)
+
+    def rebuild_box(self, opt, oplist, memo, node, box):
+        if not node.virtual:
+            return
+        clsbox = node.known_class.source
+        oplist.append(self._new_obj(opt.cpu, clsbox, box))
+        opt.setval(box) # make sure that the value for this box exists
+        for descr, node in node.curfields.items():
+            fieldbox = opt.rebuild_box(oplist, memo, node, node.source)
+##             if isinstance(clsbox, FixedList):
+##                 op = ResOperation(rop.SETARRAYITEM_GC,
+##                                   [box, descr, fieldbox],
+##                                   None, descr=clsbox.arraydescr)
+##             else:
+            assert isinstance(descr, AbstractDescr)
+            op = ResOperation(rop.SETFIELD_GC, [box, fieldbox],
+                              None, descr=descr)
+            oplist.append(op)
+
     def jump(self, opt, op):
         args = opt.spec.expanded_version_of(op.args)
         for arg in args:
@@ -534,7 +602,7 @@
         assert len(old_loops) == 1
         return old_loops[0]
     else:
-        opt.optimize_loop(loop)
+        opt.optimize_loop(loop, cpu)
         return None
 
 def optimize_bridge(options, old_loops, loop, cpu=None, spec=None):

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize3.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize3.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize3.py	Fri Jun 19 18:06:31 2009
@@ -63,6 +63,8 @@
     nodebox2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node))
     nodesize = cpu.sizeof(NODE)
     valuedescr = cpu.fielddescrof(NODE, 'value')
+
+    cpu.class_sizes = {cpu.cast_adr_to_int(node_vtable_adr): cpu.sizeof(NODE)}
     namespace = locals()
 
 class OOtypeMixin(object):
@@ -83,6 +85,7 @@
     valuedescr = cpu.fielddescrof(NODE, 'value')
     nodesize = cpu.typedescrof(NODE)
 
+    cpu.class_sizes = {node_vtable_adr: cpu.typedescrof(NODE)}
     namespace = locals()
 
 class BaseTestOptimize3(object):
@@ -228,7 +231,7 @@
     def test_optimize_loop(self):
         loop = self.getloop()
         opt = LoopOptimizer([OptimizeVirtuals()])
-        opt.optimize_loop(loop)
+        opt.optimize_loop(loop, self.cpu)
         self.check_optimize_loop(opt, loop)
 
 
@@ -402,6 +405,57 @@
         self.assert_equal(loop, expected)
         
 
+class RebuildOps(BaseVirtualTest):
+
+    def getloop(self):
+        ops = """
+        [sum, n1]
+        guard_class(n1, ConstClass(node_vtable))
+            fail()
+        v = getfield_gc(n1, descr=valuedescr)
+        v2 = int_sub(v, 1)
+        sum2 = int_add(sum, v)
+        n2 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        setfield_gc(n2, v2, descr=valuedescr)
+        guard_true(v2)
+            fail(sum2, n2)
+        jump(sum2, n2)
+        """
+        loop = self.parse(ops, boxkinds={'sum': BoxInt,
+                                         'v': BoxInt,
+                                         'n': BoxPtr})
+        loop.setvalues(sum  = 0,
+                       n1   = self.nodebox.value,
+                       v    = 20,
+                       v2   = 19,
+                       sum2 = 20,
+                       n2   = self.nodebox2.value)
+        return loop
+
+    def test_find_nodes(self):
+        pass
+
+    def test_intersect_input_and_output(self):
+        pass
+
+    def check_optimize_loop(self, opt, loop):
+        expected = """
+        [sum, v]
+        v2 = int_sub(v, 1)
+        sum2 = int_add(sum, v)
+        guard_true(v2)
+            # XXX not checked
+            n2 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+            setfield_gc(n2, v2, descr=valuedescr)
+            fail(sum2, n2)
+        jump(sum2, v2)
+        """
+        self.assert_equal(loop, expected)
+        # XXX: it seems that guard_true.suboperations is not checked
+        # check it manually
+        assert loop.operations[-2].suboperations[0].opnum == rop.NEW_WITH_VTABLE
+        assert loop.operations[-2].suboperations[1].opnum == rop.SETFIELD_GC
+        assert loop.operations[-2].suboperations[2].opnum == rop.FAIL
 
 def create_tests(ns):
     for name, value in ns.items():



More information about the Pypy-commit mailing list