Author: Maciej Fijalkowski <fij...@gmail.com> Branch: jit-threshold-hooks Changeset: r65456:fc27f85eb8d9 Date: 2013-07-18 11:17 +0200 http://bitbucket.org/pypy/pypy/changeset/fc27f85eb8d9/
Log: merge default diff --git a/lib-python/2.7/distutils/sysconfig_pypy.py b/lib-python/2.7/distutils/sysconfig_pypy.py --- a/lib-python/2.7/distutils/sysconfig_pypy.py +++ b/lib-python/2.7/distutils/sysconfig_pypy.py @@ -65,6 +65,11 @@ g['SOABI'] = g['SO'].rsplit('.')[0] g['LIBDIR'] = os.path.join(sys.prefix, 'lib') g['CC'] = "gcc -pthread" # -pthread might not be valid on OS/X, check + g['OPT'] = "" + g['CFLAGS'] = "" + g['CPPFLAGS'] = "" + g['CCSHARED'] = '-shared -O2 -fPIC -Wimplicit' + g['LDSHARED'] = g['CC'] + ' -shared' global _config_vars _config_vars = g @@ -122,13 +127,34 @@ optional C speedup components. """ if compiler.compiler_type == "unix": - compiler.compiler_so.extend(['-O2', '-fPIC', '-Wimplicit']) + cc, opt, cflags, ccshared, ldshared = get_config_vars( + 'CC', 'OPT', 'CFLAGS', 'CCSHARED', 'LDSHARED') + compiler.shared_lib_extension = get_config_var('SO') - if "CFLAGS" in os.environ: - cflags = os.environ["CFLAGS"].split() - compiler.compiler.extend(cflags) - compiler.compiler_so.extend(cflags) - compiler.linker_so.extend(cflags) + + if 'LDSHARED' in os.environ: + ldshared = os.environ['LDSHARED'] + if 'CPP' in os.environ: + cpp = os.environ['CPP'] + else: + cpp = cc + " -E" # not always + if 'LDFLAGS' in os.environ: + ldshared = ldshared + ' ' + os.environ['LDFLAGS'] + if 'CFLAGS' in os.environ: + cflags = opt + ' ' + os.environ['CFLAGS'] + ldshared = ldshared + ' ' + os.environ['CFLAGS'] + if 'CPPFLAGS' in os.environ: + cpp = cpp + ' ' + os.environ['CPPFLAGS'] + cflags = cflags + ' ' + os.environ['CPPFLAGS'] + ldshared = ldshared + ' ' + os.environ['CPPFLAGS'] + + cc_cmd = cc + ' ' + cflags + + compiler.set_executables( + preprocessor=cpp, + compiler=cc_cmd, + compiler_so=cc_cmd + ' ' + ccshared, + linker_so=ldshared) from sysconfig_cpython import ( diff --git a/pypy/doc/getting-started-dev.rst b/pypy/doc/getting-started-dev.rst --- a/pypy/doc/getting-started-dev.rst +++ b/pypy/doc/getting-started-dev.rst @@ -4,6 +4,12 @@ .. contents:: +.. warning:: + + Please `read this FAQ entry`_ first! + +.. _`read this FAQ entry`: http://doc.pypy.org/en/latest/faq.html#do-i-have-to-rewrite-my-programs-in-rpython + RPython is a subset of Python that can be statically compiled. The PyPy interpreter is written mostly in RPython (with pieces in Python), while the RPython compiler is written in Python. The hard to understand part diff --git a/pypy/doc/whatsnew-2.1.rst b/pypy/doc/whatsnew-2.1.rst --- a/pypy/doc/whatsnew-2.1.rst +++ b/pypy/doc/whatsnew-2.1.rst @@ -76,3 +76,8 @@ .. branch: inline-identityhash Inline the fast path of id() and hash() + +.. branch: package-tk +Adapt package.py script to compile CFFI tk extension. Add a --without-tk switch +to optionally skip it. + 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 @@ -16,3 +16,18 @@ .. branch: flowoperators Simplify rpython/flowspace/ code by using more metaprogramming. Create SpaceOperator class to gather static information about flow graph operations. + +.. branch: package-tk +Adapt package.py script to compile CFFI tk extension. Add a --without-tk switch +to optionally skip it. + +.. branch: distutils-cppldflags +Copy CPython's implementation of customize_compiler, dont call split on +environment variables, honour CFLAGS, CPPFLAGS, LDSHARED and LDFLAGS on Unices. + +.. branch: precise-instantiate +When an RPython class is instantiated via an indirect call (that is, which +class is being instantiated isn't known precisely) allow the optimizer to have +more precise information about which functions can be called. Needed for Topaz. + +.. branch: ssl_moving_write_buffer diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py --- a/pypy/interpreter/app_main.py +++ b/pypy/interpreter/app_main.py @@ -196,6 +196,11 @@ print >> sys.stderr, "Python", sys.version raise SystemExit + +def funroll_loops(*args): + print("Vroom vroom, I'm a racecar!") + + def set_jit_option(options, jitparam, *args): if jitparam == 'help': _print_jit_help() @@ -381,6 +386,7 @@ 'Q': (div_option, Ellipsis), '--info': (print_info, None), '--jit': (set_jit_option, Ellipsis), + '-funroll-loops': (funroll_loops, None), '--': (end_options, None), } diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py --- a/pypy/module/__pypy__/__init__.py +++ b/pypy/module/__pypy__/__init__.py @@ -36,6 +36,19 @@ } +class IntOpModule(MixedModule): + appleveldefs = {} + interpleveldefs = { + 'int_add': 'interp_intop.int_add', + 'int_sub': 'interp_intop.int_sub', + 'int_mul': 'interp_intop.int_mul', + 'int_floordiv': 'interp_intop.int_floordiv', + 'int_mod': 'interp_intop.int_mod', + 'int_lshift': 'interp_intop.int_lshift', + 'uint_rshift': 'interp_intop.uint_rshift', + } + + class Module(MixedModule): appleveldefs = { } @@ -67,6 +80,7 @@ "builders": BuildersModule, "time": TimeModule, "thread": ThreadModule, + "intop": IntOpModule, } def setup_after_space_initialization(self): diff --git a/pypy/module/__pypy__/interp_intop.py b/pypy/module/__pypy__/interp_intop.py new file mode 100644 --- /dev/null +++ b/pypy/module/__pypy__/interp_intop.py @@ -0,0 +1,35 @@ +from pypy.interpreter.gateway import unwrap_spec +from rpython.rtyper.lltypesystem import lltype +from rpython.rtyper.lltypesystem.lloperation import llop +from rpython.rlib.rarithmetic import r_uint, intmask + + +@unwrap_spec(n=int, m=int) +def int_add(space, n, m): + return space.wrap(llop.int_add(lltype.Signed, n, m)) + +@unwrap_spec(n=int, m=int) +def int_sub(space, n, m): + return space.wrap(llop.int_sub(lltype.Signed, n, m)) + +@unwrap_spec(n=int, m=int) +def int_mul(space, n, m): + return space.wrap(llop.int_mul(lltype.Signed, n, m)) + +@unwrap_spec(n=int, m=int) +def int_floordiv(space, n, m): + return space.wrap(llop.int_floordiv(lltype.Signed, n, m)) + +@unwrap_spec(n=int, m=int) +def int_mod(space, n, m): + return space.wrap(llop.int_mod(lltype.Signed, n, m)) + +@unwrap_spec(n=int, m=int) +def int_lshift(space, n, m): + return space.wrap(llop.int_lshift(lltype.Signed, n, m)) + +@unwrap_spec(n=int, m=int) +def uint_rshift(space, n, m): + n = r_uint(n) + x = llop.uint_rshift(lltype.Unsigned, n, m) + return space.wrap(intmask(x)) diff --git a/pypy/module/__pypy__/test/test_intop.py b/pypy/module/__pypy__/test/test_intop.py new file mode 100644 --- /dev/null +++ b/pypy/module/__pypy__/test/test_intop.py @@ -0,0 +1,96 @@ + + +class AppTestIntOp: + spaceconfig = dict(usemodules=['__pypy__']) + + def w_intmask(self, n): + import sys + n &= (sys.maxint*2+1) + if n > sys.maxint: + n -= 2*(sys.maxint+1) + return int(n) + + def test_intmask(self): + import sys + assert self.intmask(sys.maxint) == sys.maxint + assert self.intmask(sys.maxint+1) == -sys.maxint-1 + assert self.intmask(-sys.maxint-2) == sys.maxint + N = 2 ** 128 + assert self.intmask(N+sys.maxint) == sys.maxint + assert self.intmask(N+sys.maxint+1) == -sys.maxint-1 + assert self.intmask(N-sys.maxint-2) == sys.maxint + + def test_int_add(self): + import sys + from __pypy__ import intop + assert intop.int_add(40, 2) == 42 + assert intop.int_add(sys.maxint, 1) == -sys.maxint-1 + assert intop.int_add(-2, -sys.maxint) == sys.maxint + + def test_int_sub(self): + import sys + from __pypy__ import intop + assert intop.int_sub(40, -2) == 42 + assert intop.int_sub(sys.maxint, -1) == -sys.maxint-1 + assert intop.int_sub(-2, sys.maxint) == sys.maxint + + def test_int_mul(self): + import sys + from __pypy__ import intop + assert intop.int_mul(40, -2) == -80 + assert intop.int_mul(-sys.maxint, -sys.maxint) == ( + self.intmask(sys.maxint ** 2)) + + def test_int_floordiv(self): + import sys + from __pypy__ import intop + assert intop.int_floordiv(41, 3) == 13 + assert intop.int_floordiv(41, -3) == -13 + assert intop.int_floordiv(-41, 3) == -13 + assert intop.int_floordiv(-41, -3) == 13 + assert intop.int_floordiv(-sys.maxint, -1) == sys.maxint + assert intop.int_floordiv(sys.maxint, -1) == -sys.maxint + + def test_int_mod(self): + import sys + from __pypy__ import intop + assert intop.int_mod(41, 3) == 2 + assert intop.int_mod(41, -3) == 2 + assert intop.int_mod(-41, 3) == -2 + assert intop.int_mod(-41, -3) == -2 + assert intop.int_mod(-sys.maxint, -1) == 0 + assert intop.int_mod(sys.maxint, -1) == 0 + + def test_int_lshift(self): + import sys + from __pypy__ import intop + if sys.maxint == 2**31-1: + bits = 32 + else: + bits = 64 + assert intop.int_lshift(42, 3) == 42 << 3 + assert intop.int_lshift(0, 3333) == 0 + assert intop.int_lshift(1, bits-2) == 1 << (bits-2) + assert intop.int_lshift(1, bits-1) == -sys.maxint-1 == (-1) << (bits-1) + assert intop.int_lshift(-1, bits-2) == (-1) << (bits-2) + assert intop.int_lshift(-1, bits-1) == -sys.maxint-1 + assert intop.int_lshift(sys.maxint // 3, 2) == ( + self.intmask((sys.maxint // 3) << 2)) + assert intop.int_lshift(-sys.maxint // 3, 2) == ( + self.intmask((-sys.maxint // 3) << 2)) + + def test_uint_rshift(self): + import sys + from __pypy__ import intop + if sys.maxint == 2**31-1: + bits = 32 + else: + bits = 64 + N = 1 << bits + assert intop.uint_rshift(42, 3) == 42 >> 3 + assert intop.uint_rshift(-42, 3) == (N-42) >> 3 + assert intop.uint_rshift(0, 3333) == 0 + assert intop.uint_rshift(-1, 0) == -1 + assert intop.uint_rshift(-1, 1) == sys.maxint + assert intop.uint_rshift(-1, bits-2) == 3 + assert intop.uint_rshift(-1, bits-1) == 1 diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -2760,6 +2760,20 @@ assert wr() is None py.test.raises(RuntimeError, from_handle, cast(BCharP, 0)) +def test_new_handle_cycle(): + import _weakref + BVoidP = new_pointer_type(new_void_type()) + class A(object): + pass + o = A() + o.cycle = newp_handle(BVoidP, o) + wr = _weakref.ref(o) + del o + for i in range(3): + if wr() is not None: + import gc; gc.collect() + assert wr() is None + def _test_bitfield_details(flag): BChar = new_primitive_type("char") BShort = new_primitive_type("short") diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py --- a/pypy/module/_ssl/interp_ssl.py +++ b/pypy/module/_ssl/interp_ssl.py @@ -722,7 +722,10 @@ libssl_SSL_CTX_set_verify(ss.ctx, verification_mode, None) ss.ssl = libssl_SSL_new(ss.ctx) # new ssl struct libssl_SSL_set_fd(ss.ssl, sock_fd) # set the socket for SSL - libssl_SSL_set_mode(ss.ssl, SSL_MODE_AUTO_RETRY) + # The ACCEPT_MOVING_WRITE_BUFFER flag is necessary because the address + # of a str object may be changed by the garbage collector. + libssl_SSL_set_mode(ss.ssl, + SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) # If the socket is in non-blocking mode or timeout mode, set the BIO # to non-blocking mode (blocking is the default) diff --git a/pypy/module/micronumpy/arrayimpl/concrete.py b/pypy/module/micronumpy/arrayimpl/concrete.py --- a/pypy/module/micronumpy/arrayimpl/concrete.py +++ b/pypy/module/micronumpy/arrayimpl/concrete.py @@ -280,7 +280,7 @@ backstrides, shape, self, orig_arr) def get_storage_as_int(self, space): - return rffi.cast(lltype.Signed, self.storage) + return rffi.cast(lltype.Signed, self.storage) + self.start def get_storage(self): return self.storage diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -2212,6 +2212,11 @@ a = a[::2] i = a.__array_interface__ assert isinstance(i['data'][0], int) + b = array(range(9), dtype=int) + c = b[3:5] + b_data = b.__array_interface__['data'][0] + c_data = c.__array_interface__['data'][0] + assert b_data + 3 * b.dtype.itemsize == c_data def test_array_indexing_one_elem(self): from numpypy import array, arange diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py --- a/pypy/objspace/std/dictmultiobject.py +++ b/pypy/objspace/std/dictmultiobject.py @@ -1050,7 +1050,7 @@ else: # general case -- "for k in o.keys(): dict.__setitem__(d, k, o[k])" data_w = space.listview(space.call_function(w_method)) - update1_keys(space, w_dict, data_w) + update1_keys(space, w_dict, w_data, data_w) @jit.look_inside_iff(lambda space, w_dict, w_data: @@ -1074,7 +1074,7 @@ w_dict.setitem(w_key, w_value) -def update1_keys(space, w_dict, data_w): +def update1_keys(space, w_dict, w_data, data_w): for w_key in data_w: w_value = space.getitem(w_data, w_key) w_dict.setitem(w_key, w_value) diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py --- a/pypy/objspace/std/test/test_dictmultiobject.py +++ b/pypy/objspace/std/test/test_dictmultiobject.py @@ -367,6 +367,16 @@ d.update({'foo': 'bar'}, baz=1) assert d == {'foo': 'bar', 'baz': 1} + def test_update_keys_method(self): + class Foo(object): + def keys(self): + return [4, 1] + def __getitem__(self, key): + return key * 10 + d = {} + d.update(Foo()) + assert d == {1: 10, 4: 40} + def test_values(self): d = {1: 2, 3: 4} vals = d.values() diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py --- a/rpython/annotator/test/test_annrpython.py +++ b/rpython/annotator/test/test_annrpython.py @@ -740,7 +740,8 @@ s = a.build_types(f, [B]) assert s.classdef is a.bookkeeper.getuniqueclassdef(C) - def test_union_type_some_opbc(self): + def test_union_type_some_pbc(self): + py.test.skip("is there a point? f() can return self.__class__ instead") class A(object): name = "A" diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -23,7 +23,6 @@ supports_longlong = False # XXX requires an implementation of # read_timestamp that works in user mode supports_singlefloats = not detect_hardfloat() - can_inline_varsize_malloc = True from rpython.jit.backend.arm.arch import JITFRAME_FIXED_SIZE all_reg_indexes = range(len(all_regs)) diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -21,8 +21,6 @@ class AbstractLLCPU(AbstractCPU): from rpython.jit.metainterp.typesystem import llhelper as ts - can_inline_varsize_malloc = False - def __init__(self, rtyper, stats, opts, translate_support_code=False, gcdescr=None): assert type(opts) is not bool diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py --- a/rpython/jit/backend/llsupport/rewrite.py +++ b/rpython/jit/backend/llsupport/rewrite.py @@ -305,8 +305,6 @@ arraydescr, kind=FLAG_ARRAY): """ itemsize is an int, v_length and v_result are boxes """ - if not self.cpu.can_inline_varsize_malloc: - return False # temporary, kill when ARM supports it gc_descr = self.gc_ll_descr if (kind == FLAG_ARRAY and (arraydescr.basesize != gc_descr.standard_array_basesize or diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py --- a/rpython/jit/backend/llsupport/test/test_rewrite.py +++ b/rpython/jit/backend/llsupport/test/test_rewrite.py @@ -109,8 +109,6 @@ class BaseFakeCPU(object): JITFRAME_FIXED_SIZE = 0 - can_inline_varsize_malloc = True - def __init__(self): self.tracker = FakeTracker() self._cache = {} diff --git a/rpython/jit/backend/x86/runner.py b/rpython/jit/backend/x86/runner.py --- a/rpython/jit/backend/x86/runner.py +++ b/rpython/jit/backend/x86/runner.py @@ -23,8 +23,6 @@ with_threads = False frame_reg = regloc.ebp - can_inline_varsize_malloc = True - from rpython.jit.backend.x86.arch import JITFRAME_FIXED_SIZE all_reg_indexes = gpr_reg_mgr_cls.all_reg_indexes gen_regs = gpr_reg_mgr_cls.all_regs diff --git a/rpython/jit/codewriter/support.py b/rpython/jit/codewriter/support.py --- a/rpython/jit/codewriter/support.py +++ b/rpython/jit/codewriter/support.py @@ -7,6 +7,7 @@ from rpython.rlib import rgc from rpython.rlib.jit import elidable, oopspec from rpython.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint, intmask +from rpython.rlib.rarithmetic import LONG_BIT from rpython.rtyper import rlist from rpython.rtyper.annlowlevel import MixLevelHelperAnnotator from rpython.rtyper.extregistry import ExtRegistryEntry @@ -272,10 +273,9 @@ return result def _ll_1_int_abs(x): - if x < 0: - return -x - else: - return x + # this version doesn't branch + mask = x >> (LONG_BIT - 1) + return (x ^ mask) - mask def _ll_1_cast_uint_to_float(x): # XXX on 32-bit platforms, this should be done using cast_longlong_to_float diff --git a/rpython/jit/codewriter/test/test_codewriter.py b/rpython/jit/codewriter/test/test_codewriter.py --- a/rpython/jit/codewriter/test/test_codewriter.py +++ b/rpython/jit/codewriter/test/test_codewriter.py @@ -13,6 +13,7 @@ self.ARGS = ARGS self.RESULT = RESULT self.effectinfo = effectinfo + def get_extra_info(self): return self.effectinfo @@ -37,7 +38,7 @@ class tracker: pass - + calldescrof = FakeCallDescr fielddescrof = FakeFieldDescr sizeof = FakeSizeDescr @@ -121,20 +122,32 @@ blackholeinterp.run() assert blackholeinterp.get_tmpreg_i() == 100+6+5+4+3 + def test_instantiate(): - class A1: id = 651 - class A2(A1): id = 652 - class B1: id = 661 - class B2(B1): id = 662 + class A1: + id = 651 + + class A2(A1): + id = 652 + + class B1: + id = 661 + + class B2(B1): + id = 662 + def dont_look(n): return n + 1 + + classes = [ + (A1, B1), + (A2, B2) + ] + def f(n): - if n > 5: - x, y = A1, B1 - else: - x, y = A2, B2 + x, y = classes[n] return x().id + y().id + dont_look(n) - rtyper = support.annotate(f, [35]) + rtyper = support.annotate(f, [0]) maingraph = rtyper.annotator.translator.graphs[0] cw = CodeWriter(FakeCPU(rtyper), [FakeJitDriverSD(maingraph)]) cw.find_all_graphs(FakePolicy()) @@ -149,16 +162,10 @@ else: assert 0, "missing instantiate_*_%s in:\n%r" % (expected, names) - # - print cw.assembler.list_of_addr2name - names = dict.fromkeys([value - for key, value in cw.assembler.list_of_addr2name]) - assert 'A1' in names - assert 'B1' in names - assert 'A2' in names - assert 'B2' in names + names = set([value for key, value in cw.assembler.list_of_addr2name]) assert 'dont_look' in names + def test_instantiate_with_unreasonable_attr(): # It is possible to have in real code the instantiate() function for # a class be dont-look-inside. This is caused by the code that @@ -169,17 +176,19 @@ name = graph.name return not (name.startswith('instantiate_') and name.endswith('A2')) + class A1: pass + class A2(A1): pass + + classes = [A1, A2] + def f(n): - if n > 5: - x = A1 - else: - x = A2 + x = classes[n] x() - rtyper = support.annotate(f, [35]) + rtyper = support.annotate(f, [1]) maingraph = rtyper.annotator.translator.graphs[0] cw = CodeWriter(FakeCPU(rtyper), [FakeJitDriverSD(maingraph)]) cw.find_all_graphs(MyFakePolicy()) @@ -188,12 +197,7 @@ names = [jitcode.name for jitcode in cw.assembler.indirectcalltargets] assert len(names) == 1 assert names[0].startswith('instantiate_') and names[0].endswith('A1') - # - print cw.assembler.list_of_addr2name - names = dict.fromkeys([value - for key, value in cw.assembler.list_of_addr2name]) - assert 'A1' in names - assert 'A2' in names + def test_int_abs(): def f(n): @@ -209,7 +213,7 @@ def test_raw_malloc_and_access(): TP = rffi.CArray(lltype.Signed) - + def f(n): a = lltype.malloc(TP, n, flavor='raw') a[0] = n diff --git a/rpython/jit/codewriter/test/test_effectinfo.py b/rpython/jit/codewriter/test/test_effectinfo.py --- a/rpython/jit/codewriter/test/test_effectinfo.py +++ b/rpython/jit/codewriter/test/test_effectinfo.py @@ -1,15 +1,22 @@ +import pytest + +from rpython.jit.codewriter.effectinfo import (effectinfo_from_writeanalyze, + EffectInfo, VirtualizableAnalyzer) +from rpython.rlib import jit +from rpython.rtyper.lltypesystem import lltype from rpython.rtyper.lltypesystem.rclass import OBJECT -from rpython.rtyper.lltypesystem import lltype from rpython.rtyper.ootypesystem import ootype -from rpython.jit.codewriter.effectinfo import effectinfo_from_writeanalyze,\ - EffectInfo +from rpython.translator.translator import TranslationContext, graphof -class FakeCPU: + +class FakeCPU(object): def fielddescrof(self, T, fieldname): return ('fielddescr', T, fieldname) + def arraydescrof(self, A): return ('arraydescr', A) + def test_no_oopspec_duplicate(): # check that all the various EffectInfo.OS_* have unique values oopspecs = set() @@ -18,6 +25,7 @@ assert value not in oopspecs oopspecs.add(value) + def test_include_read_field(): S = lltype.GcStruct("S", ("a", lltype.Signed)) effects = frozenset([("readstruct", lltype.Ptr(S), "a")]) @@ -26,6 +34,7 @@ assert not effectinfo.write_descrs_fields assert not effectinfo.write_descrs_arrays + def test_include_write_field(): S = lltype.GcStruct("S", ("a", lltype.Signed)) effects = frozenset([("struct", lltype.Ptr(S), "a")]) @@ -34,6 +43,7 @@ assert not effectinfo.readonly_descrs_fields assert not effectinfo.write_descrs_arrays + def test_include_read_array(): A = lltype.GcArray(lltype.Signed) effects = frozenset([("readarray", lltype.Ptr(A))]) @@ -43,6 +53,7 @@ assert not effectinfo.write_descrs_fields assert not effectinfo.write_descrs_arrays + def test_include_write_array(): A = lltype.GcArray(lltype.Signed) effects = frozenset([("array", lltype.Ptr(A))]) @@ -51,6 +62,7 @@ assert not effectinfo.write_descrs_fields assert list(effectinfo.write_descrs_arrays) == [('arraydescr', A)] + def test_dont_include_read_and_write_field(): S = lltype.GcStruct("S", ("a", lltype.Signed)) effects = frozenset([("readstruct", lltype.Ptr(S), "a"), @@ -60,6 +72,7 @@ assert list(effectinfo.write_descrs_fields) == [('fielddescr', S, "a")] assert not effectinfo.write_descrs_arrays + def test_dont_include_read_and_write_array(): A = lltype.GcArray(lltype.Signed) effects = frozenset([("readarray", lltype.Ptr(A)), @@ -78,6 +91,7 @@ assert not effectinfo.write_descrs_fields assert not effectinfo.write_descrs_arrays + def test_filter_out_array_of_void(): effects = frozenset([("array", lltype.Ptr(lltype.GcArray(lltype.Void)))]) effectinfo = effectinfo_from_writeanalyze(effects, None) @@ -85,6 +99,7 @@ assert not effectinfo.write_descrs_fields assert not effectinfo.write_descrs_arrays + def test_filter_out_struct_with_void(): effects = frozenset([("struct", lltype.Ptr(lltype.GcStruct("x", ("a", lltype.Void))), "a")]) effectinfo = effectinfo_from_writeanalyze(effects, None) @@ -92,6 +107,7 @@ assert not effectinfo.write_descrs_fields assert not effectinfo.write_descrs_arrays + def test_filter_out_ooarray_of_void(): effects = frozenset([("array", ootype.Array(ootype.Void))]) effectinfo = effectinfo_from_writeanalyze(effects, None) @@ -99,9 +115,43 @@ assert not effectinfo.write_descrs_fields assert not effectinfo.write_descrs_arrays + def test_filter_out_instance_with_void(): effects = frozenset([("struct", ootype.Instance("x", ootype.ROOT, {"a": ootype.Void}), "a")]) effectinfo = effectinfo_from_writeanalyze(effects, None) assert not effectinfo.readonly_descrs_fields assert not effectinfo.write_descrs_fields assert not effectinfo.write_descrs_arrays + + +class TestVirtualizableAnalyzer(object): + def analyze(self, func, sig): + t = TranslationContext() + t.buildannotator().build_types(func, sig) + t.buildrtyper().specialize() + fgraph = graphof(t, func) + return VirtualizableAnalyzer(t).analyze(fgraph.startblock.operations[0]) + + def test_constructor(self): + class A(object): + x = 1 + + class B(A): + x = 2 + + @jit.elidable + def g(cls): + return cls() + + def f(x): + if x: + cls = A + else: + cls = B + return g(cls).x + + def entry(x): + return f(x) + + res = self.analyze(entry, [int]) + assert not res diff --git a/rpython/jit/codewriter/test/test_support.py b/rpython/jit/codewriter/test/test_support.py --- a/rpython/jit/codewriter/test/test_support.py +++ b/rpython/jit/codewriter/test/test_support.py @@ -1,8 +1,9 @@ -import py +import py, sys from rpython.rtyper.lltypesystem import lltype from rpython.rtyper.annlowlevel import llstr from rpython.flowspace.model import Variable, Constant, SpaceOperation from rpython.jit.codewriter.support import decode_builtin_call, LLtypeHelpers +from rpython.jit.codewriter.support import _ll_1_int_abs def newconst(x): return Constant(x, lltype.typeOf(x)) @@ -133,3 +134,12 @@ py.test.raises(IndexError, func, p1, llstr("w")) py.test.raises(AttributeError, func, p1, llstr(None)) py.test.raises(AttributeError, func, llstr(None), p2) + +def test_int_abs(): + assert _ll_1_int_abs(0) == 0 + assert _ll_1_int_abs(1) == 1 + assert _ll_1_int_abs(10) == 10 + assert _ll_1_int_abs(sys.maxint) == sys.maxint + assert _ll_1_int_abs(-1) == 1 + assert _ll_1_int_abs(-10) == 10 + assert _ll_1_int_abs(-sys.maxint) == sys.maxint diff --git a/rpython/rlib/rbigint.py b/rpython/rlib/rbigint.py --- a/rpython/rlib/rbigint.py +++ b/rpython/rlib/rbigint.py @@ -454,11 +454,19 @@ @jit.elidable def repr(self): - return self.format(BASE10, suffix="L") + try: + x = self.toint() + except OverflowError: + return self.format(BASE10, suffix="L") + return str(x) + "L" @jit.elidable def str(self): - return self.format(BASE10) + try: + x = self.toint() + except OverflowError: + return self.format(BASE10) + return str(x) @jit.elidable def eq(self, other): @@ -2050,9 +2058,38 @@ # hint for the annotator for the slice below) return ''.join(result[next_char_index:]) -_FORMAT_MINDIGITS = 5 # 36 ** 5 fits in 32 bits, there may be a better choice for this -def _format_int(val, digits): +class _PartsCache(object): + def __init__(self): + # 36 - 3, because bases 0, 1 make no sense + # and 2 is handled differently + self.parts_cache = [None] * 34 + self.mindigits = [0] * 34 + + for i in range(34): + base = i + 3 + mindigits = 1 + while base ** mindigits < sys.maxint: + mindigits += 1 + mindigits -= 1 + self.mindigits[i] = mindigits + + def get_cached_parts(self, base): + index = base - 3 + res = self.parts_cache[index] + if res is None: + rbase = rbigint.fromint(base) + part = rbase.pow(rbigint.fromint(self.mindigits[index])) + res = [part] + self.parts_cache[base - 3] = res + return res + + def get_mindigits(self, base): + return self.mindigits[base - 3] + +_parts_cache = _PartsCache() + +def _format_int_general(val, digits): base = len(digits) out = [] while val: @@ -2061,26 +2098,27 @@ out.reverse() return "".join(out) +def _format_int10(val, digits): + return str(val) -def _format_recursive(x, i, output, pts, digits, size_prefix): +@specialize.arg(7) +def _format_recursive(x, i, output, pts, digits, size_prefix, mindigits, _format_int): # bottomed out with min_digit sized pieces # use str of ints if i < 0: # this checks whether any digit has been appended yet if output.getlength() == size_prefix: - if x.sign == 0: - pass - else: + if x.sign != 0: s = _format_int(x.toint(), digits) output.append(s) else: s = _format_int(x.toint(), digits) - output.append_multiple_char(digits[0], _FORMAT_MINDIGITS - len(s)) + output.append_multiple_char(digits[0], mindigits - len(s)) output.append(s) else: top, bot = x.divmod(pts[i]) # split the number - _format_recursive(top, i-1, output, pts, digits, size_prefix) - _format_recursive(bot, i-1, output, pts, digits, size_prefix) + _format_recursive(top, i-1, output, pts, digits, size_prefix, mindigits, _format_int) + _format_recursive(bot, i-1, output, pts, digits, size_prefix, mindigits, _format_int) def _format(x, digits, prefix='', suffix=''): if x.sign == 0: @@ -2095,22 +2133,42 @@ rbase = rbigint.fromint(base) two = rbigint.fromint(2) - pts = [rbase.pow(rbigint.fromint(_FORMAT_MINDIGITS))] - stringsize = _FORMAT_MINDIGITS - while pts[-1].lt(x): - pts.append(pts[-1].pow(two)) - stringsize *= 2 - pts.pop() # remove first base**2**i greater than x + pts = _parts_cache.get_cached_parts(base) + mindigits = _parts_cache.get_mindigits(base) + stringsize = mindigits + startindex = 0 + for startindex, part in enumerate(pts): + if not part.lt(x): + break + stringsize *= 2 # XXX can this overflow on 32 bit? + else: + # not enough parts computed yet + while pts[-1].lt(x): + pts.append(pts[-1].pow(two)) + stringsize *= 2 + + startindex = len(pts) - 1 + + # remove first base**2**i greater than x + startindex -= 1 output = StringBuilder(stringsize) if negative: output.append('-') output.append(prefix) - _format_recursive(x, len(pts)-1, output, pts, digits, output.getlength()) + if digits == BASE10: + _format_recursive( + x, startindex, output, pts, digits, output.getlength(), mindigits, + _format_int10) + else: + _format_recursive( + x, startindex, output, pts, digits, output.getlength(), mindigits, + _format_int_general) output.append(suffix) return output.build() + def _bitwise(a, op, b): # '&', '|', '^' """ Bitwise and/or/xor operations """ diff --git a/rpython/rlib/ropenssl.py b/rpython/rlib/ropenssl.py --- a/rpython/rlib/ropenssl.py +++ b/rpython/rlib/ropenssl.py @@ -93,6 +93,7 @@ SSL_RECEIVED_SHUTDOWN = rffi_platform.ConstantInteger( "SSL_RECEIVED_SHUTDOWN") SSL_MODE_AUTO_RETRY = rffi_platform.ConstantInteger("SSL_MODE_AUTO_RETRY") + SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = rffi_platform.ConstantInteger("SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER") NID_subject_alt_name = rffi_platform.ConstantInteger("NID_subject_alt_name") GEN_DIRNAME = rffi_platform.ConstantInteger("GEN_DIRNAME") diff --git a/rpython/rlib/test/test_rbigint.py b/rpython/rlib/test/test_rbigint.py --- a/rpython/rlib/test/test_rbigint.py +++ b/rpython/rlib/test/test_rbigint.py @@ -515,7 +515,19 @@ assert x.format('.!') == ( '-!....!!..!!..!.!!.!......!...!...!!!........!') assert x.format('abcdefghijkl', '<<', '>>') == '-<<cakdkgdijffjf>>' - + + def test_format_caching(self): + big = rbigint.fromlong(2 ** 1000) + res1 = big.str() + oldpow = rbigint.__dict__['pow'] + rbigint.pow = None + # make sure pow is not used the second time + try: + res2 = big.str() + assert res2 == res1 + finally: + rbigint.pow = oldpow + def test_overzelous_assertion(self): a = rbigint.fromlong(-1<<10000) b = rbigint.fromlong(-1<<3000) diff --git a/rpython/rtyper/lltypesystem/rpbc.py b/rpython/rtyper/lltypesystem/rpbc.py --- a/rpython/rtyper/lltypesystem/rpbc.py +++ b/rpython/rtyper/lltypesystem/rpbc.py @@ -1,25 +1,20 @@ import types -import sys -from rpython.tool.pairtype import pairtype, pair -from rpython.annotator import model as annmodel -from rpython.annotator import description -from rpython.flowspace.model import Constant, Variable -from rpython.rtyper.lltypesystem.lltype import \ - typeOf, Void, ForwardReference, Struct, Bool, Char, \ - Ptr, malloc, nullptr, Array, Signed, FuncType -from rpython.rtyper.rmodel import Repr, TyperError, inputconst, inputdesc -from rpython.rtyper.rpbc import samesig,\ - commonbase, allattributenames, adjust_shape, \ - AbstractClassesPBCRepr, AbstractMethodsPBCRepr, OverriddenFunctionPBCRepr, \ - AbstractMultipleFrozenPBCRepr, MethodOfFrozenPBCRepr, \ - AbstractFunctionsPBCRepr, AbstractMultipleUnrelatedFrozenPBCRepr, \ - SingleFrozenPBCRepr, none_frozen_pbc_repr, get_concrete_calltable + +from rpython.annotator import description, model as annmodel +from rpython.rlib.debug import ll_assert +from rpython.rlib.unroll import unrolling_iterable +from rpython.rtyper import callparse from rpython.rtyper.lltypesystem import rclass, llmemory -from rpython.tool.sourcetools import has_varargs -from rpython.rlib.unroll import unrolling_iterable -from rpython.rlib.debug import ll_assert +from rpython.rtyper.lltypesystem.lltype import (typeOf, Void, ForwardReference, + Struct, Bool, Char, Ptr, malloc, nullptr, Array, Signed) +from rpython.rtyper.rmodel import Repr, TyperError, inputconst +from rpython.rtyper.rpbc import (AbstractClassesPBCRepr, AbstractMethodsPBCRepr, + OverriddenFunctionPBCRepr, AbstractMultipleFrozenPBCRepr, + AbstractFunctionsPBCRepr, AbstractMultipleUnrelatedFrozenPBCRepr, + SingleFrozenPBCRepr, MethodOfFrozenPBCRepr, none_frozen_pbc_repr, + get_concrete_calltable) +from rpython.tool.pairtype import pairtype -from rpython.rtyper import callparse def rtype_is_None(robj1, rnone2, hop, pos=0): if isinstance(robj1.lowleveltype, Ptr): @@ -41,6 +36,7 @@ else: raise TyperError('rtype_is_None of %r' % (robj1)) + # ____________________________________________________________ class MultipleFrozenPBCRepr(AbstractMultipleFrozenPBCRepr): @@ -67,7 +63,7 @@ mangled_name, r_value = self.fieldmap[attr] cmangledname = inputconst(Void, mangled_name) return llops.genop('getfield', [vpbc, cmangledname], - resulttype = r_value) + resulttype=r_value) class MultipleUnrelatedFrozenPBCRepr(AbstractMultipleUnrelatedFrozenPBCRepr): @@ -86,6 +82,7 @@ def null_instance(self): return llmemory.Address._defl() + class __extend__(pairtype(MultipleUnrelatedFrozenPBCRepr, MultipleUnrelatedFrozenPBCRepr), pairtype(MultipleUnrelatedFrozenPBCRepr, @@ -100,11 +97,13 @@ vlist = hop.inputargs(r, r) return hop.genop('adr_eq', vlist, resulttype=Bool) + class __extend__(pairtype(MultipleFrozenPBCRepr, MultipleUnrelatedFrozenPBCRepr)): def convert_from_to((robj1, robj2), v, llops): return llops.genop('cast_ptr_to_adr', [v], resulttype=llmemory.Address) + # ____________________________________________________________ class FunctionsPBCRepr(AbstractFunctionsPBCRepr): @@ -123,6 +122,7 @@ def get_specfunc_row(self, llop, v, c_rowname, resulttype): return llop.genop('getfield', [v, c_rowname], resulttype=resulttype) + class SmallFunctionSetPBCRepr(Repr): def __init__(self, rtyper, s_pbc): self.rtyper = rtyper @@ -252,15 +252,6 @@ return hop.genop('char_ne', [v1, inputconst(Char, '\000')], resulttype=Bool) -## def rtype_simple_call(self, hop): -## v_index = hop.inputarg(self, arg=0) -## v_ptr = hop.llops.convertvar(v_index, self, self.pointer_repr) -## hop2 = hop.copy() -## hop2.args_r[0] = self.pointer_repr -## hop2.args_v[0] = v_ptr -## return hop2.dispatch() - -## rtype_call_args = rtype_simple_call class __extend__(pairtype(SmallFunctionSetPBCRepr, FunctionsPBCRepr)): def convert_from_to((r_set, r_ptr), v, llops): @@ -273,6 +264,7 @@ return llops.genop('getarrayitem', [r_set.c_pointer_table, v_int], resulttype=r_ptr.lowleveltype) + def compression_function(r_set): if r_set._compression_function is None: table = [] @@ -280,6 +272,7 @@ table.append((chr(i), p)) last_c, last_p = table[-1] unroll_table = unrolling_iterable(table[:-1]) + def ll_compress(fnptr): for c, p in unroll_table: if fnptr == p: @@ -290,6 +283,7 @@ r_set._compression_function = ll_compress return r_set._compression_function + class __extend__(pairtype(FunctionsPBCRepr, SmallFunctionSetPBCRepr)): def convert_from_to((r_ptr, r_set), v, llops): if r_ptr.lowleveltype is Void: @@ -299,6 +293,7 @@ ll_compress = compression_function(r_set) return llops.gendirectcall(ll_compress, v) + def conversion_table(r_from, r_to): if r_to in r_from._conversion_tables: return r_from._conversion_tables[r_to] @@ -320,7 +315,6 @@ r_from._conversion_tables[r_to] = r return r -## myf = open('convlog.txt', 'w') class __extend__(pairtype(SmallFunctionSetPBCRepr, SmallFunctionSetPBCRepr)): def convert_from_to((r_from, r_to), v, llops): @@ -343,6 +337,7 @@ else: return v + class MethodsPBCRepr(AbstractMethodsPBCRepr): """Representation selected for a PBC of the form {func: classdef...}. It assumes that all the methods come from the same name in a base @@ -394,9 +389,12 @@ # no __init__ here, AbstractClassesPBCRepr.__init__ is good enough def _instantiate_runtime_class(self, hop, vtypeptr, r_instance): - from rpython.rtyper.lltypesystem.rbuiltin import ll_instantiate - v_inst1 = hop.gendirectcall(ll_instantiate, vtypeptr) - return hop.genop('cast_pointer', [v_inst1], resulttype = r_instance) + v_instantiate = hop.genop('getfield', [vtypeptr, hop.inputconst(Void, "instantiate")], resulttype=vtypeptr.concretetype.TO.instantiate) + possible_graphs = hop.inputconst(Void, + [desc.getclassdef(None).my_instantiate_graph for desc in self.s_pbc.descriptions] + ) + v_inst = hop.genop('indirect_call', [v_instantiate, possible_graphs], resulttype=vtypeptr.concretetype.TO.instantiate.TO.RESULT) + return hop.genop('cast_pointer', [v_inst], resulttype=r_instance) def getlowleveltype(self): return rclass.CLASSTYPE @@ -415,17 +413,3 @@ return 0 else: return cls.hash - -# ____________________________________________________________ - -##def rtype_call_memo(hop): -## memo_table = hop.args_v[0].value -## if memo_table.s_result.is_constant(): -## return hop.inputconst(hop.r_result, memo_table.s_result.const) -## fieldname = memo_table.fieldname -## assert hop.nb_args == 2, "XXX" - -## r_pbc = hop.args_r[1] -## assert isinstance(r_pbc, (MultipleFrozenPBCRepr, ClassesPBCRepr)) -## v_table, v_pbc = hop.inputargs(Void, r_pbc) -## return r_pbc.getfield(v_pbc, fieldname, hop.llops) diff --git a/rpython/translator/backendopt/inline.py b/rpython/translator/backendopt/inline.py --- a/rpython/translator/backendopt/inline.py +++ b/rpython/translator/backendopt/inline.py @@ -32,22 +32,22 @@ def collect_called_graphs(graph, translator, include_oosend=True): - graphs_or_something = {} + graphs_or_something = set() for block in graph.iterblocks(): for op in block.operations: if op.opname == "direct_call": graph = get_graph(op.args[0], translator) if graph is not None: - graphs_or_something[graph] = True + graphs_or_something.add(graph) else: - graphs_or_something[op.args[0]] = True + graphs_or_something.add(op.args[0]) if op.opname == "indirect_call": graphs = op.args[-1].value if graphs is None: - graphs_or_something[op.args[0]] = True + graphs_or_something.add(op.args[0]) else: for graph in graphs: - graphs_or_something[graph] = True + graphs_or_something.add(graph) if op.opname == 'oosend' and include_oosend: meth = get_meth_from_oosend(op) if hasattr(meth, 'graph'): @@ -56,7 +56,7 @@ key = CanRaise(meth._can_raise) else: key = op.args[0] - graphs_or_something[key] = True + graphs_or_something.add(key) return graphs_or_something def iter_callsites(graph, calling_what): _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit