Author: mattip <[email protected]> Branch: release-5.x Changeset: r82827:a4efe1285120 Date: 2016-03-06 21:43 +0200 http://bitbucket.org/pypy/pypy/changeset/a4efe1285120/
Log: merge default into release diff --git a/pypy/doc/release-5.0.0.rst b/pypy/doc/release-5.0.0.rst --- a/pypy/doc/release-5.0.0.rst +++ b/pypy/doc/release-5.0.0.rst @@ -3,8 +3,20 @@ ========== We have released PyPy 5.0.0, about three months after PyPy 4.0.0. -We encourage all users of PyPy to update to this version. There are -bug fixes and a major upgrade to our c-api layer (cpyext) +We encourage all users of PyPy to update to this version. Apart from the usual +bug fixes, there is an ongoing effort to improve the warmup time and memory +usage of JIT-related metadata. The exact effects depend vastly on the program +you're running and can range from insignificant to warmup being up to 30% +faster and memory dropping by about 30%. + +We also merged a major upgrade to our C-API layer (cpyext), simplifying the +interaction between c-level objects and PyPy interpreter level objects. As a +result, lxml with its cython compiled component `passes all tests`_ on PyPy + +Users who have gotten used to vmprof_ on Linux, and those on other platforms +who have not yet tried its awesomeness, will be happy to hear that vmprof +now just works on MacOS and Windows too, in both PyPy (built-in support) and +CPython (as an installed module). You can download the PyPy 5.0.0 release here: @@ -33,6 +45,8 @@ .. _`modules`: http://doc.pypy.org/en/latest/project-ideas.html#make-more-python-modules-pypy-friendly .. _`help`: http://doc.pypy.org/en/latest/project-ideas.html .. _`numpy`: https://bitbucket.org/pypy/numpy +.. _`passes all tests`: https://bitbucket.org/pypy/compatibility/wiki/lxml +.. _vmprof: http://vmprof.readthedocs.org What is PyPy? ============= @@ -53,44 +67,156 @@ .. _`dynamic languages`: http://pypyjs.org Other Highlights (since 4.0.1 released in November 2015) -======================================================= +========================================================= + +* New features: + + * Support embedding PyPy in a C-program via cffi and static callbacks in cffi. + This deprecates the old method of embedding PyPy + + * Refactor vmprof to work cross-operating-system, deprecate using buggy + libunwind on Linux platforms. Vmprof even works on Windows now. + + * Support more of the C-API type slots, like tp_getattro, and fix C-API + macros, functions, and structs such as _PyLong_FromByteArray(), + PyString_GET_SIZE, f_locals in PyFrameObject, Py_NAN, co_filename in + PyCodeObject + + * Use a more stable approach for allocating PyObjects in cpyext. (see + `blog post`_). Once the PyObject corresponding to a PyPy object is created, + it stays around at the same location until the death of the PyPy object. + Done with a little bit of custom GC support. It allows us to kill the + notion of "borrowing" inside cpyext, reduces 4 dictionaries down to 1, and + significantly simplifies the whole approach (which is why it is a new + feature while technically a refactoring) and allows PyPy to support the + populart lxml module (as of the *next* release) with no PyPy specific + patches needed + + * Make the default filesystem encoding ASCII, like CPython + + * Use `hypothesis`_ in test creation, which is great for randomizing tests * Bug Fixes - * + * Backport always using os.urandom for uuid4 from cpython and fix the JIT as well + (issue #2202) - * + * More completely support datetime, optimize timedelta creation - * + * Fix for issue 2185 which caused an inconsistent list of operations to be + generated by the unroller, appeared in a complicated DJango app + + * Fix an elusive issue with stacklets on shadowstack which showed up when + forgetting stacklets without resuming them + + * Fix entrypoint() which now acquires the GIL + + * Fix direct_ffi_call() so failure does not bail out before setting CALL_MAY_FORCE + + * Fix (de)pickling long values by simplifying the implementation + + * Fix RPython rthread so that objects stored as threadlocal do not force minor + GC collection and are kept alive automatically. This improves perfomance of + short-running Python callbacks and prevents resetting such object between + calls + + * Support floats as parameters to itertools.isslice() + + * Check for the existence of CODESET, ignoring it should have prevented PyPy + from working on FreeBSD + + * Fix for corner case (likely shown by Krakatau) for consecutive guards with + interdependencies + + * Fix applevel bare class method comparisons which should fix pretty printing + in IPython * Issues reported with our previous release were resolved_ after reports from users on our issue tracker at https://bitbucket.org/pypy/pypy/issues or on IRC at #pypy -* New features: - - * - - * - - * - * Numpy: - * + * Updates to numpy 1.10.2 (incompatibilities and not-implemented features + still exist) - * + * Support dtype=(('O', spec)) union while disallowing record arrays with + mixed object, non-object values + * Remove all traces of micronumpy from cpyext if --withoutmod-micronumpy option used + + * Support indexing filtering with a boolean ndarray + + * Support partition() as an app-level function, together with a cffi wrapper + in pypy/numpy, this now provides partial support for partition() * Performance improvements and refactorings: - * + * Refactor and improve exception analysis in the annotator - * + * Remove unnecessary special handling of space.wrap(). - * + * Improve the memory signature of numbering instances in the JIT. This should + massively decrease the amount of memory consumed by the JIT, which is + significant for most programs. Also compress the numberings using variable- + size encoding + + * Support list-resizing setslice operations in RPython + + * Tweak the trace-too-long heuristic for multiple jit drivers + + * Refactor bookkeeping (such a cool word - three double letters) in the + annotater + + * Refactor wrappers for OS functions from rtyper to rlib and simplify them + + * Simplify backend loading instructions to only use four variants + + * Optimize string concatination + + * Simplify GIL handling in non-jitted code + + * Use INT_LSHIFT instead of INT_MUL when possible + + * Improve struct.unpack by casting directly from the underlying buffer. + Unpacking floats and doubles is about 15 times faster, and integer types + about 50% faster (on 64 bit integers). This was then subsequently + improved further in optimizeopt.py. + + * Refactor naming in optimizeopt + + * Change GraphAnalyzer to use a more precise way to recognize external + functions and fix null pointer handling, generally clean up external + function handling + + * Optimize global lookups + + * Optimize two-tuple lookups in mapdict + + * Remove pure variants of ``getfield_gc_*`` operations from the JIT by + determining purity while tracing + + * Refactor databasing + + * Simplify bootstrapping in cpyext + + * Refactor rtyper debug code into python.rtyper.debug + + * Seperate structmember.h from Python.h Also enhance creating api functions + to specify which header file they appear in (previously only pypy_decl.h) + + * Reduce all guards from int_floordiv_ovf if one of the arguments is constant + + * Fix tokenizer to enforce universal newlines, needed for Python 3 support + + * Identify permutations of attributes at instance creation, reducing the + number of bridges created + + * Greatly improve re.sub() performance .. _resolved: http://doc.pypy.org/en/latest/whatsnew-5.0.0.html +.. _`hypothesis`: http://hypothesis.readthedocs.org +.. _`blog post`: http://morepypy.blogspot.com/2016/02/c-api-support-update.html Please update, and continue to help us make PyPy better. diff --git a/pypy/doc/whatsnew-5.0.0.rst b/pypy/doc/whatsnew-5.0.0.rst --- a/pypy/doc/whatsnew-5.0.0.rst +++ b/pypy/doc/whatsnew-5.0.0.rst @@ -191,3 +191,7 @@ Fix boolean-array indexing in micronumpy +.. branch: numpy_partition +Support ndarray.partition() as an app-level function numpy.core._partition_use, +provided as a cffi wrapper to upstream's implementation in the pypy/numpy repo + diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -3,6 +3,5 @@ ========================= .. this is a revision shortly after release-5.0.0 -.. startrev: 6d13e55b962a +.. startrev: 7bb6381d084c - diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py --- a/pypy/interpreter/function.py +++ b/pypy/interpreter/function.py @@ -13,6 +13,9 @@ from pypy.interpreter.argument import Arguments from rpython.rlib import jit +from rpython.rlib.rarithmetic import LONG_BIT +from rpython.rlib.rbigint import rbigint + funccallunrolling = unrolling_iterable(range(4)) @@ -557,6 +560,26 @@ return space.w_False return space.eq(self.w_function, w_other.w_function) + def is_w(self, space, other): + if not isinstance(other, Method): + return False + return (self.w_instance is other.w_instance and + self.w_function is other.w_function and + self.w_class is other.w_class) + + def immutable_unique_id(self, space): + from pypy.objspace.std.util import IDTAG_METHOD as tag + from pypy.objspace.std.util import IDTAG_SHIFT + if self.w_instance is not None: + id = space.bigint_w(space.id(self.w_instance)) + id = id.lshift(LONG_BIT) + else: + id = rbigint.fromint(0) + id = id.or_(space.bigint_w(space.id(self.w_function))) + id = id.lshift(LONG_BIT).or_(space.bigint_w(space.id(self.w_class))) + id = id.lshift(IDTAG_SHIFT).int_or_(tag) + return space.newlong_from_rbigint(id) + def descr_method_hash(self): space = self.space w_result = space.hash(self.w_function) diff --git a/pypy/interpreter/test/test_function.py b/pypy/interpreter/test/test_function.py --- a/pypy/interpreter/test/test_function.py +++ b/pypy/interpreter/test/test_function.py @@ -1,5 +1,4 @@ - -import unittest +import pytest from pypy.interpreter import eval from pypy.interpreter.function import Function, Method, descr_function_get from pypy.interpreter.pycode import PyCode @@ -187,6 +186,7 @@ raises( TypeError, func, 42, {'arg1': 23}) + @pytest.mark.skipif("config.option.runappdirect") def test_kwargs_nondict_mapping(self): class Mapping: def keys(self): @@ -257,6 +257,14 @@ meth = func.__get__(obj, object) assert meth() == obj + def test_none_get_interaction(self): + skip("XXX issue #2083") + assert type(None).__repr__(None) == 'None' + + def test_none_get_interaction_2(self): + f = None.__repr__ + assert f() == 'None' + def test_no_get_builtin(self): assert not hasattr(dir, '__get__') class A(object): @@ -284,6 +292,7 @@ raises(TypeError, len, s, some_unknown_keyword=s) raises(TypeError, len, s, s, some_unknown_keyword=s) + @pytest.mark.skipif("config.option.runappdirect") def test_call_error_message(self): try: len() @@ -325,6 +334,7 @@ f = lambda: 42 assert f.func_doc is None + @pytest.mark.skipif("config.option.runappdirect") def test_setstate_called_with_wrong_args(self): f = lambda: 42 # not sure what it should raise, since CPython doesn't have setstate @@ -550,6 +560,37 @@ assert A().m == X() assert X() == A().m + @pytest.mark.skipif("config.option.runappdirect") + def test_method_identity(self): + class A(object): + def m(self): + pass + def n(self): + pass + + class B(A): + pass + + class X(object): + def __eq__(self, other): + return True + + a = A() + a2 = A() + assert a.m is a.m + assert id(a.m) == id(a.m) + assert a.m is not a.n + assert id(a.m) != id(a.n) + assert a.m is not a2.m + assert id(a.m) != id(a2.m) + + assert A.m is A.m + assert id(A.m) == id(A.m) + assert A.m is not A.n + assert id(A.m) != id(A.n) + assert A.m is not B.m + assert id(A.m) != id(B.m) + class TestMethod: def setup_method(self, method): diff --git a/pypy/module/__builtin__/descriptor.py b/pypy/module/__builtin__/descriptor.py --- a/pypy/module/__builtin__/descriptor.py +++ b/pypy/module/__builtin__/descriptor.py @@ -79,6 +79,7 @@ W_Super.typedef = TypeDef( 'super', __new__ = interp2app(descr_new_super), + __thisclass__ = interp_attrproperty_w("w_starttype", W_Super), __getattribute__ = interp2app(W_Super.getattribute), __get__ = interp2app(W_Super.get), __doc__ = """super(type) -> unbound super object diff --git a/pypy/module/__builtin__/test/test_descriptor.py b/pypy/module/__builtin__/test/test_descriptor.py --- a/pypy/module/__builtin__/test/test_descriptor.py +++ b/pypy/module/__builtin__/test/test_descriptor.py @@ -214,7 +214,7 @@ c = C() assert C.goo(1) == (C, 1) assert c.goo(1) == (C, 1) - + assert c.foo(1) == (c, 1) class D(C): pass @@ -238,6 +238,17 @@ meth = classmethod(1).__get__(1) raises(TypeError, meth) + def test_super_thisclass(self): + class A(object): + pass + + assert super(A, A()).__thisclass__ is A + + class B(A): + pass + + assert super(B, B()).__thisclass__ is B + assert super(A, B()).__thisclass__ is A def test_property_docstring(self): assert property.__doc__.startswith('property') diff --git a/pypy/module/_collections/app_defaultdict.py b/pypy/module/_collections/app_defaultdict.py --- a/pypy/module/_collections/app_defaultdict.py +++ b/pypy/module/_collections/app_defaultdict.py @@ -12,6 +12,7 @@ class defaultdict(dict): __slots__ = ['default_factory'] + __module__ = 'collections' def __init__(self, *args, **kwds): if len(args) > 0: diff --git a/pypy/module/_collections/test/test_defaultdict.py b/pypy/module/_collections/test/test_defaultdict.py --- a/pypy/module/_collections/test/test_defaultdict.py +++ b/pypy/module/_collections/test/test_defaultdict.py @@ -14,6 +14,12 @@ d[5].append(44) assert l == [42, 43] and l2 == [44] + def test_module(self): + from _collections import defaultdict + assert repr(defaultdict) in ( + "<class 'collections.defaultdict'>", # on PyPy + "<type 'collections.defaultdict'>") # on CPython + def test_keyerror_without_factory(self): from _collections import defaultdict for d1 in [defaultdict(), defaultdict(None)]: diff --git a/pypy/module/_sre/interp_sre.py b/pypy/module/_sre/interp_sre.py --- a/pypy/module/_sre/interp_sre.py +++ b/pypy/module/_sre/interp_sre.py @@ -7,6 +7,7 @@ from pypy.interpreter.error import OperationError from rpython.rlib.rarithmetic import intmask from rpython.rlib import jit +from rpython.rlib.rstring import StringBuilder, UnicodeBuilder # ____________________________________________________________ # @@ -36,6 +37,8 @@ if 0 <= start <= end: if isinstance(ctx, rsre_core.BufMatchContext): return space.wrap(ctx._buffer.getslice(start, end, 1, end-start)) + if isinstance(ctx, rsre_core.StrMatchContext): + return space.wrap(ctx._string[start:end]) elif isinstance(ctx, rsre_core.UnicodeMatchContext): return space.wrap(ctx._unicodestr[start:end]) else: @@ -98,8 +101,8 @@ space.wrap("cannot copy this pattern object")) def make_ctx(self, w_string, pos=0, endpos=sys.maxint): - """Make a BufMatchContext or a UnicodeMatchContext for searching - in the given w_string object.""" + """Make a StrMatchContext, BufMatchContext or a UnicodeMatchContext for + searching in the given w_string object.""" space = self.space if pos < 0: pos = 0 @@ -113,6 +116,14 @@ endpos = len(unicodestr) return rsre_core.UnicodeMatchContext(self.code, unicodestr, pos, endpos, self.flags) + elif space.isinstance_w(w_string, space.w_str): + str = space.str_w(w_string) + if pos > len(str): + pos = len(str) + if endpos > len(str): + endpos = len(str) + return rsre_core.StrMatchContext(self.code, str, + pos, endpos, self.flags) else: buf = space.readbuf_w(w_string) size = buf.getlength() @@ -216,6 +227,11 @@ def subx(self, w_ptemplate, w_string, count): space = self.space + # use a (much faster) string/unicode builder if w_ptemplate and + # w_string are both string or both unicode objects, and if w_ptemplate + # is a literal + use_builder = False + filter_as_unicode = filter_as_string = None if space.is_true(space.callable(w_ptemplate)): w_filter = w_ptemplate filter_is_callable = True @@ -223,6 +239,8 @@ if space.isinstance_w(w_ptemplate, space.w_unicode): filter_as_unicode = space.unicode_w(w_ptemplate) literal = u'\\' not in filter_as_unicode + use_builder = ( + space.isinstance_w(w_string, space.w_unicode) and literal) else: try: filter_as_string = space.str_w(w_ptemplate) @@ -232,6 +250,8 @@ literal = False else: literal = '\\' not in filter_as_string + use_builder = ( + space.isinstance_w(w_string, space.w_str) and literal) if literal: w_filter = w_ptemplate filter_is_callable = False @@ -242,19 +262,44 @@ space.wrap(self), w_ptemplate) filter_is_callable = space.is_true(space.callable(w_filter)) # + # XXX this is a bit of a mess, but it improves performance a lot ctx = self.make_ctx(w_string) - sublist_w = [] + sublist_w = strbuilder = unicodebuilder = None + if use_builder: + if filter_as_unicode is not None: + unicodebuilder = UnicodeBuilder(ctx.end) + else: + assert filter_as_string is not None + strbuilder = StringBuilder(ctx.end) + else: + sublist_w = [] n = last_pos = 0 while not count or n < count: + sub_jitdriver.jit_merge_point( + self=self, + use_builder=use_builder, + filter_is_callable=filter_is_callable, + filter_type=type(w_filter), + ctx=ctx, + w_filter=w_filter, + strbuilder=strbuilder, + unicodebuilder=unicodebuilder, + filter_as_string=filter_as_string, + filter_as_unicode=filter_as_unicode, + count=count, + w_string=w_string, + n=n, last_pos=last_pos, sublist_w=sublist_w + ) + space = self.space if not searchcontext(space, ctx): break if last_pos < ctx.match_start: - sublist_w.append(slice_w(space, ctx, last_pos, - ctx.match_start, space.w_None)) + _sub_append_slice( + ctx, space, use_builder, sublist_w, + strbuilder, unicodebuilder, last_pos, ctx.match_start) start = ctx.match_end if start == ctx.match_start: start += 1 - nextctx = ctx.fresh_copy(start) if not (last_pos == ctx.match_start == ctx.match_end and n > 0): # the above ignores empty matches on latest position @@ -262,28 +307,71 @@ w_match = self.getmatch(ctx, True) w_piece = space.call_function(w_filter, w_match) if not space.is_w(w_piece, space.w_None): + assert strbuilder is None and unicodebuilder is None + assert not use_builder sublist_w.append(w_piece) else: - sublist_w.append(w_filter) + if use_builder: + if strbuilder is not None: + assert filter_as_string is not None + strbuilder.append(filter_as_string) + else: + assert unicodebuilder is not None + assert filter_as_unicode is not None + unicodebuilder.append(filter_as_unicode) + else: + sublist_w.append(w_filter) last_pos = ctx.match_end n += 1 elif last_pos >= ctx.end: break # empty match at the end: finished - ctx = nextctx + ctx.reset(start) if last_pos < ctx.end: - sublist_w.append(slice_w(space, ctx, last_pos, ctx.end, - space.w_None)) + _sub_append_slice(ctx, space, use_builder, sublist_w, + strbuilder, unicodebuilder, last_pos, ctx.end) + if use_builder: + if strbuilder is not None: + return space.wrap(strbuilder.build()), n + else: + assert unicodebuilder is not None + return space.wrap(unicodebuilder.build()), n + else: + if space.isinstance_w(w_string, space.w_unicode): + w_emptystr = space.wrap(u'') + else: + w_emptystr = space.wrap('') + w_item = space.call_method(w_emptystr, 'join', + space.newlist(sublist_w)) + return w_item, n - if space.isinstance_w(w_string, space.w_unicode): - w_emptystr = space.wrap(u'') - else: - w_emptystr = space.wrap('') - w_item = space.call_method(w_emptystr, 'join', - space.newlist(sublist_w)) - return w_item, n +sub_jitdriver = jit.JitDriver( + reds="""count n last_pos + ctx w_filter + strbuilder unicodebuilder + filter_as_string + filter_as_unicode + w_string sublist_w + self""".split(), + greens=["filter_is_callable", "use_builder", "filter_type", "ctx.pattern"]) +def _sub_append_slice(ctx, space, use_builder, sublist_w, + strbuilder, unicodebuilder, start, end): + if use_builder: + if isinstance(ctx, rsre_core.BufMatchContext): + assert strbuilder is not None + return strbuilder.append(ctx._buffer.getslice(start, end, 1, end-start)) + if isinstance(ctx, rsre_core.StrMatchContext): + assert strbuilder is not None + return strbuilder.append_slice(ctx._string, start, end) + elif isinstance(ctx, rsre_core.UnicodeMatchContext): + assert unicodebuilder is not None + return unicodebuilder.append_slice(ctx._unicodestr, start, end) + assert 0, "unreachable" + else: + sublist_w.append(slice_w(space, ctx, start, end, space.w_None)) + @unwrap_spec(flags=int, groups=int, w_groupindex=WrappedDefault(None), w_indexgroup=WrappedDefault(None)) def SRE_Pattern__new__(space, w_subtype, w_pattern, flags, w_code, @@ -482,6 +570,8 @@ ctx = self.ctx if isinstance(ctx, rsre_core.BufMatchContext): return space.wrap(ctx._buffer.as_str()) + elif isinstance(ctx, rsre_core.StrMatchContext): + return space.wrap(ctx._string) elif isinstance(ctx, rsre_core.UnicodeMatchContext): return space.wrap(ctx._unicodestr) else: diff --git a/pypy/module/micronumpy/appbridge.py b/pypy/module/micronumpy/appbridge.py --- a/pypy/module/micronumpy/appbridge.py +++ b/pypy/module/micronumpy/appbridge.py @@ -9,6 +9,7 @@ w_array_repr = None w_array_str = None w__usefields = None + w_partition = None def __init__(self, space): pass diff --git a/pypy/module/micronumpy/ndarray.py b/pypy/module/micronumpy/ndarray.py --- a/pypy/module/micronumpy/ndarray.py +++ b/pypy/module/micronumpy/ndarray.py @@ -557,8 +557,12 @@ return self.get_scalar_value().item(space) l_w = [] for i in range(self.get_shape()[0]): - l_w.append(space.call_method(self.descr_getitem(space, - space.wrap(i)), "tolist")) + item_w = self.descr_getitem(space, space.wrap(i)) + if (isinstance(item_w, W_NDimArray) or + isinstance(item_w, boxes.W_GenericBox)): + l_w.append(space.call_method(item_w, "tolist")) + else: + l_w.append(item_w) return space.newlist(l_w) def descr_ravel(self, space, w_order=None): @@ -934,6 +938,10 @@ return return self.implementation.sort(space, w_axis, w_order) + def descr_partition(self, space, __args__): + return get_appbridge_cache(space).call_method( + space, 'numpy.core._partition_use', 'partition', __args__.prepend(self)) + def descr_squeeze(self, space, w_axis=None): cur_shape = self.get_shape() if not space.is_none(w_axis): @@ -1658,6 +1666,7 @@ argsort = interp2app(W_NDimArray.descr_argsort), sort = interp2app(W_NDimArray.descr_sort), + partition = interp2app(W_NDimArray.descr_partition), astype = interp2app(W_NDimArray.descr_astype), base = GetSetProperty(W_NDimArray.descr_get_base), byteswap = interp2app(W_NDimArray.descr_byteswap), diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py --- a/pypy/module/micronumpy/test/test_ndarray.py +++ b/pypy/module/micronumpy/test/test_ndarray.py @@ -1936,6 +1936,22 @@ a = array([[1, 2], [3, 4]]) assert (a + a).tolist() == [[2, 4], [6, 8]] + def test_tolist_object(self): + from numpy import array + a = array([0], dtype=object) + assert a.tolist() == [0] + + def test_tolist_object_slice(self): + from numpy import array + list_expected = [slice(0, 1), 0] + a = array(list_expected, dtype=object) + assert a.tolist() == list_expected + + def test_tolist_object_slice_2d(self): + from numpy import array + a = array([(slice(0, 1), 1), (0, 1)], dtype=object) + assert a.tolist() == [[slice(0, 1, None), 1], [0, 1]] + def test_tolist_slice(self): from numpy import array a = array([[17.1, 27.2], [40.3, 50.3]]) diff --git a/pypy/objspace/std/complexobject.py b/pypy/objspace/std/complexobject.py --- a/pypy/objspace/std/complexobject.py +++ b/pypy/objspace/std/complexobject.py @@ -266,11 +266,12 @@ return None from rpython.rlib.longlong2float import float2longlong from pypy.objspace.std.util import IDTAG_COMPLEX as tag + from pypy.objspace.std.util import IDTAG_SHIFT real = space.float_w(space.getattr(self, space.wrap("real"))) imag = space.float_w(space.getattr(self, space.wrap("imag"))) real_b = rbigint.fromrarith_int(float2longlong(real)) imag_b = rbigint.fromrarith_int(r_ulonglong(float2longlong(imag))) - val = real_b.lshift(64).or_(imag_b).lshift(3).int_or_(tag) + val = real_b.lshift(64).or_(imag_b).lshift(IDTAG_SHIFT).int_or_(tag) return space.newlong_from_rbigint(val) def int(self, space): diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py --- a/pypy/objspace/std/floatobject.py +++ b/pypy/objspace/std/floatobject.py @@ -181,9 +181,10 @@ return None from rpython.rlib.longlong2float import float2longlong from pypy.objspace.std.util import IDTAG_FLOAT as tag + from pypy.objspace.std.util import IDTAG_SHIFT val = float2longlong(space.float_w(self)) b = rbigint.fromrarith_int(val) - b = b.lshift(3).int_or_(tag) + b = b.lshift(IDTAG_SHIFT).int_or_(tag) return space.newlong_from_rbigint(b) def __repr__(self): diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py --- a/pypy/objspace/std/intobject.py +++ b/pypy/objspace/std/intobject.py @@ -24,7 +24,7 @@ from pypy.interpreter.typedef import TypeDef from pypy.objspace.std import newformat from pypy.objspace.std.util import ( - BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_INT, wrap_parsestringerror) + BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_INT, IDTAG_SHIFT, wrap_parsestringerror) SENTINEL = object() @@ -46,7 +46,7 @@ if self.user_overridden_class: return None b = space.bigint_w(self) - b = b.lshift(3).int_or_(IDTAG_INT) + b = b.lshift(IDTAG_SHIFT).int_or_(IDTAG_INT) return space.newlong_from_rbigint(b) def int(self, space): diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py --- a/pypy/objspace/std/longobject.py +++ b/pypy/objspace/std/longobject.py @@ -16,7 +16,7 @@ from pypy.objspace.std import newformat from pypy.objspace.std.intobject import W_AbstractIntObject from pypy.objspace.std.util import ( - BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_LONG, wrap_parsestringerror) + BINARY_OPS, CMP_OPS, COMMUTATIVE_OPS, IDTAG_LONG, IDTAG_SHIFT, wrap_parsestringerror) def delegate_other(func): @@ -45,7 +45,7 @@ if self.user_overridden_class: return None b = space.bigint_w(self) - b = b.lshift(3).int_or_(IDTAG_LONG) + b = b.lshift(IDTAG_SHIFT).int_or_(IDTAG_LONG) return space.newlong_from_rbigint(b) def unwrap(self, space): diff --git a/pypy/objspace/std/test/test_obj.py b/pypy/objspace/std/test/test_obj.py --- a/pypy/objspace/std/test/test_obj.py +++ b/pypy/objspace/std/test/test_obj.py @@ -172,15 +172,15 @@ def test_id_on_primitives(self): if self.cpython_apptest: skip("cpython behaves differently") - assert id(1) == (1 << 3) + 1 - assert id(1l) == (1 << 3) + 3 + assert id(1) == (1 << 4) + 1 + assert id(1l) == (1 << 4) + 3 class myint(int): pass assert id(myint(1)) != id(1) assert id(1.0) & 7 == 5 assert id(-0.0) != id(0.0) - assert hex(id(2.0)) == '0x20000000000000005L' + assert hex(id(2.0)) == '0x40000000000000005L' assert id(0.0) == 5 def test_id_on_strs(self): diff --git a/pypy/objspace/std/util.py b/pypy/objspace/std/util.py --- a/pypy/objspace/std/util.py +++ b/pypy/objspace/std/util.py @@ -2,11 +2,13 @@ from pypy.interpreter.error import OperationError, oefmt +IDTAG_SHIFT = 4 IDTAG_INT = 1 IDTAG_LONG = 3 IDTAG_FLOAT = 5 IDTAG_COMPLEX = 7 +IDTAG_METHOD = 9 CMP_OPS = dict(lt='<', le='<=', eq='==', ne='!=', gt='>', ge='>=') BINARY_BITWISE_OPS = {'and': '&', 'lshift': '<<', 'or': '|', 'rshift': '>>', diff --git a/pypy/tool/release/force-builds.py b/pypy/tool/release/force-builds.py --- a/pypy/tool/release/force-builds.py +++ b/pypy/tool/release/force-builds.py @@ -9,7 +9,7 @@ modified by PyPy team """ -import os, sys, urllib +import os, sys, urllib, subprocess from twisted.internet import reactor, defer from twisted.python import log @@ -83,4 +83,9 @@ (options, args) = parser.parse_args() if not options.branch: parser.error("branch option required") + try: + subprocess.check_call(['hg','id','-r', options.branch]) + except subprocess.CalledProcessError: + print 'branch', options.branch, 'could not be found in local repository' + sys.exit(-1) main(options.branch, options.server, user=options.user) diff --git a/rpython/doc/translation.rst b/rpython/doc/translation.rst --- a/rpython/doc/translation.rst +++ b/rpython/doc/translation.rst @@ -33,7 +33,7 @@ The RPython translation toolchain never sees Python source code or syntax trees, but rather starts with the *code objects* that define the behaviour of the function objects one gives it as input. The -`bytecode evaluator`_ and the :ref:`flow graph builder<flow-graphs>` work through these +:ref:`flow graph builder<flow-graphs>` works through these code objects using `abstract interpretation`_ to produce a control flow graph (one per function): yet another representation of the source program, but one which is suitable for applying type inference @@ -85,7 +85,6 @@ .. _PDF color version: _static/translation.pdf -.. _bytecode evaluator: interpreter.html .. _abstract interpretation: http://en.wikipedia.org/wiki/Abstract_interpretation _______________________________________________ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
