[pypy-svn] r69772 - in pypy/trunk/pypy/jit/metainterp: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Mon Nov 30 17:13:05 CET 2009


Author: cfbolz
Date: Mon Nov 30 17:13:04 2009
New Revision: 69772

Modified:
   pypy/trunk/pypy/jit/metainterp/optimizeopt.py
   pypy/trunk/pypy/jit/metainterp/optimizeutil.py
   pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py
   pypy/trunk/pypy/jit/metainterp/test/test_resume.py
Log:
Share the field descr lists between all virtual info objects that have the same
layout, not just those coming from the same specific virtual instance. This is
done by having a sharing-dict-like (or SELF map-like) approach.


Modified: pypy/trunk/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/optimizeopt.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/optimizeopt.py	Mon Nov 30 17:13:04 2009
@@ -9,7 +9,7 @@
 from pypy.jit.metainterp.specnode import VirtualInstanceSpecNode
 from pypy.jit.metainterp.specnode import VirtualArraySpecNode
 from pypy.jit.metainterp.specnode import VirtualStructSpecNode
-from pypy.jit.metainterp.optimizeutil import av_newdict2, _findall, sort_descrs
+from pypy.jit.metainterp.optimizeutil import av_newdict2, av_newdict_int, _findall
 from pypy.jit.metainterp.optimizeutil import InvalidLoop
 from pypy.jit.metainterp import resume, compile
 from pypy.jit.metainterp.typesystem import llhelper, oohelper
@@ -173,20 +173,60 @@
         raise NotImplementedError("abstract base")
 
 
+class FieldMap(object):
+    def __init__(self, prev, newfield):
+        if prev is not None:
+            assert newfield is not None
+            self.fieldindexes = prev.fieldindexes.copy()
+            self.fieldindexes[newfield] = len(self.fieldindexes)
+            self.fieldlist = prev.fieldlist + [newfield]
+        else:
+            assert newfield is None
+            self.fieldindexes = av_newdict_int()
+            self.fieldlist = []
+        self.nextmaps = av_newdict2()
+
+    def getindex(self, field):
+        return self.fieldindexes.get(field, -1)
+
+    def nextmap(self, field):
+        result = self.nextmaps.get(field, None)
+        if result is None:
+            result = FieldMap(self, field)
+            self.nextmaps[field] = result
+        return result
+
+def get_no_fields_map(cpu):
+    if hasattr(cpu, '_optimizeopt_fieldmap'):
+        return cpu._optimizeopt_fieldmap
+    res = FieldMap(None, None)
+    cpu._optimizeopt_fieldmap = res
+    return res
+get_no_fields_map._annspecialcase_ = 'specialize:memo'
+
 class AbstractVirtualStructValue(AbstractVirtualValue):
-    _attrs_ = ('_fields', '_cached_sorted_fields')
+    _attrs_ = ('_fieldmap', '_fieldvalues')
 
     def __init__(self, optimizer, keybox, source_op=None):
         AbstractVirtualValue.__init__(self, optimizer, keybox, source_op)
-        self._fields = av_newdict2()
-        self._cached_sorted_fields = None
+        self._fieldmap = get_no_fields_map(optimizer.cpu)
+        self._fieldvalues = []
 
     def getfield(self, ofs, default):
-        return self._fields.get(ofs, default)
+        i = self._fieldmap.getindex(ofs)
+        if i == -1:
+            return default
+        return self._fieldvalues[i]
 
     def setfield(self, ofs, fieldvalue):
         assert isinstance(fieldvalue, OptValue)
-        self._fields[ofs] = fieldvalue
+        i = self._fieldmap.getindex(ofs)
+        if i != -1:
+            self._fieldvalues[i] = fieldvalue
+        else:
+            self._fieldmap = self._fieldmap.nextmap(ofs)
+            self._fieldvalues.append(fieldvalue)
+
 
     def _really_force(self):
         assert self.source_op is not None
@@ -194,39 +234,30 @@
         newoperations.append(self.source_op)
         self.box = box = self.source_op.result
         #
-        iteritems = self._fields.iteritems()
-        if not we_are_translated(): #random order is fine, except for tests
-            iteritems = list(iteritems)
-            iteritems.sort(key = lambda (x,y): x.sort_key())
-        for ofs, value in iteritems:
+        #if not we_are_translated(): #random order is fine, except for tests
+        #    iteritems = self._fields.iteritems()
+        #    iteritems = list(iteritems)
+        #    iteritems.sort(key = lambda (x,y): x.sort_key())
+        for i in range(len(self._fieldmap.fieldlist)):
+            ofs = self._fieldmap.fieldlist[i]
+            value = self._fieldvalues[i]
             subbox = value.force_box()
             op = ResOperation(rop.SETFIELD_GC, [box, subbox], None,
                               descr=ofs)
             newoperations.append(op)
-        self._fields = None
+        self._fieldvalues = None
 
     def _get_field_descr_list(self):
-        # this shares only per instance and not per type, but better than nothing
-        _cached_sorted_fields = self._cached_sorted_fields
-        if (_cached_sorted_fields is not None and
-            len(self._fields) == len(_cached_sorted_fields)):
-            lst = self._cached_sorted_fields
-        else:
-            lst = self._fields.keys()
-            sort_descrs(lst)
-            self._cached_sorted_fields = lst
-        return lst
+        return self._fieldmap.fieldlist
 
     def get_args_for_fail(self, modifier):
+        # modifier.already_seen_virtual()
+        # checks for recursion: it is False unless
+        # we have already seen the very same keybox
         if self.box is None and not modifier.already_seen_virtual(self.keybox):
-            # modifier.already_seen_virtual()
-            # checks for recursion: it is False unless
-            # we have already seen the very same keybox
-            lst = self._get_field_descr_list()
-            fieldboxes = [self._fields[ofs].get_key_box() for ofs in lst]
+            fieldboxes = [value.get_key_box() for value in self._fieldvalues]
             modifier.register_virtual_fields(self.keybox, fieldboxes)
-            for ofs in lst:
-                fieldvalue = self._fields[ofs]
+            for fieldvalue in self._fieldvalues:
                 fieldvalue.get_args_for_fail(modifier)
 
 

Modified: pypy/trunk/pypy/jit/metainterp/optimizeutil.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/optimizeutil.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/optimizeutil.py	Mon Nov 30 17:13:04 2009
@@ -24,6 +24,9 @@
     # the values...
     return r_dict(av_eq, av_hash)
 
+def av_newdict_int():
+    return r_dict(av_eq, av_hash)
+
 def _findall(Class, name_prefix):
     result = []
     for value, name in resoperation.opname.items():

Modified: pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py	Mon Nov 30 17:13:04 2009
@@ -63,16 +63,28 @@
     assert fdescr.rd_consts == []
 
 def test_sharing_field_lists_of_virtual():
-    virt1 = optimizeopt.AbstractVirtualStructValue(None, None)
+    class FakeOptimizer(object):
+        class cpu(object):
+            pass
+    opt = FakeOptimizer()
+    virt1 = optimizeopt.AbstractVirtualStructValue(opt, None)
     lst1 = virt1._get_field_descr_list()
     assert lst1 == []
     lst2 = virt1._get_field_descr_list()
     assert lst1 is lst2
     virt1.setfield(LLtypeMixin.valuedescr, optimizeopt.OptValue(None))
-    lst1 = virt1._get_field_descr_list()
-    assert lst1 == [LLtypeMixin.valuedescr]
-    lst2 = virt1._get_field_descr_list()
-    assert lst1 is lst2
+    lst3 = virt1._get_field_descr_list()
+    assert lst3 == [LLtypeMixin.valuedescr]
+    lst4 = virt1._get_field_descr_list()
+    assert lst3 is lst4
+    
+    virt2 = optimizeopt.AbstractVirtualStructValue(opt, None)
+    lst5 = virt2._get_field_descr_list()
+    assert lst5 is lst1
+    virt2.setfield(LLtypeMixin.valuedescr, optimizeopt.OptValue(None))
+    lst6 = virt1._get_field_descr_list()
+    assert lst6 is lst3
+
 
 def test_reuse_vinfo():
     class FakeVInfo(object):
@@ -90,6 +102,15 @@
     assert vinfo3 is vinfo4
     
 
+def test_fieldmap():
+    map = optimizeopt.FieldMap(None, None)
+    assert map.getindex(LLtypeMixin.valuedescr) == -1
+    map2 = map.nextmap(LLtypeMixin.valuedescr)
+    assert map2.getindex(LLtypeMixin.valuedescr) == 0
+    assert map2.fieldlist == [LLtypeMixin.valuedescr]
+    map3 = map.nextmap(LLtypeMixin.valuedescr)
+    assert map2 is map3
+
 # ____________________________________________________________
 
 def equaloplists(oplist1, oplist2, strict_fail_args=True, remap={}):

Modified: pypy/trunk/pypy/jit/metainterp/test/test_resume.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_resume.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_resume.py	Mon Nov 30 17:13:04 2009
@@ -358,13 +358,18 @@
     assert metainterp.framestack == fs2
 
 
+class FakeOptimizer_VirtualValue(object):
+    class cpu:
+        pass
+fakeoptimizer = FakeOptimizer_VirtualValue()
+
 def virtual_value(keybox, value, next):
-    vv = VirtualValue(None, ConstAddr(LLtypeMixin.node_vtable_adr,
-                                      LLtypeMixin.cpu), keybox)
+    vv = VirtualValue(fakeoptimizer, ConstAddr(LLtypeMixin.node_vtable_adr,
+                                     LLtypeMixin.cpu), keybox)
     if not isinstance(next, OptValue):
         next = OptValue(next)
-    vv.setfield(LLtypeMixin.nextdescr, next)
     vv.setfield(LLtypeMixin.valuedescr, OptValue(value))
+    vv.setfield(LLtypeMixin.nextdescr, next)
     return vv
 
 def test_rebuild_from_resumedata_two_guards_w_virtuals():
@@ -797,18 +802,16 @@
     modifier.liveboxes = {}
     modifier.vfieldboxes = {}
 
-    v2 = VirtualValue(None, ConstAddr(LLtypeMixin.node_vtable_adr,
-                                                LLtypeMixin.cpu), b2s)
-    v2._fields = {LLtypeMixin.nextdescr: b4s,
-                  LLtypeMixin.valuedescr: c1s}
-    v2._cached_sorted_fields = [LLtypeMixin.nextdescr, LLtypeMixin.valuedescr]
-    v4 = VirtualValue(None, ConstAddr(LLtypeMixin.node_vtable_adr2,
+    v4 = VirtualValue(fakeoptimizer, ConstAddr(LLtypeMixin.node_vtable_adr2,
                                                 LLtypeMixin.cpu), b4s)
-    v4._fields = {LLtypeMixin.nextdescr: b2s,
-                  LLtypeMixin.valuedescr: b3s,
-                  LLtypeMixin.otherdescr: b5s}
-    v4._cached_sorted_fields = [LLtypeMixin.nextdescr, LLtypeMixin.valuedescr,
-                                LLtypeMixin.otherdescr]
+    v4.setfield(LLtypeMixin.nextdescr, OptValue(b2s))
+    v4.setfield(LLtypeMixin.valuedescr, OptValue(b3s))
+    v4.setfield(LLtypeMixin.otherdescr, OptValue(b5s))
+    v2 = VirtualValue(fakeoptimizer, ConstAddr(LLtypeMixin.node_vtable_adr,
+                                                LLtypeMixin.cpu), b2s)
+    v2.setfield(LLtypeMixin.nextdescr, v4)
+    v2.setfield(LLtypeMixin.valuedescr, OptValue(c1s))
+
     modifier.register_virtual_fields(b2s, [b4s, c1s])
     modifier.register_virtual_fields(b4s, [b2s, b3s, b5s])
     values = {b2s: v2, b4s: v4}
@@ -870,6 +873,8 @@
     modifier.vfieldboxes = {}
 
     class FakeOptimizer(object):
+        class cpu:
+            pass
         def new_const_item(self, descr):
             return None
     v2 = VArrayValue(FakeOptimizer(), LLtypeMixin.arraydescr, 2, b2s)
@@ -918,9 +923,9 @@
     modifier.liveboxes_from_env = {}
     modifier.liveboxes = {}
     modifier.vfieldboxes = {}
-    v2 = VStructValue(None, LLtypeMixin.ssize, b2s)
-    v2._fields = {LLtypeMixin.adescr: c1s, LLtypeMixin.bdescr: b4s}
-    v2._cached_sorted_fields = [LLtypeMixin.adescr, LLtypeMixin.bdescr]
+    v2 = VStructValue(fakeoptimizer, LLtypeMixin.ssize, b2s)
+    v2.setfield(LLtypeMixin.adescr, OptValue(c1s))
+    v2.setfield(LLtypeMixin.bdescr, OptValue(b4s))
     modifier.register_virtual_fields(b2s, [c1s, b4s])
     liveboxes = []
     modifier._number_virtuals(liveboxes, {b2s: v2}, 0)



More information about the Pypy-commit mailing list