[pypy-commit] pypy default: Also use the same jitdriver for list(generator).

arigo noreply at buildbot.pypy.org
Tue Nov 1 13:04:22 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r48646:f908d360e53c
Date: 2011-11-01 12:06 +0100
http://bitbucket.org/pypy/pypy/changeset/f908d360e53c/

Log:	Also use the same jitdriver for list(generator).

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -781,7 +781,9 @@
             # xxx special hack for speed
             from pypy.interpreter.generator import GeneratorIterator
             if isinstance(w_iterator, GeneratorIterator):
-                return w_iterator.unpackiterable()
+                lst_w = []
+                w_iterator.unpack_into(lst_w)
+                return lst_w
             # /xxx
             return self._unpackiterable_unknown_length(w_iterator, w_iterable)
         else:
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -156,7 +156,7 @@
                     break
                 block = block.previous
 
-    def unpackiterable(self):
+    def unpack_into(self, results_w):
         """This is a hack for performance: runs the generator and collects
         all produced items in a list."""
         # XXX copied and simplified version of send_ex()
@@ -164,10 +164,9 @@
         if self.running:
             raise OperationError(space.w_ValueError,
                                  space.wrap('generator already executing'))
-        results_w = []
         frame = self.frame
         if frame is None:    # already finished
-            return results_w
+            return
         self.running = True
         try:
             while True:
@@ -182,7 +181,6 @@
             frame.f_backref = jit.vref_None
             self.running = False
             self.frame = None
-        return results_w
 
 jitdriver = jit.JitDriver(greens=['self.pycode'],
                           reds=['self', 'frame', 'results_w'])
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
@@ -54,7 +54,12 @@
 
 def _init_from_iterable(space, items_w, w_iterable):
     # in its own function to make the JIT look into init__List
-    # XXX this would need a JIT driver somehow?
+    # xxx special hack for speed
+    from pypy.interpreter.generator import GeneratorIterator
+    if isinstance(w_iterable, GeneratorIterator):
+        w_iterable.unpack_into(items_w)
+        return
+    # /xxx
     w_iterator = space.iter(w_iterable)
     while True:
         try:
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
@@ -801,6 +801,20 @@
         l.__delslice__(0, 2)
         assert l == [3, 4]
 
+    def test_list_from_set(self):
+        l = ['a']
+        l.__init__(set('b'))
+        assert l == ['b']
+
+    def test_list_from_generator(self):
+        l = ['a']
+        g = (i*i for i in range(5))
+        l.__init__(g)
+        assert l == [0, 1, 4, 9, 16]
+        l.__init__(g)
+        assert l == []
+        assert list(g) == []
+
 
 class AppTestListFastSubscr:
 


More information about the pypy-commit mailing list