[pypy-commit] pypy default: (l.diekmann, cfbolz): Be more careful about unrolling getitems. also make one less copy

l.diekmann noreply at buildbot.pypy.org
Thu Dec 8 17:55:21 CET 2011


Author: Lukas Diekmann <lukas.diekmann at uni-duesseldorf.de>
Branch: 
Changeset: r50310:f19d06a5972d
Date: 2011-12-08 17:27 +0100
http://bitbucket.org/pypy/pypy/changeset/f19d06a5972d/

Log:	(l.diekmann, cfbolz): Be more careful about unrolling getitems. also
	make one less copy

diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -9,8 +9,9 @@
 from pypy.interpreter import gateway, baseobjspace
 from pypy.rlib.objectmodel import instantiate, specialize
 from pypy.rlib.listsort import make_timsort_class
-from pypy.rlib import rerased, jit
+from pypy.rlib import rerased, jit, debug
 from pypy.interpreter.argument import Signature
+from pypy.tool.sourcetools import func_with_new_name
 
 UNROLL_CUTOFF = 5
 
@@ -170,6 +171,19 @@
         share with the storage, if possible."""
         return self.strategy.getitems(self)
 
+    def getitems_fixedsize(self):
+        """Returns a fixed-size list of all items after wrapping them."""
+        l = self.strategy.getitems_fixedsize(self)
+        debug.make_sure_not_resized(l)
+        return l
+
+    def getitems_unroll(self):
+        """Returns a fixed-size list of all items after wrapping them. The JIT
+        will fully unroll this function.  """
+        l = self.strategy.getitems_unroll(self)
+        debug.make_sure_not_resized(l)
+        return l
+
     def getitems_copy(self):
         """Returns a copy of all items in the list. Same as getitems except for
         ObjectListStrategy."""
@@ -366,6 +380,8 @@
 
     def getitems_copy(self, w_list):
         return []
+    getitems_fixedsize = func_with_new_name(getitems_copy, "getitems_fixedsize")
+    getitems_unroll = getitems_fixedsize
 
     def getstorage_copy(self, w_list):
         return self.erase(None)
@@ -496,7 +512,6 @@
         # tuple is unmutable
         return w_list.lstorage
 
-
     @specialize.arg(2)
     def _getitems_range(self, w_list, wrap_items):
         l = self.unerase(w_list.lstorage)
@@ -519,6 +534,13 @@
 
         return r
 
+    @jit.dont_look_inside
+    def getitems_fixedsize(self, w_list):
+        return self._getitems_range_unroll(w_list, True)
+    def getitems_unroll(self, w_list):
+        return self._getitems_range_unroll(w_list, True)
+    _getitems_range_unroll = jit.unroll_safe(func_with_new_name(_getitems_range, "_getitems_range_unroll"))
+
     def getslice(self, w_list, start, stop, step, length):
         v = self.unerase(w_list.lstorage)
         old_start = v[0]
@@ -676,6 +698,13 @@
     def getitems_copy(self, w_list):
         return [self.wrap(item) for item in self.unerase(w_list.lstorage)]
 
+    @jit.unroll_safe
+    def getitems_unroll(self, w_list):
+        return [self.wrap(item) for item in self.unerase(w_list.lstorage)]
+    @jit.dont_look_inside
+    def getitems_fixedsize(self, w_list):
+        return self.getitems_unroll(w_list)
+
     def getstorage_copy(self, w_list):
         items = self.unerase(w_list.lstorage)[:]
         return self.erase(items)
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -408,8 +408,10 @@
         if isinstance(w_obj, W_TupleObject):
             t = w_obj.wrappeditems
         elif isinstance(w_obj, W_ListObject):
-            # XXX this can copy twice
-            t = w_obj.getitems()[:]
+            if unroll:
+                t = w_obj.getitems_unroll()
+            else:
+                t = w_obj.getitems_fixedsize()
         else:
             if unroll:
                 return make_sure_not_resized(ObjSpace.unpackiterable_unroll(
diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -48,6 +48,46 @@
         for i in range(7):
             assert self.space.eq_w(l[i], l2[i])
 
+    def test_getitems_fixedsize(self):
+        w = self.space.wrap
+        from pypy.objspace.std.listobject import make_range_list
+        rangelist = make_range_list(self.space, 1,1,7)
+        emptylist = W_ListObject(self.space, [])
+        intlist = W_ListObject(self.space, [w(1),w(2),w(3),w(4),w(5),w(6),w(7)])
+        strlist = W_ListObject(self.space, [w('1'),w('2'),w('3'),w('4'),w('5'),w('6'),w('7')])
+        floatlist = W_ListObject(self.space, [w(1.0),w(2.0),w(3.0),w(4.0),w(5.0),w(6.0),w(7.0)])
+        objlist = W_ListObject(self.space, [w(1),w('2'),w(3.0),w(4),w(5),w(6),w(7)])
+
+        emptylist_copy = emptylist.getitems_fixedsize()
+        assert emptylist_copy == []
+
+        rangelist_copy = rangelist.getitems_fixedsize()
+        intlist_copy = intlist.getitems_fixedsize()
+        strlist_copy = strlist.getitems_fixedsize()
+        floatlist_copy = floatlist.getitems_fixedsize()
+        objlist_copy = objlist.getitems_fixedsize()
+        for i in range(7):
+            assert self.space.eq_w(rangelist_copy[i], rangelist.getitem(i))
+            assert self.space.eq_w(intlist_copy[i], intlist.getitem(i))
+            assert self.space.eq_w(strlist_copy[i], strlist.getitem(i))
+            assert self.space.eq_w(floatlist_copy[i], floatlist.getitem(i))
+            assert self.space.eq_w(objlist_copy[i], objlist.getitem(i))
+
+        emptylist_copy = emptylist.getitems_unroll()
+        assert emptylist_copy == []
+
+        rangelist_copy = rangelist.getitems_unroll()
+        intlist_copy = intlist.getitems_unroll()
+        strlist_copy = strlist.getitems_unroll()
+        floatlist_copy = floatlist.getitems_unroll()
+        objlist_copy = objlist.getitems_unroll()
+        for i in range(7):
+            assert self.space.eq_w(rangelist_copy[i], rangelist.getitem(i))
+            assert self.space.eq_w(intlist_copy[i], intlist.getitem(i))
+            assert self.space.eq_w(strlist_copy[i], strlist.getitem(i))
+            assert self.space.eq_w(floatlist_copy[i], floatlist.getitem(i))
+            assert self.space.eq_w(objlist_copy[i], objlist.getitem(i))
+
     def test_random_getitem(self):
         w = self.space.wrap
         s = list('qedx387tn3uixhvt 7fh387fymh3dh238 dwd-wq.dwq9')


More information about the pypy-commit mailing list