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

arigo at codespeak.net arigo at codespeak.net
Fri Jul 17 16:46:33 CEST 2009


Author: arigo
Date: Fri Jul 17 16:46:32 2009
New Revision: 66307

Modified:
   pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimize.py
   pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/specnode.py
   pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimize.py
Log:
Start support for the next phase, namely intersect().
Support for tracking which boxes know their class.
Write more tests about that.


Modified: pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimize.py
==============================================================================
--- pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimize.py	(original)
+++ pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimize.py	Fri Jul 17 16:46:32 2009
@@ -1,6 +1,6 @@
 from pypy.rlib.objectmodel import r_dict
 from pypy.rlib.unroll import unrolling_iterable
-from pypy.jit.metainterp import resoperation
+from pypy.jit.metainterp import resoperation, specnode
 from pypy.jit.metainterp.history import AbstractValue
 
 
@@ -31,8 +31,7 @@
     origfields = None   # optimization; equivalent to an empty dict
     curfields = None    # optimization; equivalent to an empty dict
     dependencies = None
-    origclass = False
-    curclass = None
+    knownclsbox = None
 
     def __init__(self, escaped, fromstart=False):
         self.escaped = escaped
@@ -62,21 +61,21 @@
 
 
 class PerfectSpecializationFinder(object):
+    node_escaped = InstanceNode(escaped=True)
 
     def __init__(self):
         self.nodes = {}     # Box -> InstanceNode
-        self.node_escaped = InstanceNode(escaped=True)
-
-    def clear(self):
-        self.nodes.clear()
 
     def getnode(self, box):
         return self.nodes.get(box, self.node_escaped)
 
     def find_nodes(self, loop):
-        self.clear()
+        inputnodes = []
         for box in loop.inputargs:
-            self.nodes[box] = InstanceNode(escaped=False, fromstart=True)
+            instnode = InstanceNode(escaped=False, fromstart=True)
+            inputnodes.append(instnode)
+            self.nodes[box] = instnode
+        self.inputnodes = inputnodes
         #
         for op in loop.operations:
             opnum = op.opnum
@@ -95,7 +94,7 @@
 
     def find_nodes_NEW_WITH_VTABLE(self, op):
         instnode = InstanceNode(escaped=False)
-        instnode.curclass = op.args[0]
+        instnode.knownclsbox = op.args[0]
         self.nodes[op.result] = instnode
 
     def find_nodes_SETFIELD_GC(self, op):
@@ -134,22 +133,40 @@
 
     def find_nodes_GUARD_CLASS(self, op):
         instbox = op.args[0]
+        clsbox = op.args[1]
         try:
             instnode = self.nodes[instbox]
         except KeyError:
             instnode = self.nodes[instbox] = InstanceNode(escaped=True)
-        else:
-            if instnode.fromstart:
-                instnode.origclass = True
-        instnode.curclass = op.args[1]
+        assert instnode is not self.node_escaped
+        assert (instnode.knownclsbox is None or
+                instnode.knownclsbox.equals(clsbox))
+        instnode.knownclsbox = clsbox
 
     def find_nodes_JUMP(self, op):
-        pass    # prevent the default handling
-
-    def find_nodes_FAIL(self, op):
-        pass    # prevent the default handling
+        """Build the list of specnodes based on the result
+        computed by this PerfectSpecializationFinder.
+        """
+        specnodes = []
+        assert len(self.inputnodes) == len(op.args)
+        for i in range(len(op.args)):
+            inputnode = self.inputnodes[i]
+            specnodes.append(self.intersect(inputnode, op.args[i]))
+        self.specnodes = specnodes
+
+    def intersect(self, inputnode, exitbox):
+        assert inputnode.fromstart
+        exitnode = self.getnode(exitbox)
+        if inputnode.escaped or exitnode.escaped or exitnode.fromstart:
+            if (inputnode.knownclsbox is not None and
+                exitnode.knownclsbox is not None and
+                inputnode.knownclsbox.equals(exitnode.knownclsbox)):
+                return specnode.FixedClassSpecNode(inputnode.knownclsbox)
+            else:
+                return specnode.prebuiltNotSpecNode
+        else:
+            xxx #...
 
 find_nodes_ops = _findall(PerfectSpecializationFinder, 'find_nodes_')
-perfect_specialization_finder = PerfectSpecializationFinder()
 
 # ____________________________________________________________

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	Fri Jul 17 16:46:32 2009
@@ -1,369 +1,25 @@
-from pypy.jit.metainterp.resoperation import ResOperation, rop
-from pypy.jit.metainterp import executor
+
 
 class SpecNode(object):
     __slots__ = ()
 
-    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, offsets):
-        instnode.escaped = True
-
-    def mutate_nodes(self, instnode):
-        raise NotImplementedError
-
-    def equals(self, other):
-        raise NotImplementedError
-
-    def matches(self, other):
-        raise NotImplementedError
-
-    def compute_number_of_nodes(self):
-        raise NotImplementedError
 
 class NotSpecNode(SpecNode):
     __slots__ = ()
 
-    def mutate_nodes(self, instnode):
-        instnode.cursize = -1
 
-    def equals(self, other):
-        if type(other) is NotSpecNode:
-            return True
-        return False
-
-    def matches(self, other):
-        # NotSpecNode matches everything
-        return True
-
-    def compute_number_of_nodes(self):
-        return 1
-
-class MatchEverythingSpecNode(SpecNode):
-
-    def compute_number_of_nodes(self):
-        return 0
-
-#class SpecNodeWithBox(NotSpecNode):
-#    # XXX what is this class used for?
-#    def __init__(self, box):
-#        self.box = box
-    
-#    def equals(self, other):
-#        if type(other) is SpecNodeWithBox:
-#            return True
-#        return False
+prebuiltNotSpecNode = NotSpecNode()
+
 
 class FixedClassSpecNode(SpecNode):
     def __init__(self, known_class):
         self.known_class = known_class
 
-    def mutate_nodes(self, instnode):
-        from pypy.jit.metainterp.optimize import InstanceNode
-        
-        if instnode.cls is None:
-            instnode.cls = InstanceNode(self.known_class, const=True)
-        else:
-            assert instnode.cls.source.equals(self.known_class)
-
-    def equals(self, other):
-        if type(other) is not FixedClassSpecNode:
-            return False
-        else:
-            assert isinstance(other, FixedClassSpecNode) # make annotator happy
-            return self.known_class.equals(other.known_class)
-
-    def matches(self, instnode):
-        if instnode.cls is None:
-            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):
-##        if type(other) is not FixedListSpecNode:
-##            return False
-##        else:
-##            assert isinstance(other, FixedListSpecNode) # make annotator happy
-##            return self.known_class.equals(other.known_class)
 
-class SpecNodeWithFields(FixedClassSpecNode):
+class VirtualInstanceSpecNode(FixedClassSpecNode):
     def __init__(self, known_class, fields):
         FixedClassSpecNode.__init__(self, known_class)
         self.fields = fields
-
-    def mutate_nodes(self, instnode):
-        from pypy.jit.metainterp.optimize import av_eq, av_hash
-        from pypy.rlib.objectmodel import r_dict
-        
-        FixedClassSpecNode.mutate_nodes(self, instnode)
-        curfields = r_dict(av_eq, av_hash)
-        for ofs, subspecnode in self.fields:
-            if not isinstance(subspecnode, MatchEverythingSpecNode):
-                subinstnode = instnode.origfields[ofs]
-                # should really be there
-                subspecnode.mutate_nodes(subinstnode)
-                curfields[ofs] = subinstnode
-        instnode.curfields = curfields
-
-    def equals(self, other):
-        if not isinstance(other, SpecNodeWithFields):
-            return False
-        if not self.known_class.equals(other.known_class):
-            return False
-        elif len(self.fields) != len(other.fields):
-            return False
-        else:
-            for i in range(len(self.fields)):
-                key, value = self.fields[i]
-                otherkey, othervalue = other.fields[i]
-                if key != otherkey:
-                    return False
-                if not value.equals(othervalue):
-                    return False
-            return True
-
-    def matches(self, instnode):
-        # XXX think about details of virtual vs virtualizable
-        if not FixedClassSpecNode.matches(self, instnode):
-            return False
-        for key, value in self.fields:
-            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):
-        for ofs, subspecnode in self.fields:
-            if not isinstance(subspecnode, MatchEverythingSpecNode):
-                subinstnode = instnode.curfields[ofs]  # should really be there
-                subspecnode.expand_boxlist(subinstnode, newboxlist)
-
-    def extract_runtime_data(self, cpu, valuebox, resultlist):
-        for ofs, subspecnode in self.fields:
-            from pypy.jit.metainterp.history import AbstractDescr
-            assert isinstance(ofs, AbstractDescr)
-            if not isinstance(subspecnode, MatchEverythingSpecNode):
-                fieldbox = executor.execute(cpu, rop.GETFIELD_GC,
-                                            [valuebox], ofs)
-                subspecnode.extract_runtime_data(cpu, fieldbox, resultlist)
-
-    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:
-            counter += subspecnode.compute_number_of_nodes()
-        return counter
-
-class VirtualizedSpecNode(SpecNodeWithFields):
-
-    def equals(self, other):
-        if not self.known_class.equals(other.known_class):
-            return False
-        assert len(self.fields) == len(other.fields)
-        for i in range(len(self.fields)):
-            if (isinstance(self.fields[i][1], MatchEverythingSpecNode) or
-                isinstance(other.fields[i][1], MatchEverythingSpecNode)):
-                continue
-            assert self.fields[i][0].equals(other.fields[i][0])
-            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):
-        newboxlist.append(instnode.source)
-        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, offsets_relative_to):
-        instnode.escaped = True
-        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):
-
-#     def expand_boxlist(self, instnode, newboxlist, oplist):
-#         from pypy.jit.metainterp.history import AbstractDescr
-#         newboxlist.append(instnode.source)
-#         for ofs, subspecnode in self.fields:
-#             assert isinstance(subspecnode, SpecNodeWithBox)
-#             if oplist is None:
-#                 instnode.cleanfields[ofs] = instnode.origfields[ofs]
-#                 newboxlist.append(instnode.curfields[ofs].source)
-#             else:
-#                 if ofs in instnode.cleanfields:
-#                     newboxlist.append(instnode.cleanfields[ofs].source)
-#                 else:
-#                     box = subspecnode.box.clonebox()
-#                     assert isinstance(ofs, AbstractDescr)
-#                     oplist.append(ResOperation(rop.GETFIELD_GC,
-#                        [instnode.source], box, ofs))
-#                     newboxlist.append(box)
-
-# class DelayedFixedListSpecNode(DelayedSpecNode):
-
-#    def expand_boxlist(self, instnode, newboxlist, oplist):
-#        from pypy.jit.metainterp.history import ResOperation
-#        from pypy.jit.metainterp.resoperation import rop
-#        from pypy.jit.metainterp.optimize import FixedList
-        
-#        newboxlist.append(instnode.source)
-#        cls = self.known_class
-#        assert isinstance(cls, FixedList)
-#        arraydescr = cls.arraydescr
-#        for ofs, subspecnode in self.fields:
-#            assert isinstance(subspecnode, SpecNodeWithBox)
-#            if oplist is None:
-#                instnode.cleanfields[ofs] = instnode.origfields[ofs]
-#                newboxlist.append(instnode.curfields[ofs].source)
-#            else:
-#                if ofs in instnode.cleanfields:
-#                    newboxlist.append(instnode.cleanfields[ofs].source)
-#                else:
-#                    box = subspecnode.box.clonebox()
-#                    oplist.append(ResOperation(rop.GETARRAYITEM_GC,
-#                       [instnode.source, ofs], box, arraydescr))
-#                    newboxlist.append(box)
-
-#    def extract_runtime_data(self, cpu, valuebox, resultlist):
-#        from pypy.jit.metainterp.resoperation import rop
-#        from pypy.jit.metainterp.optimize import FixedList
-#        from pypy.jit.metainterp.history import check_descr
-       
-#        resultlist.append(valuebox)
-#        cls = self.known_class
-#        assert isinstance(cls, FixedList)
-#        arraydescr = cls.arraydescr
-#        check_descr(arraydescr)
-#        for ofs, subspecnode in self.fields:
-#            fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC,
-#                                        [valuebox, ofs], arraydescr)
-#            subspecnode.extract_runtime_data(cpu, fieldbox, resultlist)
-
-class VirtualizableSpecNode(VirtualizedSpecNode):
-
-    def equals(self, other):
-        if not isinstance(other, VirtualizableSpecNode):
-            return False
-        return VirtualizedSpecNode.equals(self, other)        
-
-    def adapt_to(self, instnode, offsets):
-        instnode.virtualized = True
-        VirtualizedSpecNode.adapt_to(self, instnode, offsets)
-
-class VirtualizableListSpecNode(VirtualizedSpecNode):
-
-    def equals(self, other):
-        if not isinstance(other, VirtualizableListSpecNode):
-            return False
-        return VirtualizedSpecNode.equals(self, other)
-    
-    def extract_runtime_data(self, cpu, valuebox, resultlist):
-        from pypy.jit.metainterp.resoperation import rop
-        from pypy.jit.metainterp.optimize import FixedList
-        from pypy.jit.metainterp.history import check_descr
-
-        resultlist.append(valuebox)
-        cls = self.known_class
-        assert isinstance(cls, FixedList)
-        arraydescr = cls.arraydescr
-        check_descr(arraydescr)
-        for ofs, subspecnode in self.fields:
-            if not isinstance(subspecnode, MatchEverythingSpecNode):
-                fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC,
-                                            [valuebox, ofs], arraydescr)
-                subspecnode.extract_runtime_data(cpu, fieldbox, resultlist)
-
-    def adapt_to(self, instnode, offsets):
-        instnode.virtualized = True
-        VirtualizedSpecNode.adapt_to(self, instnode, offsets)
-
-class VirtualSpecNode(SpecNodeWithFields):
-
-    def adapt_to(self, instnode, offsets):
-        instnode.virtual = True
-        SpecNodeWithFields.adapt_to(self, instnode, offsets)
-
-    def mutate_nodes(self, instnode):
-        SpecNodeWithFields.mutate_nodes(self, instnode)
-        instnode.virtual = True
-
-class VirtualInstanceSpecNode(VirtualSpecNode):
-
-    def equals(self, other):
-        if not isinstance(other, VirtualInstanceSpecNode):
-            return False
-        return SpecNodeWithFields.equals(self, other)
-
-class VirtualFixedListSpecNode(VirtualSpecNode):
-
-   def __init__(self, known_class, fields, known_length):
-       VirtualSpecNode.__init__(self, known_class, fields)
-       self.known_length = known_length
-
-   def mutate_nodes(self, instnode):
-       VirtualSpecNode.mutate_nodes(self, instnode)
-       instnode.cursize = self.known_length
-
-   def equals(self, other):
-       if not isinstance(other, VirtualFixedListSpecNode):
-           return False
-       return SpecNodeWithFields.equals(self, other)
-    
-   def extract_runtime_data(self, cpu, valuebox, resultlist):
-       from pypy.jit.metainterp.resoperation import rop
-       from pypy.jit.metainterp.optimize import FixedList
-       from pypy.jit.metainterp.history import check_descr
-       cls = self.known_class
-       assert isinstance(cls, FixedList)
-       arraydescr = cls.arraydescr
-       check_descr(arraydescr)
-       for ofs, subspecnode in self.fields:
-           fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC,
-                                       [valuebox, ofs], arraydescr)
-           subspecnode.extract_runtime_data(cpu, fieldbox, resultlist)

Modified: pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimize.py
==============================================================================
--- pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimize.py	(original)
+++ pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimize.py	Fri Jul 17 16:46:32 2009
@@ -7,7 +7,9 @@
 from pypy.jit.backend.llgraph import runner
 from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr,
                                          Const, ConstAddr, TreeLoop, BoxObj)
-from pypy.jit.metainterp.optimize import perfect_specialization_finder
+from pypy.jit.metainterp.optimize import PerfectSpecializationFinder
+from pypy.jit.metainterp.specnode import NotSpecNode, FixedClassSpecNode
+from pypy.jit.metainterp.specnode import VirtualInstanceSpecNode
 from pypy.jit.metainterp.test.oparser import parse
 
 # ____________________________________________________________
@@ -56,12 +58,16 @@
 
     node_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
     node_vtable_adr = llmemory.cast_ptr_to_adr(node_vtable)
+    node_vtable2 = lltype.malloc(OBJECT_VTABLE, immortal=True)
+    node_vtable_adr2 = llmemory.cast_ptr_to_adr(node_vtable2)
     cpu = runner.LLtypeCPU(None)
 
     NODE = lltype.GcForwardReference()
     NODE.become(lltype.GcStruct('NODE', ('parent', OBJECT),
                                         ('value', lltype.Signed),
                                         ('next', lltype.Ptr(NODE))))
+    NODE2 = lltype.GcStruct('NODE2', ('parent', NODE),
+                                     ('other', lltype.Ptr(NODE)))
     node = lltype.malloc(NODE)
     nodebox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node))
     nodebox2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node))
@@ -69,7 +75,8 @@
     valuedescr = cpu.fielddescrof(NODE, 'value')
     nextdescr = cpu.fielddescrof(NODE, 'next')
 
-    cpu.class_sizes = {cpu.cast_adr_to_int(node_vtable_adr): cpu.sizeof(NODE)}
+    cpu.class_sizes = {cpu.cast_adr_to_int(node_vtable_adr): cpu.sizeof(NODE),
+                      cpu.cast_adr_to_int(node_vtable_adr2): cpu.sizeof(NODE2)}
     namespace = locals()
 
 class OOtypeMixin(object):
@@ -80,9 +87,12 @@
     NODE = ootype.Instance('NODE', ootype.ROOT, {})
     NODE._add_fields({'value': ootype.Signed,
                       'next': NODE})
+    NODE2 = ootype.Instance('NODE2', NODE, {'other': NODE})
 
     node_vtable = ootype.runtimeClass(NODE)
     node_vtable_adr = ootype.cast_to_object(node_vtable)
+    node_vtable2 = ootype.runtimeClass(NODE2)
+    node_vtable_adr2 = ootype.cast_to_object(node_vtable2)
 
     node = ootype.new(NODE)
     nodebox = BoxObj(ootype.cast_to_object(node))
@@ -91,7 +101,8 @@
     nextdescr = cpu.fielddescrof(NODE, 'next')
     nodesize = cpu.typedescrof(NODE)
 
-    cpu.class_sizes = {node_vtable_adr: cpu.typedescrof(NODE)}
+    cpu.class_sizes = {node_vtable_adr: cpu.typedescrof(NODE),
+                       node_vtable_adr2: cpu.typedescrof(NODE2)}
     namespace = locals()
 
 # ____________________________________________________________
@@ -109,8 +120,11 @@
 
     def find_nodes(self, ops, boxkinds=None):
         loop = self.parse(ops, boxkinds=boxkinds)
+        perfect_specialization_finder = PerfectSpecializationFinder()
         perfect_specialization_finder.find_nodes(loop)
-        return loop.getboxes(), perfect_specialization_finder.getnode
+        return (loop.getboxes(),
+                perfect_specialization_finder.getnode,
+                perfect_specialization_finder.specnodes)
 
     def test_find_nodes_simple(self):
         ops = """
@@ -120,9 +134,10 @@
           fail(i0)
         jump(i0)
         """
-        boxes, getnode = self.find_nodes(ops)
+        boxes, getnode, specnodes = self.find_nodes(ops)
         assert getnode(boxes.i).fromstart
         assert not getnode(boxes.i0).fromstart
+        assert [sn.__class__ for sn in specnodes] == [NotSpecNode]
 
     def test_find_nodes_non_escape(self):
         ops = """
@@ -134,13 +149,14 @@
         setfield_gc(p2, i1, descr=valuedescr)
         jump(p0)
         """
-        boxes, getnode = self.find_nodes(ops)
+        boxes, getnode, specnodes = self.find_nodes(ops)
         assert not getnode(boxes.p0).escaped
         assert not getnode(boxes.p1).escaped
         assert not getnode(boxes.p2).escaped
         assert getnode(boxes.p0).fromstart
         assert getnode(boxes.p1).fromstart
         assert getnode(boxes.p2).fromstart
+        assert [sn.__class__ for sn in specnodes] == [NotSpecNode]
 
     def test_find_nodes_escape(self):
         ops = """
@@ -156,7 +172,7 @@
         setfield_gc(p4, i1, descr=valuedescr)
         jump(p0)
         """
-        boxes, getnode = self.find_nodes(ops)
+        boxes, getnode, specnodes = self.find_nodes(ops)
         assert not getnode(boxes.p0).escaped
         assert getnode(boxes.p1).escaped
         assert getnode(boxes.p2).escaped    # forced by p1
@@ -167,8 +183,21 @@
         assert getnode(boxes.p2).fromstart
         assert getnode(boxes.p3).fromstart
         assert not getnode(boxes.p4).fromstart
+        assert [sn.__class__ for sn in specnodes] == [NotSpecNode]
 
-    def test_find_nodes_guard_class(self):
+    def test_find_nodes_guard_class_1(self):
+        ops = """
+        [p1]
+        guard_class(p1, ConstClass(node_vtable))
+            fail()
+        jump(p1)
+        """
+        boxes, getnode, specnodes = self.find_nodes(ops)
+        boxp1 = getnode(boxes.p1)
+        assert boxp1.knownclsbox.value == self.node_vtable_adr
+        assert [sn.__class__ for sn in specnodes] == [FixedClassSpecNode]
+
+    def test_find_nodes_guard_class_2(self):
         ops = """
         [p1]
         p2 = getfield_gc(p1, descr=nextdescr)
@@ -176,15 +205,79 @@
             fail()
         jump(p1)
         """
-        boxes, getnode = self.find_nodes(ops)
+        boxes, getnode, specnodes = self.find_nodes(ops)
+        boxp1 = getnode(boxes.p1)
+        boxp2 = getnode(boxes.p2)
+        assert boxp1.knownclsbox is None
+        assert boxp2.knownclsbox.value == self.node_vtable_adr
+        assert [sn.__class__ for sn in specnodes] == [NotSpecNode]
+
+    def test_find_nodes_guard_class_outonly(self):
+        ops = """
+        [p1]
+        p2 = escape()
+        guard_class(p2, ConstClass(node_vtable))
+            fail()
+        jump(p2)
+        """
+        boxes, getnode, specnodes = self.find_nodes(ops)
+        boxp1 = getnode(boxes.p1)
+        boxp2 = getnode(boxes.p2)
+        assert boxp1.knownclsbox is None
+        assert boxp2.knownclsbox.value == self.node_vtable_adr
+        assert [sn.__class__ for sn in specnodes] == [NotSpecNode]
+
+    def test_find_nodes_guard_class_inonly(self):
+        ops = """
+        [p1]
+        guard_class(p1, ConstClass(node_vtable))
+            fail()
+        p2 = escape()
+        jump(p2)
+        """
+        boxes, getnode, specnodes = self.find_nodes(ops)
+        boxp1 = getnode(boxes.p1)
+        boxp2 = getnode(boxes.p2)
+        assert boxp1.knownclsbox.value == self.node_vtable_adr
+        assert boxp2.knownclsbox is None
+        assert [sn.__class__ for sn in specnodes] == [NotSpecNode]
+
+    def test_find_nodes_guard_class_inout(self):
+        ops = """
+        [p1]
+        guard_class(p1, ConstClass(node_vtable))
+            fail()
+        p2 = escape()
+        guard_class(p2, ConstClass(node_vtable))
+            fail()
+        jump(p2)
+        """
+        boxes, getnode, specnodes = self.find_nodes(ops)
         boxp1 = getnode(boxes.p1)
         boxp2 = getnode(boxes.p2)
-        assert not boxp1.origclass
-        assert boxp1.curclass is None
-        assert boxp2.origclass
-        assert boxp2.curclass.value == self.node_vtable_adr
+        assert boxp1.knownclsbox.value == self.node_vtable_adr
+        assert boxp2.knownclsbox.value == self.node_vtable_adr
+        assert [sn.__class__ for sn in specnodes] == [FixedClassSpecNode]
+
+    def test_find_nodes_guard_class_mismatch(self):
+        ops = """
+        [p1]
+        guard_class(p1, ConstClass(node_vtable))
+            fail()
+        p2 = escape()
+        guard_class(p2, ConstClass(node_vtable2))
+            fail()
+        jump(p2)
+        """
+        boxes, getnode, specnodes = self.find_nodes(ops)
+        boxp1 = getnode(boxes.p1)
+        boxp2 = getnode(boxes.p2)
+        assert boxp1.knownclsbox.value == self.node_vtable_adr
+        assert boxp2.knownclsbox.value == self.node_vtable_adr2
+        assert [sn.__class__ for sn in specnodes] == [NotSpecNode]
 
     def test_find_nodes_new(self):
+        py.test.skip("VirtualInstanceSpecNode in-progress")
         ops = """
         [sum, p1]
         guard_class(p1, ConstClass(node_vtable))
@@ -197,8 +290,8 @@
         setfield_gc(p2, p2, descr=nextdescr)
         jump(sum2, p2)
         """
-        boxes, getnode = self.find_nodes(ops, boxkinds={'sum': BoxInt,
-                                                        'sum2': BoxInt})
+        boxes, getnode, specnodes = self.find_nodes(
+            ops, boxkinds={'sum': BoxInt, 'sum2': BoxInt})
         assert getnode(boxes.sum) is not getnode(boxes.sum2)
         assert getnode(boxes.p1) is not getnode(boxes.p2)
 
@@ -215,10 +308,11 @@
         assert boxp1.fromstart
         assert not boxp2.fromstart
 
-        assert boxp1.origclass
-        assert boxp1.curclass.value == self.node_vtable_adr
-        assert not boxp2.origclass
-        assert boxp2.curclass.value == self.node_vtable_adr
+        assert boxp1.knownclsbox.value == self.node_vtable_adr
+        assert boxp2.knownclsbox.value == self.node_vtable_adr
+
+        assert [sn.__class__ for sn in specnodes] == [NotSpecNode,
+                                                      VirtualInstanceSpecNode]
 
 
 class TestLLtype(BaseTestOptimize, LLtypeMixin):



More information about the Pypy-commit mailing list