Author: Philip Jenvey <[email protected]>
Branch: length-hint
Changeset: r57334:052294c6b2a2
Date: 2012-09-13 14:02 -0700
http://bitbucket.org/pypy/pypy/changeset/052294c6b2a2/

Log:    add an unpackiterable_into that uses resizelist_hint, make an
        attempt of integrating length_hint into list.extend

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -7,8 +7,8 @@
 from pypy.interpreter.miscutils import ThreadLocals
 from pypy.tool.cache import Cache
 from pypy.tool.uid import HUGEVAL_BYTES
-from pypy.rlib.objectmodel import we_are_translated, newlist_hint,\
-     compute_unique_id
+from pypy.rlib.objectmodel import (compute_unique_id, resizelist_hint,
+                                   we_are_translated)
 from pypy.rlib.debug import make_sure_not_resized
 from pypy.rlib.timer import DummyTimer, Timer
 from pypy.rlib.rarithmetic import r_uint
@@ -837,34 +837,45 @@
         """Unpack an iterable into a real (interpreter-level) list.
 
         Raise an OperationError(w_ValueError) if the length is wrong."""
+        if expected_length == -1:
+            lst_w = []
+            self.unpackiterable_into(w_iterable, lst_w)
+            return lst_w
+
+        lst_w = self._unpackiterable_known_length(self.iter(w_iterable),
+                                                  expected_length)
+        return lst_w[:]     # make the resulting list resizable
+
+    def unpackiterable_into(self, w_iterable, lst_w):
+        """Unpack an iterable into a pre-existing real
+        (interpreter-level) list.
+        """
         w_iterator = self.iter(w_iterable)
-        if expected_length == -1:
-            # xxx special hack for speed
-            from pypy.interpreter.generator import GeneratorIterator
-            if isinstance(w_iterator, GeneratorIterator):
-                lst_w = []
-                w_iterator.unpack_into(lst_w)
-                return lst_w
-            # /xxx
-            return self._unpackiterable_unknown_length(w_iterator, w_iterable)
-        else:
-            lst_w = self._unpackiterable_known_length(w_iterator,
-                                                      expected_length)
-            return lst_w[:]     # make the resulting list resizable
+        # xxx special hack for speed
+        from pypy.interpreter.generator import GeneratorIterator
+        if isinstance(w_iterator, GeneratorIterator):
+            # XXX: hint?
+            w_iterator.unpack_into(lst_w)
+            return
+        # /xxx
+        self._unpackiterable_into_unknown_length(w_iterator, w_iterable,
+                                                 lst_w)
 
     def iteriterable(self, w_iterable):
         return W_InterpIterable(self, w_iterable)
 
-    def _unpackiterable_unknown_length(self, w_iterator, w_iterable):
+    def _unpackiterable_into_unknown_length(self, w_iterator, w_iterable, 
items):
         """Unpack an iterable of unknown length into an interp-level
         list.
         """
         # If we can guess the expected length we can preallocate.
         from pypy.objspace.std.iterobject import length_hint
+        newlen = len(items) + length_hint(self, w_iterable, 0)
+        #newlen = len(items) + self.length_hint(w_iterable, 0)
         try:
-            items = newlist_hint(length_hint(self, w_iterable, 0))
+            resizelist_hint(items, newlen)
         except MemoryError:
-            items = [] # it might have lied
+            pass # it might have lied
 
         tp = self.type(w_iterator)
         while True:
@@ -879,6 +890,7 @@
                 break  # done
             items.append(w_item)
         #
+        # XXX: resizelist_hint again if necessary
         return items
 
     @jit.dont_look_inside
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
@@ -459,8 +459,13 @@
         assert index == 0
         self.append(w_list, w_item)
 
-    def extend(self, w_list, w_other):
-        w_other.copy_into(w_list)
+    def extend(self, w_list, w_any):
+        if isinstance(w_any, W_ListObject):
+            w_any.copy_into(w_list)
+            return
+
+        w_other = W_ListObject(self.space, self.space.listview(w_any))
+        self.extend(w_list, w_other)
 
     def reverse(self, w_list):
         pass
@@ -791,7 +796,22 @@
         w_list.switch_to_object_strategy()
         w_list.insert(index, w_item)
 
-    def extend(self, w_list, w_other):
+    def extend(self, w_list, w_any):
+        if isinstance(w_any, W_ListObject):
+            self.extend_list(w_list, w_any)
+            return
+
+        if self is not self.space.fromcache(ObjectListStrategy):
+            # XXX: force ObjectListStrategy for now
+            w_list.switch_to_object_strategy()
+            w_list.extend(w_any)
+            return
+
+        # XXX:
+        l = self.unerase(w_list.lstorage)
+        self.space.unpackiterable_into(w_any, l)
+
+    def extend_list(self, w_list, w_other):
         l = self.unerase(w_list.lstorage)
         if self.list_is_correct_type(w_other):
             l += self.unerase(w_other.lstorage)
@@ -1068,6 +1088,8 @@
     w_iterable, = __args__.parse_obj(
             None, 'list', init_signature, init_defaults)
     w_list.clear(space)
+    # XXX: move all this into 'extend', then ideally this simply calls
+    # extend
     if w_iterable is not None:
         if type(w_iterable) is W_ListObject:
             w_iterable.copy_into(w_list)
@@ -1177,10 +1199,6 @@
         raise
     return w_list1
 
-def inplace_add__List_List(space, w_list1, w_list2):
-    list_extend__List_List(space, w_list1, w_list2)
-    return w_list1
-
 def mul_list_times(space, w_list, w_times):
     try:
         times = space.getindex_w(w_times, space.w_OverflowError)
@@ -1329,12 +1347,7 @@
     w_list.append(w_any)
     return space.w_None
 
-def list_extend__List_List(space, w_list, w_other):
-    w_list.extend(w_other)
-    return space.w_None
-
-def list_extend__List_ANY(space, w_list, w_any):
-    w_other = W_ListObject(space, space.listview(w_any))
+def list_extend__List_ANY(space, w_list, w_other):
     w_list.extend(w_other)
     return space.w_None
 
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to