Author: Manuel Jacob Branch: remove-tuple-smm Changeset: r64379:8d7578543296 Date: 2013-05-21 14:32 +0200 http://bitbucket.org/pypy/pypy/changeset/8d7578543296/
Log: Kill all tuple SMMs. diff --git a/pypy/objspace/std/tupleobject.py b/pypy/objspace/std/tupleobject.py --- a/pypy/objspace/std/tupleobject.py +++ b/pypy/objspace/std/tupleobject.py @@ -1,3 +1,4 @@ +import sys from pypy.interpreter.error import OperationError from pypy.objspace.std.model import registerimplementation, W_Object from pypy.objspace.std.register_all import register_all @@ -6,9 +7,12 @@ from rpython.rlib.rarithmetic import intmask from pypy.objspace.std.sliceobject import W_SliceObject, normalize_simple_slice from pypy.objspace.std import slicetype +from pypy.objspace.std.util import negate +from pypy.objspace.std.stdtypedef import StdTypeDef from rpython.rlib.debug import make_sure_not_resized from rpython.rlib import jit from rpython.tool.sourcetools import func_with_new_name +from pypy.interpreter import gateway UNROLL_CUTOFF = 10 @@ -24,8 +28,12 @@ raise NotImplementedError +def tuple_unroll_condition(space, self, w_other): + return jit.loop_unrolling_heuristic(self, len(self.wrappeditems), UNROLL_CUTOFF) or \ + jit.loop_unrolling_heuristic(w_other, len(w_other.wrappeditems), UNROLL_CUTOFF) + + class W_TupleObject(W_AbstractTupleObject): - from pypy.objspace.std.tupletype import tuple_typedef as typedef _immutable_fields_ = ['wrappeditems[*]'] def __init__(w_self, wrappeditems): @@ -47,132 +55,202 @@ def getitems_copy(self): return self.wrappeditems[:] # returns a resizable list + @staticmethod + def descr_new(space, w_tupletype, w_sequence=None): + from pypy.objspace.std.tupleobject import W_TupleObject + if w_sequence is None: + tuple_w = [] + elif (space.is_w(w_tupletype, space.w_tuple) and + space.is_w(space.type(w_sequence), space.w_tuple)): + return w_sequence + else: + tuple_w = space.fixedview(w_sequence) + w_obj = space.allocate_instance(W_TupleObject, w_tupletype) + W_TupleObject.__init__(w_obj, tuple_w) + return w_obj + + def descr_repr(self, space): + items = self.wrappeditems + # XXX this is quite innefficient, still better than calling + # it via applevel + if len(items) == 1: + return space.wrap("(" + space.str_w(space.repr(items[0])) + ",)") + return space.wrap("(" + + (", ".join([space.str_w(space.repr(item)) for item in items])) + + ")") + + def descr_hash(self, space): + return space.wrap(hash_tuple(space, self.wrappeditems)) + + @jit.look_inside_iff(tuple_unroll_condition) + def descr_eq(self, space, w_other): + if not isinstance(w_other, W_TupleObject): + return space.w_NotImplemented + items1 = self.wrappeditems + items2 = w_other.wrappeditems + lgt1 = len(items1) + lgt2 = len(items2) + if lgt1 != lgt2: + return space.w_False + for i in range(lgt1): + item1 = items1[i] + item2 = items2[i] + if not space.eq_w(item1, item2): + return space.w_False + return space.w_True + + descr_ne = negate(descr_eq) + + def _make_tuple_comparison(name): + import operator + op = getattr(operator, name) + + @jit.look_inside_iff(tuple_unroll_condition) + def compare_tuples(self, space, w_other): + if not isinstance(w_other, W_TupleObject): + return space.w_NotImplemented + items1 = self.wrappeditems + items2 = w_other.wrappeditems + ncmp = min(len(items1), len(items2)) + # Search for the first index where items are different + for p in range(ncmp): + if not space.eq_w(items1[p], items2[p]): + return getattr(space, name)(items1[p], items2[p]) + # No more items to compare -- compare sizes + return space.newbool(op(len(items1), len(items2))) + return func_with_new_name(compare_tuples, name + '__Tuple_Tuple') + + descr_lt = _make_tuple_comparison('lt') + descr_le = _make_tuple_comparison('le') + descr_gt = _make_tuple_comparison('gt') + descr_ge = _make_tuple_comparison('ge') + + def descr_len(self, space): + result = len(self.wrappeditems) + return wrapint(space, result) + + def descr_iter(self, space): + from pypy.objspace.std import iterobject + return iterobject.W_FastTupleIterObject(self, self.wrappeditems) + + @jit.look_inside_iff(lambda self, space, w_obj: + jit.loop_unrolling_heuristic(self, len(self.wrappeditems), UNROLL_CUTOFF)) + def descr_contains(self, space, w_obj): + for w_item in self.wrappeditems: + if space.eq_w(w_item, w_obj): + return space.w_True + return space.w_False + + def descr_add(self, space, w_other): + if not isinstance(w_other, W_TupleObject): + return space.w_NotImplemented + items1 = self.wrappeditems + items2 = w_other.wrappeditems + return space.newtuple(items1 + items2) + + def descr_mul(self, space, w_times): + try: + times = space.getindex_w(w_times, space.w_OverflowError) + except OperationError, e: + if e.match(space, space.w_TypeError): + raise FailedToImplement + raise + if times == 1 and space.type(self) == space.w_tuple: + return self + items = self.wrappeditems + return space.newtuple(items * times) + + def descr_getitem(self, space, w_index): + if isinstance(w_index, W_SliceObject): + items = self.wrappeditems + length = len(items) + start, stop, step, slicelength = w_index.indices4(space, length) + assert slicelength >= 0 + subitems = [None] * slicelength + for i in range(slicelength): + subitems[i] = items[start] + start += step + return space.newtuple(subitems) + + # getindex_w should get a second argument space.w_IndexError, + # but that doesn't exist the first time this is called. + try: + w_IndexError = space.w_IndexError + except AttributeError: + w_IndexError = None + index = space.getindex_w(w_index, w_IndexError, "tuple index") + try: + return self.wrappeditems[index] + except IndexError: + raise OperationError(space.w_IndexError, + space.wrap("tuple index out of range")) + + def descr_getslice(self, space, w_start, w_stop): + length = len(self.wrappeditems) + start, stop = normalize_simple_slice(space, length, w_start, w_stop) + return space.newtuple(self.wrappeditems[start:stop]) + + def descr_getnewargs(self, space): + return space.newtuple([space.newtuple(self.wrappeditems)]) + + def descr_count(self, space, w_obj): + """count(obj) -> number of times obj appears in the tuple""" + count = 0 + for w_item in self.wrappeditems: + if space.eq_w(w_item, w_obj): + count += 1 + return space.wrap(count) + + @gateway.unwrap_spec(w_start=gateway.WrappedDefault(0), + w_stop=gateway.WrappedDefault(sys.maxint)) + def descr_index(self, space, w_obj, w_start, w_stop): + """index(obj, [start, [stop]]) -> first index that obj appears in the + tuple + """ + length = len(self.wrappeditems) + start, stop = slicetype.unwrap_start_stop(space, length, w_start, w_stop) + for i in range(start, min(stop, length)): + w_item = self.wrappeditems[i] + if space.eq_w(w_item, w_obj): + return space.wrap(i) + raise OperationError(space.w_ValueError, + space.wrap("tuple.index(x): x not in tuple")) + +W_TupleObject.typedef = StdTypeDef("tuple", + __doc__ = '''tuple() -> an empty tuple +tuple(sequence) -> tuple initialized from sequence's items + +If the argument is a tuple, the return value is the same object.''', + __new__ = gateway.interp2app(W_TupleObject.descr_new), + __repr__ = gateway.interp2app(W_TupleObject.descr_repr), + __hash__ = gateway.interp2app(W_TupleObject.descr_hash), + + __eq__ = gateway.interp2app(W_TupleObject.descr_eq), + __ne__ = gateway.interp2app(W_TupleObject.descr_ne), + __lt__ = gateway.interp2app(W_TupleObject.descr_lt), + __le__ = gateway.interp2app(W_TupleObject.descr_le), + __gt__ = gateway.interp2app(W_TupleObject.descr_gt), + __ge__ = gateway.interp2app(W_TupleObject.descr_ge), + + __len__ = gateway.interp2app(W_TupleObject.descr_len), + __iter__ = gateway.interp2app(W_TupleObject.descr_iter), + __contains__ = gateway.interp2app(W_TupleObject.descr_contains), + + __add__ = gateway.interp2app(W_TupleObject.descr_add), + __mul__ = gateway.interp2app(W_TupleObject.descr_mul), + __rmul__ = gateway.interp2app(W_TupleObject.descr_mul), + + __getitem__ = gateway.interp2app(W_TupleObject.descr_getitem), + __getslice__ = gateway.interp2app(W_TupleObject.descr_getslice), + + __getnewargs__ = gateway.interp2app(W_TupleObject.descr_getnewargs), + count = gateway.interp2app(W_TupleObject.descr_count), + index = gateway.interp2app(W_TupleObject.descr_index) +) + registerimplementation(W_TupleObject) -def len__Tuple(space, w_tuple): - result = len(w_tuple.wrappeditems) - return wrapint(space, result) - -def getitem__Tuple_ANY(space, w_tuple, w_index): - # getindex_w should get a second argument space.w_IndexError, - # but that doesn't exist the first time this is called. - try: - w_IndexError = space.w_IndexError - except AttributeError: - w_IndexError = None - index = space.getindex_w(w_index, w_IndexError, "tuple index") - try: - return w_tuple.wrappeditems[index] - except IndexError: - raise OperationError(space.w_IndexError, - space.wrap("tuple index out of range")) - -def getitem__Tuple_Slice(space, w_tuple, w_slice): - items = w_tuple.wrappeditems - length = len(items) - start, stop, step, slicelength = w_slice.indices4(space, length) - assert slicelength >= 0 - subitems = [None] * slicelength - for i in range(slicelength): - subitems[i] = items[start] - start += step - return space.newtuple(subitems) - -def getslice__Tuple_ANY_ANY(space, w_tuple, w_start, w_stop): - length = len(w_tuple.wrappeditems) - start, stop = normalize_simple_slice(space, length, w_start, w_stop) - return space.newtuple(w_tuple.wrappeditems[start:stop]) - -@jit.look_inside_iff(lambda space, w_tuple, w_obj: - jit.loop_unrolling_heuristic(w_tuple, len(w_tuple.wrappeditems), UNROLL_CUTOFF)) -def contains__Tuple_ANY(space, w_tuple, w_obj): - for w_item in w_tuple.wrappeditems: - if space.eq_w(w_item, w_obj): - return space.w_True - return space.w_False - -def iter__Tuple(space, w_tuple): - from pypy.objspace.std import iterobject - return iterobject.W_FastTupleIterObject(w_tuple, w_tuple.wrappeditems) - -def add__Tuple_Tuple(space, w_tuple1, w_tuple2): - items1 = w_tuple1.wrappeditems - items2 = w_tuple2.wrappeditems - return space.newtuple(items1 + items2) - -def mul_tuple_times(space, w_tuple, w_times): - try: - times = space.getindex_w(w_times, space.w_OverflowError) - except OperationError, e: - if e.match(space, space.w_TypeError): - raise FailedToImplement - raise - if times == 1 and space.type(w_tuple) == space.w_tuple: - return w_tuple - items = w_tuple.wrappeditems - return space.newtuple(items * times) - -def mul__Tuple_ANY(space, w_tuple, w_times): - return mul_tuple_times(space, w_tuple, w_times) - -def mul__ANY_Tuple(space, w_times, w_tuple): - return mul_tuple_times(space, w_tuple, w_times) - -def tuple_unroll_condition(space, w_tuple1, w_tuple2): - return jit.loop_unrolling_heuristic(w_tuple1, len(w_tuple1.wrappeditems), UNROLL_CUTOFF) or \ - jit.loop_unrolling_heuristic(w_tuple2, len(w_tuple2.wrappeditems), UNROLL_CUTOFF) - -@jit.look_inside_iff(tuple_unroll_condition) -def eq__Tuple_Tuple(space, w_tuple1, w_tuple2): - items1 = w_tuple1.wrappeditems - items2 = w_tuple2.wrappeditems - lgt1 = len(items1) - lgt2 = len(items2) - if lgt1 != lgt2: - return space.w_False - for i in range(lgt1): - item1 = items1[i] - item2 = items2[i] - if not space.eq_w(item1, item2): - return space.w_False - return space.w_True - -def _make_tuple_comparison(name): - import operator - op = getattr(operator, name) - - @jit.look_inside_iff(tuple_unroll_condition) - def compare_tuples(space, w_tuple1, w_tuple2): - items1 = w_tuple1.wrappeditems - items2 = w_tuple2.wrappeditems - ncmp = min(len(items1), len(items2)) - # Search for the first index where items are different - for p in range(ncmp): - if not space.eq_w(items1[p], items2[p]): - return getattr(space, name)(items1[p], items2[p]) - # No more items to compare -- compare sizes - return space.newbool(op(len(items1), len(items2))) - return func_with_new_name(compare_tuples, name + '__Tuple_Tuple') - -lt__Tuple_Tuple = _make_tuple_comparison('lt') -le__Tuple_Tuple = _make_tuple_comparison('le') -gt__Tuple_Tuple = _make_tuple_comparison('gt') -ge__Tuple_Tuple = _make_tuple_comparison('ge') - -def repr__Tuple(space, w_tuple): - items = w_tuple.wrappeditems - # XXX this is quite innefficient, still better than calling - # it via applevel - if len(items) == 1: - return space.wrap("(" + space.str_w(space.repr(items[0])) + ",)") - return space.wrap("(" + - (", ".join([space.str_w(space.repr(item)) for item in items])) - + ")") - -def hash__Tuple(space, w_tuple): - return space.wrap(hash_tuple(space, w_tuple.wrappeditems)) - @jit.look_inside_iff(lambda space, wrappeditems: jit.loop_unrolling_heuristic(wrappeditems, len(wrappeditems), UNROLL_CUTOFF)) def hash_tuple(space, wrappeditems): @@ -188,25 +266,5 @@ x += 97531 return intmask(x) -def getnewargs__Tuple(space, w_tuple): - return space.newtuple([space.newtuple(w_tuple.wrappeditems)]) - -def tuple_count__Tuple_ANY(space, w_tuple, w_obj): - count = 0 - for w_item in w_tuple.wrappeditems: - if space.eq_w(w_item, w_obj): - count += 1 - return space.wrap(count) - -def tuple_index__Tuple_ANY_ANY_ANY(space, w_tuple, w_obj, w_start, w_stop): - length = len(w_tuple.wrappeditems) - start, stop = slicetype.unwrap_start_stop(space, length, w_start, w_stop) - for i in range(start, min(stop, length)): - w_item = w_tuple.wrappeditems[i] - if space.eq_w(w_item, w_obj): - return space.wrap(i) - raise OperationError(space.w_ValueError, - space.wrap("tuple.index(x): x not in tuple")) - from pypy.objspace.std import tupletype -register_all(vars(), tupletype) +tupletype.tuple_typedef = W_TupleObject.typedef diff --git a/pypy/objspace/std/tupletype.py b/pypy/objspace/std/tupletype.py --- a/pypy/objspace/std/tupletype.py +++ b/pypy/objspace/std/tupletype.py @@ -1,7 +1,4 @@ -import sys -from pypy.interpreter import gateway from pypy.objspace.std.register_all import register_all -from pypy.objspace.std.stdtypedef import StdTypeDef, SMM def wraptuple(space, list_w): from pypy.objspace.std.tupleobject import W_TupleObject @@ -37,34 +34,3 @@ return W_SmallTupleObject8(list_w) return W_TupleObject(list_w) -tuple_count = SMM("count", 2, - doc="count(obj) -> number of times obj appears in the tuple") - -tuple_index = SMM("index", 4, defaults=(0, sys.maxint), - doc="index(obj, [start, [stop]]) -> first index that obj " - "appears in the tuple") - - -def descr__new__(space, w_tupletype, w_sequence=None): - from pypy.objspace.std.tupleobject import W_TupleObject - if w_sequence is None: - tuple_w = [] - elif (space.is_w(w_tupletype, space.w_tuple) and - space.is_w(space.type(w_sequence), space.w_tuple)): - return w_sequence - else: - tuple_w = space.fixedview(w_sequence) - w_obj = space.allocate_instance(W_TupleObject, w_tupletype) - W_TupleObject.__init__(w_obj, tuple_w) - return w_obj - -# ____________________________________________________________ - -tuple_typedef = StdTypeDef("tuple", - __doc__ = '''tuple() -> an empty tuple -tuple(sequence) -> tuple initialized from sequence's items - -If the argument is a tuple, the return value is the same object.''', - __new__ = gateway.interp2app(descr__new__), - ) -tuple_typedef.registermethods(globals()) _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit