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