Author: Brian Kearns <bdkea...@gmail.com> Branch: Changeset: r61405:ab0486abc9f6 Date: 2013-02-18 09:06 -0500 http://bitbucket.org/pypy/pypy/changeset/ab0486abc9f6/
Log: significantly speed up min/max in the non-unrolled case diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py --- a/pypy/module/__builtin__/functional.py +++ b/pypy/module/__builtin__/functional.py @@ -133,56 +133,76 @@ v = v.add(step) return space.newlist(res_w) +min_jitdriver = jit.JitDriver(name='min', + greens=['w_type'], reds='auto') +max_jitdriver = jit.JitDriver(name='max', + greens=['w_type'], reds='auto') + +def make_min_max(unroll): + @specialize.arg(2) + def min_max_impl(space, args, implementation_of): + if implementation_of == "max": + compare = space.gt + jitdriver = max_jitdriver + else: + compare = space.lt + jitdriver = min_jitdriver + args_w = args.arguments_w + if len(args_w) > 1: + w_sequence = space.newtuple(args_w) + elif len(args_w): + w_sequence = args_w[0] + else: + msg = "%s() expects at least one argument" % (implementation_of,) + raise OperationError(space.w_TypeError, space.wrap(msg)) + w_key = None + kwds = args.keywords + if kwds: + if kwds[0] == "key" and len(kwds) == 1: + w_key = args.keywords_w[0] + else: + msg = "%s() got unexpected keyword argument" % (implementation_of,) + raise OperationError(space.w_TypeError, space.wrap(msg)) + + w_iter = space.iter(w_sequence) + w_type = space.type(w_iter) + w_max_item = None + w_max_val = None + while True: + if not unroll: + jitdriver.jit_merge_point(w_type=w_type) + try: + w_item = space.next(w_iter) + except OperationError, e: + if not e.match(space, space.w_StopIteration): + raise + break + if w_key is not None: + w_compare_with = space.call_function(w_key, w_item) + else: + w_compare_with = w_item + if w_max_item is None or \ + space.is_true(compare(w_compare_with, w_max_val)): + w_max_item = w_item + w_max_val = w_compare_with + if w_max_item is None: + msg = "arg is an empty sequence" + raise OperationError(space.w_ValueError, space.wrap(msg)) + return w_max_item + if unroll: + min_max_impl = jit.unroll_safe(min_max_impl) + return min_max_impl + +min_max_unroll = make_min_max(True) +min_max_normal = make_min_max(False) @specialize.arg(2) -@jit.look_inside_iff(lambda space, args, implementation_of: - jit.isconstant(len(args.arguments_w)) and - len(args.arguments_w) == 2 -) def min_max(space, args, implementation_of): - if implementation_of == "max": - compare = space.gt + if not jit.we_are_jitted() or (jit.isconstant(len(args.arguments_w)) and + len(args.arguments_w) == 2): + return min_max_unroll(space, args, implementation_of) else: - compare = space.lt - args_w = args.arguments_w - if len(args_w) > 1: - w_sequence = space.newtuple(args_w) - elif len(args_w): - w_sequence = args_w[0] - else: - msg = "%s() expects at least one argument" % (implementation_of,) - raise OperationError(space.w_TypeError, space.wrap(msg)) - w_key = None - kwds = args.keywords - if kwds: - if kwds[0] == "key" and len(kwds) == 1: - w_key = args.keywords_w[0] - else: - msg = "%s() got unexpected keyword argument" % (implementation_of,) - raise OperationError(space.w_TypeError, space.wrap(msg)) - - w_iter = space.iter(w_sequence) - w_max_item = None - w_max_val = None - while True: - try: - w_item = space.next(w_iter) - except OperationError, e: - if not e.match(space, space.w_StopIteration): - raise - break - if w_key is not None: - w_compare_with = space.call_function(w_key, w_item) - else: - w_compare_with = w_item - if w_max_item is None or \ - space.is_true(compare(w_compare_with, w_max_val)): - w_max_item = w_item - w_max_val = w_compare_with - if w_max_item is None: - msg = "arg is an empty sequence" - raise OperationError(space.w_ValueError, space.wrap(msg)) - return w_max_item + return min_max_normal(space, args, implementation_of) def max(space, __args__): """max(iterable[, key=func]) -> value _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit