[pypy-svn] r63032 - in pypy/branch/virtualizable-specnodes/pypy/jit: backend/llgraph metainterp metainterp/test

fijal at codespeak.net fijal at codespeak.net
Wed Mar 18 14:16:21 CET 2009


Author: fijal
Date: Wed Mar 18 14:16:20 2009
New Revision: 63032

Modified:
   pypy/branch/virtualizable-specnodes/pypy/jit/backend/llgraph/runner.py
   pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/compile.py
   pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py
   pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py
   pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/test/test_virtualizable.py
   pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/virtualizable.py
Log:
in-progress checkin of dealing with virtualizable specnodes in a correct way


Modified: pypy/branch/virtualizable-specnodes/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/virtualizable-specnodes/pypy/jit/backend/llgraph/runner.py	(original)
+++ pypy/branch/virtualizable-specnodes/pypy/jit/backend/llgraph/runner.py	Wed Mar 18 14:16:20 2009
@@ -37,6 +37,11 @@
     def sort_key(self):
         return self.ofs
 
+    def equals(self, other):
+        if not isinstance(other, Descr):
+            return False
+        return self.sort_key() == other.sort_key()
+
     def __lt__(self, other):
         raise TypeError("cannot use comparison on Descrs")
     def __le__(self, other):
@@ -74,6 +79,19 @@
     def set_meta_interp(self, metainterp):
         self.metainterp = metainterp    # to handle guard failures
 
+    def compile_arg(self, x, c, op, var2index):
+        if isinstance(x, history.Box):
+            llimpl.compile_add_var(c, var2index[x])
+        elif isinstance(x, history.ConstInt):
+            llimpl.compile_add_int_const(c, x.value)
+        elif isinstance(x, history.ConstPtr):
+            llimpl.compile_add_ptr_const(c, x.value)
+        elif isinstance(x, history.ConstAddr):
+            llimpl.compile_add_int_const(c, x.getint())
+        else:
+            raise Exception("%s args contain: %r" % (op.getopname(),
+                                                     x))
+
     def compile_operations(self, operations, from_guard=None):
         """In a real assembler backend, this should assemble the given
         list of operations.  Here we just generate a similar LoopOrBridge
@@ -105,17 +123,7 @@
             if op.descr is not None:
                 llimpl.compile_add_descr(c, op.descr.ofs, op.descr.type)
             for x in op.args:
-                if isinstance(x, history.Box):
-                    llimpl.compile_add_var(c, var2index[x])
-                elif isinstance(x, history.ConstInt):
-                    llimpl.compile_add_int_const(c, x.value)
-                elif isinstance(x, history.ConstPtr):
-                    llimpl.compile_add_ptr_const(c, x.value)
-                elif isinstance(x, history.ConstAddr):
-                    llimpl.compile_add_int_const(c, x.getint())
-                else:
-                    raise Exception("%s args contain: %r" % (op.getopname(),
-                                                             x))
+                self.compile_arg(x, c, op, var2index)
             x = op.result
             if x is not None:
                 if isinstance(x, history.BoxInt):
@@ -142,6 +150,9 @@
             llimpl.compile_from_guard(c, from_guard._compiled,
                                          from_guard._opindex)
 
+    def update_loop(self, loop, mp, guard_op, newboxlist):
+        self.compile_operations(loop.operations)
+
     def execute_operations_in_new_frame(self, name, operations, valueboxes):
         """Perform a 'call' to the given merge point, i.e. create
         a new CPU frame and use it to execute the operations that

Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/compile.py	(original)
+++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/compile.py	Wed Mar 18 14:16:20 2009
@@ -112,6 +112,7 @@
     else:
         name = 'Loop #%d' % len(metainterp.stats.loops)
     graph = Graph(name, '#f084c2')
+    graph.extensions = [None]
     return graph
 
 def create_empty_bridge(metainterp):
@@ -120,6 +121,7 @@
     else:
         name = 'Bridge #%d' % len(metainterp.stats.loops)
     graph = Graph(name, '#84f0c2')
+    graph.extensions = [None]
     return graph
 
 # ____________________________________________________________
@@ -149,6 +151,15 @@
     metainterp.cpu.compile_operations(loop.operations, guard_op)
     metainterp.stats.loops.append(loop)
 
+def update_loop(metainterp, loop, guard_op, newboxlist):
+    mp = loop.operations[0]
+    mp.args += newboxlist
+    jump = loop.operations[-1]
+    jump.args += newboxlist
+    guard_op.liveboxes += newboxlist
+    guard_op.storage = None
+    metainterp.cpu.update_loop(loop, mp, guard_op, newboxlist)
+
 # ____________________________________________________________
 
 def matching_merge_point(metainterp, targetmp, endliveboxes):
@@ -165,10 +176,14 @@
     op = ResOperation(rop.JUMP, endliveboxes, None)
     operations.append(op)
     #
-    old_loop = optimize.optimize_bridge(metainterp.options, old_loops, bridge,
-                                        metainterp.cpu)
+    old_loop, newboxlist = optimize.optimize_bridge(metainterp.options,
+                                                    old_loops, bridge,
+                                                    metainterp.cpu)
     if old_loop is None:
         return None
     bridge.jump_to = old_loop
+    if newboxlist:
+        # recompile loop
+        update_loop(metainterp, old_loop, guard_op, newboxlist)
     finish_loop_or_bridge(metainterp, bridge, old_loop.operations[0], guard_op)
     return bridge

Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py
==============================================================================
--- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py	(original)
+++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/optimize.py	Wed Mar 18 14:16:20 2009
@@ -3,15 +3,10 @@
                                          ResOperation, AbstractDescr,
                                          Options, AbstractValue, ConstPtr)
 from pypy.jit.metainterp.specnode import (FixedClassSpecNode,
-                                          VirtualInstanceSpecNode,
-                                          VirtualizableSpecNode,
-                                          NotSpecNode,
-                                          DelayedSpecNode,
-                                          SpecNodeWithBox,
-                                          DelayedFixedListSpecNode,
-                                          VirtualFixedListSpecNode,
-                                          VirtualizableListSpecNode,
-                                          )
+     VirtualInstanceSpecNode, VirtualizableSpecNode, NotSpecNode,
+     DelayedSpecNode, SpecNodeWithBox, DelayedFixedListSpecNode,
+     VirtualFixedListSpecNode, MatchEverythingSpecNode,
+     VirtualizableListSpecNode, av_eq, av_hash)
 from pypy.jit.metainterp import executor
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rpython.lltypesystem import lltype, llmemory
@@ -106,12 +101,6 @@
             liveboxes.append(box)
         return res
 
-def av_eq(self, other):
-    return self.sort_key() == other.sort_key()
-
-def av_hash(self):
-    return self.sort_key()
-
 def av_list_in(lst, key):
     # lst is a list of about 2 elements in the typical case, so no
     # point in making a dict lookup
@@ -139,6 +128,7 @@
         self.expanded_fields = r_dict(av_eq, av_hash)
         self.cursize = -1
         self.vdesc = None # for virtualizables
+        self.allfields = None
 
     def is_nonzero(self):
         return self.cls is not None or self.nonzero
@@ -146,7 +136,7 @@
     def is_zero(self):
         return self.const and not self.source.getptr_base()
 
-    def escape_if_startbox(self, memo):
+    def escape_if_startbox(self, memo, cpu):
         if self in memo:
             return
         memo[self] = None
@@ -154,23 +144,29 @@
             self.escaped = True
         if not self.virtualized:
             for node in self.curfields.values():
-                node.escape_if_startbox(memo)
+                node.escape_if_startbox(memo, cpu)
         else:
             for key, node in self.curfields.items():
                 if self.vdesc is not None and av_list_in(self.vdesc, key):
-                    node.virtualized = True
-                    if node.cls is None:
-                        node.cls = InstanceNode(FixedClass(), const=True)
-                node.escape_if_startbox(memo)
+                    node.initialize_virtualizable(cpu)
+                node.escape_if_startbox(memo, cpu)
             # we also need to escape fields that are only read, never written,
             # if they're not marked specifically as ones that does not escape
             for key, node in self.origfields.items():
                 if key not in self.curfields:
                     if self.vdesc is not None and av_list_in(self.vdesc, key):
-                        node.virtualized = True
-                        if node.cls is None:
-                            node.cls = InstanceNode(FixedClass(), const=True)
-                    node.escape_if_startbox(memo)
+                        node.initialize_virtualizable(cpu)
+                    node.escape_if_startbox(memo, cpu)
+
+    def initialize_virtualizable(self, cpu):
+        self.virtualized = True
+        if self.cls is None:
+            self.cls = InstanceNode(FixedClass(), const=True)
+            self.allfields = xxx
+        else:
+            ad = self.cls.source.arraydescr
+            lgtbox = cpu.do_arraylen_gc([self.source], ad)
+            self.allfields = [ConstInt(i) for i in range(lgtbox.getint())]
 
     def add_to_dependency_graph(self, other, dep_graph):
         dep_graph.append((self, other))
@@ -228,9 +224,7 @@
             return DelayedSpecNode(known_class, fields)
         else:
             assert self is other
-            d = self.origfields.copy()
-            d.update(other.curfields)
-            offsets = d.keys()
+            offsets = self.allfields
             sort_descrs(offsets)
             fields = []
             for ofs in offsets:
@@ -242,10 +236,11 @@
                         self.origfields[ofs].cls = node.cls
                         nodes[box] = self.origfields[ofs]
                     specnode = self.origfields[ofs].intersect(node, nodes)
-                else:
-                    # ofs in self.origfields:
+                elif ofs in self.origfields:
                     node = self.origfields[ofs]
                     specnode = node.intersect(node, nodes)
+                else:
+                    specnode = MatchEverythingSpecNode()
                 fields.append((ofs, specnode))
             if isinstance(known_class, FixedList):
                 return VirtualizableListSpecNode(known_class, fields)
@@ -285,9 +280,14 @@
     perfect_specializer.find_nodes()
     for old_loop in old_loops:
         if perfect_specializer.match(old_loop.operations):
-            perfect_specializer.adapt_for_match(old_loop.operations)
+            num = len(old_loop.extensions)
+            newlist, newspecnodes = perfect_specializer.adapt_for_match(
+                old_loop.operations, num)
+            if newlist:
+                old_loop.extensions.append(newspecnodes)
+            perfect_specializer.loop.operations[0].args.extend(newlist)
             perfect_specializer.optimize_loop()
-            return old_loop
+            return old_loop, newlist
     return None     # no loop matches
 
 class PerfectSpecializer(object):
@@ -439,7 +439,8 @@
                 if instnode.cls is None:
                     instnode.cls = InstanceNode(op.args[1], const=True)
                     if op.vdesc:
-                        instnode.vdesc = op.vdesc.virtuals
+                        instnode.vdesc     = op.vdesc.virtuals
+                        instnode.allfields = op.vdesc.fields
                 continue
             elif op.is_always_pure():
                 for arg in op.args:
@@ -469,7 +470,7 @@
         for i in range(len(end_args)):
             end_box = end_args[i]
             if isinstance(end_box, Box):
-                self.nodes[end_box].escape_if_startbox(memo)
+                self.nodes[end_box].escape_if_startbox(memo, self.cpu)
         for i in range(len(end_args)):
             box = self.loop.operations[0].args[i]
             other_box = end_args[i]
@@ -508,18 +509,28 @@
             box = boxlist[i]
             specnode = self.specnodes[i]
             specnode.expand_boxlist(self.nodes[box], newboxlist, oplist)
+        l = []
+        for i, (group, arg) in enumerate(newboxlist):
+            l.append((group, i, arg))
+        l.sort()
+        return [e[2] for e in l]
+
         return newboxlist
 
-    def optimize_guard(self, op):
-        liveboxes = []
+    def deal_with_boxes(self, boxes):
         storage = AllocationStorage()
-        memo = {}
+        newboxes = []
         indices = []
+        memo = {}
+        for box in boxes:
+            indices.append(storage.deal_with_box(box, self.nodes, newboxes,
+                                                 memo))
+        return storage, newboxes, indices
+
+    def optimize_guard(self, op):
         old_boxes = op.liveboxes
         op = op.clone()
-        for box in old_boxes:
-            indices.append(storage.deal_with_box(box, self.nodes,
-                                                 liveboxes, memo))
+        storage, liveboxes, indices = self.deal_with_boxes(old_boxes)
         rev_boxes = {}
         for i in range(len(liveboxes)):
             box = liveboxes[i]
@@ -821,14 +832,18 @@
                 return False
         return True
 
-    def adapt_for_match(self, old_operations):
+    def adapt_for_match(self, old_operations, num):
         old_mp = old_operations[0]
         jump_op = self.loop.operations[-1]
         self.specnodes = old_mp.specnodes
+        newboxlist = []
+        extensions = []
         for i in range(len(old_mp.specnodes)):
             old_specnode = old_mp.specnodes[i]
             new_instnode = self.nodes[jump_op.args[i]]
-            old_specnode.adapt_to(new_instnode)
+            old_specnode.adapt_to(new_instnode, newboxlist, extensions, num)
+        newboxlist = [i for _, i in newboxlist]
+        return newboxlist, extensions
 
 class Chooser(object):
     def __init__(self, boxes_from_frame, allocated_boxes, allocated_lists):

Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/pyjitpl.py	Wed Mar 18 14:16:20 2009
@@ -898,7 +898,11 @@
         for i in range(len(mp.specnodes)):
             specnode = mp.specnodes[i]
             specnode.extract_runtime_data(self.cpu, args[i], expanded_args)
-        return expanded_args
+        l = []
+        for i, (group, arg) in enumerate(expanded_args):
+            l.append((group, i, arg))
+        l.sort()
+        return [e[2] for e in l]
 
     def _initialize_from_start(self, original_boxes, num_green_args, *args):
         if args:

Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py
==============================================================================
--- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py	(original)
+++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/specnode.py	Wed Mar 18 14:16:20 2009
@@ -1,15 +1,22 @@
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.metainterp import executor
+from pypy.rlib.objectmodel import r_dict
+
+def av_eq(self, other):
+    return self.sort_key() == other.sort_key()
+
+def av_hash(self):
+    return self.sort_key()
 
 class SpecNode(object):
 
     def expand_boxlist(self, instnode, newboxlist, start):
-        newboxlist.append(instnode.source)
+        newboxlist.append((0, instnode.source))
 
     def extract_runtime_data(self, cpu, valuebox, resultlist):
-        resultlist.append(valuebox)
+        resultlist.append((0, valuebox))
 
-    def adapt_to(self, instnode):
+    def adapt_to(self, instnode, newboxlist, newspecnodes, num):
         instnode.escaped = True
 
     def mutate_nodes(self, instnode):
@@ -21,6 +28,33 @@
     def matches(self, other):
         raise NotImplementedError
 
+class RedirectingSpecNode(SpecNode):
+    def __init__(self, specnode, group):
+        self.redirect_to = specnode
+        self.group = group
+
+    def expand_boxlist(self, instnode, newboxlist, start):
+        l = []
+        self.redirect_to.expand_boxlist(instnode, l, start)
+        newboxlist.extend([(self.group, e) for _, e in l])
+
+    def extract_runtime_data(self, cpu, valuebox, resultlist):
+        l = []
+        self.redirect_to.extract_runtime_data(cpu, valuebox, l)
+        resultlist.extend([(self.group, e) for _, e in l])
+
+    def adapt_to(self, *args):
+        self.redirect_to.adapt_to(*args)
+
+    def equals(self, other):
+        return self.redirect_to.equals(other)
+
+    def matches(self, other):
+        return self.redirect_to.matches(other)
+
+class MatchEverythingSpecNode(SpecNode):
+    pass
+
 class NotSpecNode(SpecNode):
     def mutate_nodes(self, instnode):
         instnode.cursize = -1
@@ -68,31 +102,20 @@
             return False
         return instnode.cls.source.equals(self.known_class)
 
-##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):
     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:
-            subinstnode = instnode.origfields[ofs]
-            # should really be there
-            subspecnode.mutate_nodes(subinstnode)
-            curfields[ofs] = subinstnode
+            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):
@@ -111,66 +134,70 @@
             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
+            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):
         for ofs, subspecnode in self.fields:
-            subinstnode = instnode.curfields[ofs]  # should really be there
-            subspecnode.expand_boxlist(subinstnode, newboxlist, start)
+            if not isinstance(subspecnode, MatchEverythingSpecNode):
+                subinstnode = instnode.curfields[ofs]  # should really be there
+                subspecnode.expand_boxlist(subinstnode, newboxlist, start)
 
     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)
-            fieldbox = executor.execute(cpu, rop.GETFIELD_GC,
-                                        [valuebox], ofs)
-            subspecnode.extract_runtime_data(cpu, fieldbox, resultlist)
+            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):
+    def adapt_to(self, instnode, newboxlist, newspecnodes, num):
         for ofs, subspecnode in self.fields:
-            subspecnode.adapt_to(instnode.curfields[ofs])
+            subspecnode.adapt_to(instnode.curfields[ofs], newboxlist,
+                                 newspecnodes, num)
 
-class VirtualizedSpecNode(SpecNodeWithFields):
+class VirtualizedOrDelayedSpecNode(SpecNodeWithFields):
     
     def expand_boxlist(self, instnode, newboxlist, start):
-        newboxlist.append(instnode.source)
+        newboxlist.append((0, instnode.source))
         SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist, start)
 
     def extract_runtime_data(self, cpu, valuebox, resultlist):
-        resultlist.append(valuebox)
+        resultlist.append((0, valuebox))
         SpecNodeWithFields.extract_runtime_data(self, cpu, valuebox, resultlist)
 
-    def adapt_to(self, instnode):
+    def adapt_to(self, instnode, newboxlist, newspecnodes, num):
         instnode.escaped = True
-        SpecNodeWithFields.adapt_to(self, instnode)
+        SpecNodeWithFields.adapt_to(self, instnode, newboxlist, newspecnodes,
+                                    num)
 
-class DelayedSpecNode(VirtualizedSpecNode):
+class DelayedSpecNode(VirtualizedOrDelayedSpecNode):
 
     def expand_boxlist(self, instnode, newboxlist, oplist):
         from pypy.jit.metainterp.history import AbstractDescr
-        newboxlist.append(instnode.source)
+        newboxlist.append((0, 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)
+                newboxlist.append((0, instnode.curfields[ofs].source))
             else:
                 if ofs in instnode.cleanfields:
-                    newboxlist.append(instnode.cleanfields[ofs].source)
+                    newboxlist.append((0, 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)
+                    newboxlist.append((0, box))
 
 class DelayedFixedListSpecNode(DelayedSpecNode):
 
@@ -179,7 +206,7 @@
        from pypy.jit.metainterp.resoperation import rop
        from pypy.jit.metainterp.optimize import FixedList
         
-       newboxlist.append(instnode.source)
+       newboxlist.append((0, instnode.source))
        cls = self.known_class
        assert isinstance(cls, FixedList)
        arraydescr = cls.arraydescr
@@ -187,22 +214,22 @@
            assert isinstance(subspecnode, SpecNodeWithBox)
            if oplist is None:
                instnode.cleanfields[ofs] = instnode.origfields[ofs]
-               newboxlist.append(instnode.curfields[ofs].source)
+               newboxlist.append((0, instnode.curfields[ofs].source))
            else:
                if ofs in instnode.cleanfields:
-                   newboxlist.append(instnode.cleanfields[ofs].source)
+                   newboxlist.append((0, instnode.cleanfields[ofs].source))
                else:
                    box = subspecnode.box.clonebox()
                    oplist.append(ResOperation(rop.GETARRAYITEM_GC,
                       [instnode.source, ofs], box, arraydescr))
-                   newboxlist.append(box)
+                   newboxlist.append((0, 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)
+       resultlist.append((0, valuebox))
        cls = self.known_class
        assert isinstance(cls, FixedList)
        arraydescr = cls.arraydescr
@@ -212,48 +239,77 @@
                                        [valuebox, ofs], arraydescr)
            subspecnode.extract_runtime_data(cpu, fieldbox, resultlist)
 
-class VirtualizableSpecNode(VirtualizedSpecNode):
+class VirtualizedSpecNode(VirtualizedOrDelayedSpecNode):
 
     def equals(self, other):
-        if not isinstance(other, VirtualizableSpecNode):
+        if not self.known_class.equals(other.known_class):
             return False
-        return SpecNodeWithFields.equals(self, other)        
+        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 adapt_to(self, instnode):
+    def adapt_to(self, instnode, newboxlist, newspecnodes, num):
         instnode.virtualized = True
-        VirtualizedSpecNode.adapt_to(self, instnode)
+        fields = []
+        for ofs, subspecnode in self.fields:
+            if isinstance(subspecnode, MatchEverythingSpecNode):
+                if ofs in instnode.curfields:
+                    orignode = instnode.origfields[ofs]
+                    node = instnode.curfields[ofs]
+                    subspecnode = orignode.intersect(node, {})
+                    subspecnode.mutate_nodes(orignode)
+                    subspecnode = RedirectingSpecNode(subspecnode, num)
+                    subspecnode.expand_boxlist(orignode, newboxlist, None)
+                    newspecnodes.append(subspecnode)
+                # otherwise we simply ignore unused field
+            else:
+                subspecnode.adapt_to(instnode.curfields[ofs], newboxlist,
+                                     newspecnodes, num)
+            fields.append((ofs, subspecnode))
+        self.fields = fields
+
+class VirtualizableSpecNode(VirtualizedSpecNode):
+
+    def equals(self, other):
+        if not isinstance(other, VirtualizableSpecNode):
+            return False
+        return VirtualizedSpecNode.equals(self, other)        
 
 class VirtualizableListSpecNode(VirtualizedSpecNode):
 
     def equals(self, other):
         if not isinstance(other, VirtualizableListSpecNode):
             return False
-        return SpecNodeWithFields.equals(self, other)
+        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)
+        resultlist.append((0, 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)
-
-    def adapt_to(self, instnode):
-        instnode.virtualized = True
-        VirtualizedSpecNode.adapt_to(self, instnode)
+            if not isinstance(subspecnode, MatchEverythingSpecNode):
+                fieldbox = executor.execute(cpu, rop.GETARRAYITEM_GC,
+                                            [valuebox, ofs], arraydescr)
+                subspecnode.extract_runtime_data(cpu, fieldbox, resultlist)
 
 class VirtualSpecNode(SpecNodeWithFields):
 
-    def adapt_to(self, instnode):
+    def adapt_to(self, instnode, newboxlist, newspecnodes, num):
         instnode.virtual = True
-        SpecNodeWithFields.adapt_to(self, instnode)
+        return SpecNodeWithFields.adapt_to(self, instnode, newboxlist,
+                                           newspecnodes, num)
 
     def mutate_nodes(self, instnode):
         SpecNodeWithFields.mutate_nodes(self, instnode)

Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/test/test_virtualizable.py
==============================================================================
--- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/test/test_virtualizable.py	(original)
+++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/test/test_virtualizable.py	Wed Mar 18 14:16:20 2009
@@ -394,7 +394,6 @@
         assert res == 2
 
     def test_pass_always_virtual_to_bridge(self):
-        py.test.skip("in-progress")
         jitdriver = JitDriver(greens = [], reds = ['frame', 'n'],
                               virtualizables = ['frame'])
 
@@ -423,7 +422,6 @@
         assert res == 3
 
     def test_virtual_obj_on_always_virtual(self):
-        py.test.skip("in-progress")
         jitdriver = JitDriver(greens = [], reds = ['frame', 'n', 's'],
                               virtualizables = ['frame'])
 
@@ -452,7 +450,7 @@
                     s += frame.l[1].elem
                     frame.l[1] = Stuff(n)
                 n -= 1
-            return s
+            return (frame.l[0].elem << 16) + frame.l[1].elem
 
         res = self.meta_interp(f, [30], listops=True)
         self.check_loops(getfield_gc=0)

Modified: pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/virtualizable.py
==============================================================================
--- pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/virtualizable.py	(original)
+++ pypy/branch/virtualizable-specnodes/pypy/jit/metainterp/virtualizable.py	Wed Mar 18 14:16:20 2009
@@ -10,5 +10,18 @@
 
     def __init__(self, cpu, TOPSTRUCT, STRUCTTYPE):
         "NOT_RPYTHON"
-        self.virtuals     = [cpu.fielddescrof(STRUCTTYPE, 'inst_' + name) for
-                             name in TOPSTRUCT._hints['virtuals']]
+        self.virtuals = [cpu.fielddescrof(STRUCTTYPE, 'inst_' + name) for
+                         name in TOPSTRUCT._hints['virtuals']]
+        self.fields = self.catch_all_fields(cpu, STRUCTTYPE)
+
+    def catch_all_fields(self, cpu, S):
+        lst = []
+        p = S
+        while True:
+            lst.extend(p._names)
+            if getattr(p, 'super', None) is not None:
+                p = p.super
+            else:
+                break
+        return [cpu.fielddescrof(S, name) for name in lst if
+                name.startswith('inst_')]



More information about the Pypy-commit mailing list