Author: Armin Rigo <[email protected]>
Branch:
Changeset: r48641:33adaaf2cc05
Date: 2011-11-01 11:08 +0100
http://bitbucket.org/pypy/pypy/changeset/33adaaf2cc05/
Log: Expand the code of unpackiterable() into several versions instead of
keeping a single does-it-all version.
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -777,22 +777,55 @@
"""Unpack an iterable object into a real (interpreter-level) list.
Raise an OperationError(w_ValueError) if the length is wrong."""
w_iterator = self.iter(w_iterable)
- # If we know the expected length we can preallocate.
if expected_length == -1:
+ return self._unpackiterable_unknown_length(w_iterator, w_iterable)
+ else:
+ return self._unpackiterable_known_length(w_iterator,
+ expected_length)
+
+ @jit.dont_look_inside
+ def _unpackiterable_unknown_length(self, w_iterator, w_iterable):
+ # Unpack a variable-size list of unknown length.
+ # The JIT does not look inside this function because it
+ # contains a loop (made explicit with the decorator above).
+ #
+ # If we can guess the expected length we can preallocate.
+ try:
+ lgt_estimate = self.len_w(w_iterable)
+ except OperationError, o:
+ if (not o.match(self, self.w_AttributeError) and
+ not o.match(self, self.w_TypeError)):
+ raise
+ items = []
+ else:
try:
- lgt_estimate = self.len_w(w_iterable)
- except OperationError, o:
- if (not o.match(self, self.w_AttributeError) and
- not o.match(self, self.w_TypeError)):
+ items = newlist(lgt_estimate)
+ except MemoryError:
+ items = [] # it might have lied
+ #
+ while True:
+ try:
+ w_item = self.next(w_iterator)
+ except OperationError, e:
+ if not e.match(self, self.w_StopIteration):
raise
- items = []
- else:
- try:
- items = newlist(lgt_estimate)
- except MemoryError:
- items = [] # it might have lied
- else:
- items = [None] * expected_length
+ break # done
+ items.append(w_item)
+ #
+ return items
+
+ @jit.dont_look_inside
+ def _unpackiterable_known_length(self, w_iterator, expected_length):
+ # Unpack a known length list, without letting the JIT look inside.
+ # Implemented by just calling the @jit.unroll_safe version, but
+ # the JIT stopped looking inside already.
+ return self._unpackiterable_known_length_jitlook(w_iterator,
+ expected_length)
+
+ @jit.unroll_safe
+ def _unpackiterable_known_length_jitlook(self, w_iterator,
+ expected_length):
+ items = [None] * expected_length
idx = 0
while True:
try:
@@ -801,26 +834,29 @@
if not e.match(self, self.w_StopIteration):
raise
break # done
- if expected_length != -1 and idx == expected_length:
+ if idx == expected_length:
raise OperationError(self.w_ValueError,
- self.wrap("too many values to unpack"))
- if expected_length == -1:
- items.append(w_item)
- else:
- items[idx] = w_item
+ self.wrap("too many values to unpack"))
+ items[idx] = w_item
idx += 1
- if expected_length != -1 and idx < expected_length:
+ if idx < expected_length:
if idx == 1:
plural = ""
else:
plural = "s"
- raise OperationError(self.w_ValueError,
- self.wrap("need more than %d value%s to unpack" %
- (idx, plural)))
+ raise operationerrfmt(self.w_ValueError,
+ "need more than %d value%s to unpack",
+ idx, plural)
return items
- unpackiterable_unroll = jit.unroll_safe(func_with_new_name(unpackiterable,
- 'unpackiterable_unroll'))
+ def unpackiterable_unroll(self, w_iterable, expected_length):
+ # Like unpackiterable(), but for the cases where we have
+ # an expected_length and want to unroll when JITted.
+ # Returns a fixed-size list.
+ w_iterator = self.iter(w_iterable)
+ assert expected_length != -1
+ return self._unpackiterable_known_length_jitlook(w_iterator,
+ expected_length)
def fixedview(self, w_iterable, expected_length=-1):
""" A fixed list view of w_iterable. Don't modify the result
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
@@ -414,7 +414,7 @@
else:
if unroll:
return make_sure_not_resized(ObjSpace.unpackiterable_unroll(
- self, w_obj, expected_length)[:])
+ self, w_obj, expected_length))
else:
return make_sure_not_resized(ObjSpace.unpackiterable(
self, w_obj, expected_length)[:])
@@ -422,7 +422,8 @@
raise self._wrap_expected_length(expected_length, len(t))
return make_sure_not_resized(t)
- def fixedview_unroll(self, w_obj, expected_length=-1):
+ def fixedview_unroll(self, w_obj, expected_length):
+ assert expected_length >= 0
return self.fixedview(w_obj, expected_length, unroll=True)
def listview(self, w_obj, expected_length=-1):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit