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

fijal at codespeak.net fijal at codespeak.net
Sun Mar 29 21:34:23 CEST 2009


Author: fijal
Date: Sun Mar 29 21:34:20 2009
New Revision: 63419

Modified:
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py
Log:
Port one more fix from virtualizable-specnodes, less terrible than on the
branch


Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py	Sun Mar 29 21:34:20 2009
@@ -137,6 +137,9 @@
 
 # ____________________________________________________________
 
+def update_loop(loop, spec):
+    pass
+
 def compile_fresh_bridge(metainterp, old_loops, resumekey):
     #temp = TreeLoop('temp')
     #temp.operations = metainterp.history.operations

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/optimize.py	Sun Mar 29 21:34:20 2009
@@ -162,6 +162,8 @@
         assert other.virtualized
         assert self is other
         offsets = self.allfields
+        if offsets is None:
+            return None
         sort_descrs(offsets)
         fields = []
         for ofs in offsets:
@@ -217,8 +219,14 @@
     perfect_specializer.find_nodes()
     for old_loop in old_loops:
         if perfect_specializer.match(old_loop):
-            perfect_specializer.adapt_for_match(old_loop)
+            # xxx slow, maybe
+            for node in perfect_specializer.nodes.values():
+                if node.startbox:
+                    node.cls = None
+                    assert not node.virtual
+            ofs = perfect_specializer.adapt_for_match(old_loop)
             perfect_specializer.optimize_loop()
+            perfect_specializer.update_loop(ofs, old_loop)
             return old_loop
     return None     # no loop matches
 
@@ -436,14 +444,13 @@
             specnodes.append(enternode.intersect(leavenode, self.nodes))
         self.specnodes = specnodes
 
-    def expanded_version_of(self, boxlist, oplist):
-        # oplist is None means at the start
+    def expanded_version_of(self, boxlist):
         newboxlist = []
         assert len(boxlist) == len(self.specnodes)
         for i in range(len(boxlist)):
             box = boxlist[i]
             specnode = self.specnodes[i]
-            specnode.expand_boxlist(self.nodes[box], newboxlist, oplist)
+            specnode.expand_boxlist(self.nodes[box], newboxlist)
         return newboxlist
 
     def prepare_rebuild_ops(self, instnode, rebuild_ops, memo):
@@ -572,7 +579,9 @@
                 return True
             # this means field comes from a virtualizable but is never
             # written.
-            self.nodes[box] = InstanceNode(box)
+            node = InstanceNode(box)
+            self.nodes[box] = node
+            instnode.curfields[ofs] = node
             return True
         #if ofs in instnode.cleanfields:
         #    self.nodes[box] = instnode.cleanfields[ofs]
@@ -604,20 +613,15 @@
             for i in range(len(self.specnodes)):
                 box = self.history.inputargs[i]
                 self.specnodes[i].mutate_nodes(self.nodes[box])
-            newinputargs = self.expanded_version_of(self.history.inputargs,
-                                                    None)
+            newinputargs = self.expanded_version_of(self.history.inputargs)
         else:
             # making a bridge
-            for node in self.nodes.values():     # xxx slow, maybe
-                if node.startbox:
-                    node.cls = None
-                    assert not node.virtual
             newinputargs = None
         #
         for op in self.history.operations:
             opnum = op.opnum
             if opnum == rop.JUMP:
-                args = self.expanded_version_of(op.args, newoperations)
+                args = self.expanded_version_of(op.args)
                 for arg in args:
                     if arg in self.nodes:
                         assert not self.nodes[arg].virtual
@@ -821,10 +825,59 @@
         jump_op = self.history.operations[-1]
         assert jump_op.opnum == rop.JUMP
         self.specnodes = old_loop.specnodes
+        all_offsets = []
         for i in range(len(old_loop.specnodes)):
             old_specnode = old_loop.specnodes[i]
             new_instnode = self.getnode(jump_op.args[i])
-            old_specnode.adapt_to(new_instnode)
+            offsets = []
+            old_specnode.adapt_to(new_instnode, offsets)
+            all_offsets.append(offsets)
+        return all_offsets
+
+    def update_loop(self, offsets, loop):
+        j = 0
+        new_inputargs = []
+        new_jumpargs = []
+        if loop.operations[-1].jump_target is loop:
+            patch_jump = True
+            jumpargs = loop.operations[-1].args
+        else:
+            patch_jump = False
+            jumpargs = []
+        prev_ofs = 0
+        rebuild_ops = []
+        memo = {}
+        for i in range(len(offsets)):
+            for specnode, descr, parentnode, rel_ofs, node in offsets[i]:
+                while parentnode.source != loop.inputargs[j]:
+                    j += 1
+                ofs = j + rel_ofs + 1
+                new_inputargs.extend(loop.inputargs[prev_ofs:ofs])
+                if patch_jump:
+                    new_jumpargs.extend(jumpargs[prev_ofs:ofs])
+                prev_ofs = ofs
+                boxlist = []
+                specnode.expand_boxlist(node, boxlist)
+                new_inputargs.extend(boxlist)
+                new_jumpargs.extend(boxlist)
+                box = self.prepare_rebuild_ops(node, rebuild_ops, memo)
+                if (parentnode.cls and
+                    isinstance(parentnode.cls.source, FixedList)):
+                    rebuild_ops.append(ResOperation(rop.SETARRAYITEM_GC,
+                      [parentnode.source, descr, box], None,
+                      parentnode.cls.source.arraydescr))
+                else:
+                    rebuild_ops.append(ResOperation(rop.SETFIELD_GC,
+                      [parentnode.source, box], None, descr))
+        new_inputargs.extend(loop.inputargs[prev_ofs:])
+        loop.inputargs = new_inputargs
+        if patch_jump:
+            new_jumpargs.extend(loop.operations[-1].args[prev_ofs:])
+            loop.operations[-1].args = new_jumpargs
+        for op in loop.operations:
+            if op.is_guard():
+                op.suboperations = (op.suboperations[:-1] + rebuild_ops +
+                                    [op.suboperations[-1]])
 
 def get_in_list(dict, boxes_or_consts):
     result = []
@@ -851,6 +904,7 @@
 ##    # done
 ##    return [currentvalues[box] for box in guard_op.unoptboxes]
 
+# ---------------------------------------------------------------
 
 def partition(array, left, right):
     last_item = array[right]

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/specnode.py	Sun Mar 29 21:34:20 2009
@@ -3,13 +3,13 @@
 
 class SpecNode(object):
 
-    def expand_boxlist(self, instnode, newboxlist, start):
+    def expand_boxlist(self, instnode, newboxlist):
         newboxlist.append(instnode.source)
 
     def extract_runtime_data(self, cpu, valuebox, resultlist):
         resultlist.append(valuebox)
 
-    def adapt_to(self, instnode):
+    def adapt_to(self, instnode, offsets):
         instnode.escaped = True
 
     def mutate_nodes(self, instnode):
@@ -21,6 +21,9 @@
     def matches(self, other):
         raise NotImplementedError
 
+    def compute_number_of_nodes(self):
+        raise NotImplementedError
+
 class NotSpecNode(SpecNode):
     def mutate_nodes(self, instnode):
         instnode.cursize = -1
@@ -34,8 +37,13 @@
         # NotSpecNode matches everything
         return True
 
+    def compute_number_of_nodes(self):
+        return 1
+
 class MatchEverythingSpecNode(SpecNode):
-    pass
+
+    def compute_number_of_nodes(self):
+        return 0
 
 #class SpecNodeWithBox(NotSpecNode):
 #    # XXX what is this class used for?
@@ -71,6 +79,9 @@
             return False
         return instnode.cls.source.equals(self.known_class)
 
+    def compute_number_of_nodes(self):
+        return 1
+
 ##class FixedListSpecNode(FixedClassSpecNode):
 
 ##    def equals(self, other):
@@ -125,11 +136,11 @@
                 return False
         return True
 
-    def expand_boxlist(self, instnode, newboxlist, start):
+    def expand_boxlist(self, instnode, newboxlist):
         for ofs, subspecnode in self.fields:
             if not isinstance(subspecnode, MatchEverythingSpecNode):
                 subinstnode = instnode.curfields[ofs]  # should really be there
-                subspecnode.expand_boxlist(subinstnode, newboxlist, start)
+                subspecnode.expand_boxlist(subinstnode, newboxlist)
 
     def extract_runtime_data(self, cpu, valuebox, resultlist):
         for ofs, subspecnode in self.fields:
@@ -140,9 +151,15 @@
                                             [valuebox], ofs)
                 subspecnode.extract_runtime_data(cpu, fieldbox, resultlist)
 
-    def adapt_to(self, instnode):
+    def adapt_to(self, instnode, offsets):
+        for ofs, subspecnode in self.fields:
+            subspecnode.adapt_to(instnode.curfields[ofs], offsets)
+
+    def compute_number_of_nodes(self):
+        counter = 0
         for ofs, subspecnode in self.fields:
-            subspecnode.adapt_to(instnode.curfields[ofs])
+            counter += subspecnode.compute_number_of_nodes()
+        return counter
 
 class VirtualizedSpecNode(SpecNodeWithFields):
 
@@ -158,18 +175,50 @@
             if not self.fields[i][1].equals(other.fields[i][1]):
                 return False
         return True
+
+    def matches(self, instnode):
+        for key, value in self.fields:
+            if not isinstance(value, MatchEverythingSpecNode):
+                if key not in instnode.curfields:
+                    return False
+                if value is not None and not value.matches(instnode.curfields[key]):
+                    return False
+        return True
     
-    def expand_boxlist(self, instnode, newboxlist, start):
+    def expand_boxlist(self, instnode, newboxlist):
         newboxlist.append(instnode.source)
-        SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist, start)
+        SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist)
 
     def extract_runtime_data(self, cpu, valuebox, resultlist):
         resultlist.append(valuebox)
         SpecNodeWithFields.extract_runtime_data(self, cpu, valuebox, resultlist)
 
-    def adapt_to(self, instnode):
+    def adapt_to(self, instnode, offsets_relative_to):
         instnode.escaped = True
-        SpecNodeWithFields.adapt_to(self, instnode)
+        fields = []
+        offsets_so_far = 0
+        for ofs, subspecnode in self.fields:
+            if isinstance(subspecnode, MatchEverythingSpecNode):
+                node = None
+                if ofs in instnode.curfields:
+                    node = instnode.curfields[ofs]
+                    orignode = instnode.origfields[ofs]
+                    subspecnode = orignode.intersect(node, {})
+                elif ofs in instnode.origfields:
+                    node = instnode.origfields[ofs]
+                    subspecnode = node.intersect(node, {})
+                    orignode = node
+                if node is not None:
+                    subspecnode.mutate_nodes(orignode)
+                    offsets_relative_to.append((subspecnode, ofs, instnode,
+                                                offsets_so_far, orignode))
+            else:
+                subspecnode.adapt_to(instnode.curfields[ofs],
+                                     offsets_relative_to)
+                offsets_so_far += subspecnode.compute_number_of_nodes()
+            fields.append((ofs, subspecnode))
+
+        self.fields = fields
 
 # class DelayedSpecNode(VirtualizedSpecNode):
 
@@ -238,9 +287,9 @@
             return False
         return VirtualizedSpecNode.equals(self, other)        
 
-    def adapt_to(self, instnode):
+    def adapt_to(self, instnode, offsets):
         instnode.virtualized = True
-        VirtualizedSpecNode.adapt_to(self, instnode)
+        VirtualizedSpecNode.adapt_to(self, instnode, offsets)
 
 class VirtualizableListSpecNode(VirtualizedSpecNode):
 
@@ -265,15 +314,15 @@
                                             [valuebox, ofs], arraydescr)
                 subspecnode.extract_runtime_data(cpu, fieldbox, resultlist)
 
-    def adapt_to(self, instnode):
+    def adapt_to(self, instnode, offsets):
         instnode.virtualized = True
-        VirtualizedSpecNode.adapt_to(self, instnode)
+        VirtualizedSpecNode.adapt_to(self, instnode, offsets)
 
 class VirtualSpecNode(SpecNodeWithFields):
 
-    def adapt_to(self, instnode):
+    def adapt_to(self, instnode, offsets):
         instnode.virtual = True
-        SpecNodeWithFields.adapt_to(self, instnode)
+        SpecNodeWithFields.adapt_to(self, instnode, offsets)
 
     def mutate_nodes(self, instnode):
         SpecNodeWithFields.mutate_nodes(self, instnode)

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/test/test_virtualizable.py	Sun Mar 29 21:34:20 2009
@@ -423,7 +423,7 @@
 
         res = self.meta_interp(f, [30], listops=True)
         self.check_loops(setarrayitem_gc=0)
-        #self.check_loop_count(2) # -- this is hard to predict right now:
+        self.check_loop_count(2) # -- this is hard to predict right now:
         #  what occurs is that one path through the loop is compiled,
         #  then exits; then later when we compile again we see the other
         #  path of the loop by chance, then exits; then finally we see
@@ -439,7 +439,6 @@
                         assert isinstance(op.args[1], history.BoxInt)
 
     def test_virtual_obj_on_always_virtual(self):
-        py.test.skip("XX")
         jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 's'],
                               virtualizables = ['frame'])
 



More information about the Pypy-commit mailing list