Author: Ronan Lamy <[email protected]> Branch: var-in-Some Changeset: r73867:77ca6f4b2c85 Date: 2014-10-09 19:20 +0100 http://bitbucket.org/pypy/pypy/changeset/77ca6f4b2c85/
Log: hg merge default 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 @@ -12,3 +12,6 @@ Allocate by 4-byte chunks in rffi_platform, Skip testing objdump if it does not exist, and other small adjustments in own tests + +.. branch: rtyper-stuff +Small internal refactorings in the rtyper. diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst --- a/pypy/doc/windows.rst +++ b/pypy/doc/windows.rst @@ -37,6 +37,13 @@ using a 32 bit Python and vice versa. By default pypy is built using the Multi-threaded DLL (/MD) runtime environment. +If you wish to override this detection method to use a different compiler +(mingw or a different version of MSVC): + +* set up the PATH and other environment variables as needed +* set the `CC` environment variable to compiler exe to be used, + for a different version of MSVC `SET CC=cl.exe`. + **Note:** PyPy is currently not supported for 64 bit Python, and translation will fail in this case. @@ -264,7 +271,7 @@ Since hacking on PyPy means running tests, you will need a way to specify the mingw compiler when hacking (as opposed to translating). As of March 2012, --cc is not a valid option for pytest.py. However if you set an -environment variable CC to the compliter exe, testing will use it. +environment variable CC to the compiler exe, testing will use it. .. _`mingw32 build`: http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Automated%20Builds .. _`mingw64 build`: http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Automated%20Builds diff --git a/pypy/module/_socket/__init__.py b/pypy/module/_socket/__init__.py --- a/pypy/module/_socket/__init__.py +++ b/pypy/module/_socket/__init__.py @@ -17,8 +17,6 @@ def startup(self, space): from rpython.rlib.rsocket import rsocket_startup rsocket_startup() - from pypy.module._socket.interp_func import State - space.fromcache(State).startup(space) def buildloaders(cls): from rpython.rlib import rsocket diff --git a/pypy/module/_socket/interp_func.py b/pypy/module/_socket/interp_func.py --- a/pypy/module/_socket/interp_func.py +++ b/pypy/module/_socket/interp_func.py @@ -1,5 +1,6 @@ from rpython.rlib import rsocket from rpython.rlib.rsocket import SocketError, INVALID_SOCKET +from rpython.rlib.rarithmetic import intmask from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import unwrap_spec, WrappedDefault @@ -46,9 +47,8 @@ Return the true host name, a list of aliases, and a list of IP addresses, for a host. The host argument is a string giving a host name or IP number. """ - lock = space.fromcache(State).netdb_lock try: - res = rsocket.gethostbyname_ex(host, lock) + res = rsocket.gethostbyname_ex(host) except SocketError, e: raise converted_error(space, e) return common_wrapgethost(space, res) @@ -60,9 +60,8 @@ Return the true host name, a list of aliases, and a list of IP addresses, for a host. The host argument is a string giving a host name or IP number. """ - lock = space.fromcache(State).netdb_lock try: - res = rsocket.gethostbyaddr(host, lock) + res = rsocket.gethostbyaddr(host) except SocketError, e: raise converted_error(space, e) return common_wrapgethost(space, res) @@ -174,7 +173,7 @@ Convert a 16-bit integer from network to host byte order. """ - return space.wrap(rsocket.ntohs(x)) + return space.wrap(rsocket.ntohs(intmask(x))) @unwrap_spec(x="c_uint") def ntohl(space, x): @@ -190,7 +189,7 @@ Convert a 16-bit integer from host to network byte order. """ - return space.wrap(rsocket.htons(x)) + return space.wrap(rsocket.htons(intmask(x))) @unwrap_spec(x="c_uint") def htonl(space, x): @@ -319,10 +318,3 @@ raise OperationError(space.w_ValueError, space.wrap('Timeout value out of range')) rsocket.setdefaulttimeout(timeout) - -class State(object): - def __init__(self, space): - self.netdb_lock = None - - def startup(self, space): - self.netdb_lock = space.allocate_lock() diff --git a/pypy/module/_socket/interp_socket.py b/pypy/module/_socket/interp_socket.py --- a/pypy/module/_socket/interp_socket.py +++ b/pypy/module/_socket/interp_socket.py @@ -109,10 +109,11 @@ # XXX Hack to seperate rpython and pypy def make_ushort_port(space, port): + assert isinstance(port, int) if port < 0 or port > 0xffff: raise OperationError(space.w_OverflowError, space.wrap( "port must be 0-65535.")) - return rffi.cast(rffi.USHORT, port) + return port def make_unsigned_flowinfo(space, flowinfo): if flowinfo < 0 or flowinfo > 0xfffff: @@ -401,8 +402,10 @@ The value argument can either be an integer or a string. """ try: - optval = space.int_w(w_optval) - except: + optval = space.c_int_w(w_optval) + except OperationError, e: + if e.async(space): + raise optval = space.str_w(w_optval) try: self.sock.setsockopt(level, optname, optval) diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py --- a/pypy/module/_socket/test/test_sock_app.py +++ b/pypy/module/_socket/test/test_sock_app.py @@ -498,6 +498,13 @@ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) reuse = s.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) assert reuse == 0 + # + raises(TypeError, s.setsockopt, socket.SOL_SOCKET, + socket.SO_REUSEADDR, 2 ** 31) + raises(TypeError, s.setsockopt, socket.SOL_SOCKET, + socket.SO_REUSEADDR, 2 ** 32 + 1) + assert s.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) == 0 + # s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) reuse = s.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) assert reuse != 0 diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -116,6 +116,8 @@ validate_fd(fileno(fp)) return _feof(fp) +def is_valid_fp(fp): + return is_valid_fd(fileno(fp)) constant_names = """ Py_TPFLAGS_READY Py_TPFLAGS_READYING Py_TPFLAGS_HAVE_GETCHARBUFFER diff --git a/pypy/module/cpyext/eval.py b/pypy/module/cpyext/eval.py --- a/pypy/module/cpyext/eval.py +++ b/pypy/module/cpyext/eval.py @@ -3,7 +3,7 @@ from rpython.rtyper.lltypesystem import rffi, lltype from pypy.module.cpyext.api import ( cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, fread, feof, Py_ssize_tP, - cpython_struct) + cpython_struct, is_valid_fp) from pypy.module.cpyext.pyobject import PyObject, borrow_from from pypy.module.cpyext.pyerrors import PyErr_SetFromErrno from pypy.module.cpyext.funcobject import PyCodeObject @@ -154,6 +154,10 @@ source = "" filename = rffi.charp2str(filename) buf = lltype.malloc(rffi.CCHARP.TO, BUF_SIZE, flavor='raw') + if not is_valid_fp(fp): + lltype.free(buf, flavor='raw') + PyErr_SetFromErrno(space, space.w_IOError) + return None try: while True: count = fread(buf, 1, BUF_SIZE, fp) diff --git a/pypy/module/cpyext/test/test_eval.py b/pypy/module/cpyext/test/test_eval.py --- a/pypy/module/cpyext/test/test_eval.py +++ b/pypy/module/cpyext/test/test_eval.py @@ -89,12 +89,12 @@ rffi.free_charp(buf) assert 0 == run("42 * 43") - + assert -1 == run("4..3 * 43") - + assert api.PyErr_Occurred() api.PyErr_Clear() - + def test_run_string(self, space, api): def run(code, start, w_globals, w_locals): buf = rffi.str2charp(code) diff --git a/pypy/module/micronumpy/ctors.py b/pypy/module/micronumpy/ctors.py --- a/pypy/module/micronumpy/ctors.py +++ b/pypy/module/micronumpy/ctors.py @@ -3,7 +3,7 @@ from rpython.rlib.buffer import SubBuffer from rpython.rlib.rstring import strip_spaces from rpython.rtyper.lltypesystem import lltype, rffi -from pypy.module.micronumpy import descriptor, loop +from pypy.module.micronumpy import descriptor, loop, support from pypy.module.micronumpy.base import ( W_NDimArray, convert_to_array, W_NumpyObject) from pypy.module.micronumpy.converters import shape_converter @@ -134,6 +134,15 @@ if dtype.is_str_or_unicode() and dtype.elsize < 1: dtype = descriptor.variable_dtype(space, dtype.char + '1') shape = shape_converter(space, w_shape, dtype) + for dim in shape: + if dim < 0: + raise OperationError(space.w_ValueError, space.wrap( + "negative dimensions are not allowed")) + try: + support.product(shape) + except OverflowError: + raise OperationError(space.w_ValueError, space.wrap( + "array is too big.")) return W_NDimArray.from_shape(space, shape, dtype=dtype, zero=zero) def empty(space, w_shape, w_dtype=None, w_order=None): diff --git a/pypy/module/micronumpy/support.py b/pypy/module/micronumpy/support.py --- a/pypy/module/micronumpy/support.py +++ b/pypy/module/micronumpy/support.py @@ -1,5 +1,6 @@ from pypy.interpreter.error import OperationError, oefmt from rpython.rlib import jit +from rpython.rlib.rarithmetic import ovfcheck def issequence_w(space, w_obj): @@ -23,7 +24,7 @@ def product(s): i = 1 for x in s: - i *= x + i = ovfcheck(i * x) return i 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 @@ -384,6 +384,19 @@ assert zeros((), dtype='S').shape == () assert zeros((), dtype='S').dtype == '|S1' + def test_check_shape(self): + import numpy as np + for func in [np.zeros, np.empty]: + exc = raises(ValueError, func, [0, -1, 1], 'int8') + assert str(exc.value) == "negative dimensions are not allowed" + exc = raises(ValueError, func, [2, -1, 3], 'int8') + assert str(exc.value) == "negative dimensions are not allowed" + + exc = raises(ValueError, func, [975]*7, 'int8') + assert str(exc.value) == "array is too big." + exc = raises(ValueError, func, [26244]*5, 'int8') + assert str(exc.value) == "array is too big." + def test_empty_like(self): import numpy as np a = np.empty_like(np.zeros(())) diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py --- a/pypy/module/micronumpy/test/test_zjit.py +++ b/pypy/module/micronumpy/test/test_zjit.py @@ -599,8 +599,7 @@ 'float_mul': 2, 'getarrayitem_gc': 7, 'getarrayitem_gc_pure': 15, - 'getfield_gc': 8, - 'getfield_gc_pure': 44, + 'getfield_gc_pure': 52, 'guard_class': 4, 'guard_false': 14, 'guard_not_invalidated': 2, diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py b/pypy/module/pypyjit/test_pypy_c/test_call.py --- a/pypy/module/pypyjit/test_pypy_c/test_call.py +++ b/pypy/module/pypyjit/test_pypy_c/test_call.py @@ -85,9 +85,9 @@ p38 = call(ConstClass(_ll_0_threadlocalref_getter___), descr=<Callr . EF=1 OS=5>) p39 = getfield_gc(p38, descr=<FieldP pypy.interpreter.executioncontext.ExecutionContext.inst_topframeref .*>) i40 = force_token() - p41 = getfield_gc(p38, descr=<FieldP pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>) + p41 = getfield_gc_pure(p38, descr=<FieldP pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>) guard_value(p41, ConstPtr(ptr42), descr=...) - i42 = getfield_gc(p38, descr=<FieldU pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc .*>) + i42 = getfield_gc_pure(p38, descr=<FieldU pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc .*>) i43 = int_is_zero(i42) guard_true(i43, descr=...) i50 = force_token() @@ -447,9 +447,9 @@ p29 = call(ConstClass(_ll_0_threadlocalref_getter___), descr=<Callr . EF=1 OS=5>) p30 = getfield_gc(p29, descr=<FieldP pypy.interpreter.executioncontext.ExecutionContext.inst_topframeref .*>) p31 = force_token() - p32 = getfield_gc(p29, descr=<FieldP pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>) + p32 = getfield_gc_pure(p29, descr=<FieldP pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>) guard_value(p32, ConstPtr(ptr33), descr=...) - i34 = getfield_gc(p29, descr=<FieldU pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc .*>) + i34 = getfield_gc_pure(p29, descr=<FieldU pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc .*>) i35 = int_is_zero(i34) guard_true(i35, descr=...) p37 = getfield_gc(ConstPtr(ptr36), descr=<FieldP pypy.interpreter.nestedscope.Cell.inst_w_value .*>) diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -785,6 +785,7 @@ raise Exception("getfield_raw_r (without _pure) not supported") # if immut in (IR_QUASIIMMUTABLE, IR_QUASIIMMUTABLE_ARRAY): + op1.opname += "_pure" descr1 = self.cpu.fielddescrof( v_inst.concretetype.TO, quasiimmut.get_mutate_field_name(c_fieldname.value)) diff --git a/rpython/jit/codewriter/test/test_jtransform.py b/rpython/jit/codewriter/test/test_jtransform.py --- a/rpython/jit/codewriter/test/test_jtransform.py +++ b/rpython/jit/codewriter/test/test_jtransform.py @@ -1296,7 +1296,7 @@ assert op1.args[1] == ('fielddescr', STRUCT, 'inst_x') assert op1.args[2] == ('fielddescr', STRUCT, 'mutate_x') assert op1.result is None - assert op2.opname == 'getfield_gc_i' + assert op2.opname == 'getfield_gc_i_pure' assert len(op2.args) == 2 assert op2.args[0] == v_x assert op2.args[1] == ('fielddescr', STRUCT, 'inst_x') diff --git a/rpython/jit/metainterp/optimizeopt/heap.py b/rpython/jit/metainterp/optimizeopt/heap.py --- a/rpython/jit/metainterp/optimizeopt/heap.py +++ b/rpython/jit/metainterp/optimizeopt/heap.py @@ -6,6 +6,7 @@ from rpython.jit.metainterp.jitexc import JitException from rpython.jit.metainterp.optimizeopt.optimizer import Optimization, MODE_ARRAY, LEVEL_KNOWNCLASS, REMOVED from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method +from rpython.jit.metainterp.optimize import InvalidLoop from rpython.jit.metainterp.resoperation import rop, ResOperation from rpython.rlib.objectmodel import we_are_translated @@ -531,10 +532,14 @@ def optimize_QUASIIMMUT_FIELD(self, op): # Pattern: QUASIIMMUT_FIELD(s, descr=QuasiImmutDescr) - # x = GETFIELD_GC(s, descr='inst_x') - # If 's' is a constant (after optimizations), then we make 's.inst_x' - # a constant too, and we rely on the rest of the optimizations to - # constant-fold the following getfield_gc. + # x = GETFIELD_GC_PURE(s, descr='inst_x') + # If 's' is a constant (after optimizations) we rely on the rest of the + # optimizations to constant-fold the following getfield_gc_pure. + # in addition, we record the dependency here to make invalidation work + # correctly. + # NB: emitting the GETFIELD_GC_PURE is only safe because the + # QUASIIMMUT_FIELD is also emitted to make sure the dependency is + # registered. structvalue = self.getvalue(op.getarg(0)) if not structvalue.is_constant(): self._remove_guard_not_invalidated = True @@ -544,21 +549,14 @@ qmutdescr = op.getdescr() assert isinstance(qmutdescr, QuasiImmutDescr) # check that the value is still correct; it could have changed - # already between the tracing and now. In this case, we are - # simply ignoring the QUASIIMMUT_FIELD hint and compiling it - # as a regular getfield. + # already between the tracing and now. In this case, we mark the loop + # as invalid if not qmutdescr.is_still_valid_for(structvalue.get_key_box()): - self._remove_guard_not_invalidated = True - return + raise InvalidLoop('quasi immutable field changed during tracing') # record as an out-of-line guard if self.optimizer.quasi_immutable_deps is None: self.optimizer.quasi_immutable_deps = {} self.optimizer.quasi_immutable_deps[qmutdescr.qmut] = None - # perform the replacement in the list of operations - fieldvalue = self.getvalue(qmutdescr.constantfieldbox) - cf = self.field_cache(qmutdescr.fielddescr) - cf.force_lazy_setfield(self) - cf.remember_field_value(structvalue, fieldvalue) self._remove_guard_not_invalidated = False def optimize_GUARD_NOT_INVALIDATED(self, op): diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py @@ -5200,7 +5200,7 @@ [] quasiimmut_field(ConstPtr(quasiptr), descr=quasiimmutdescr) guard_not_invalidated() [] - i0 = getfield_gc(ConstPtr(quasiptr), descr=quasifielddescr) + i0 = getfield_gc_pure(ConstPtr(quasiptr), descr=quasifielddescr) i1 = call_pure(123, i0, descr=nonwritedescr) finish(i1) """ diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -6893,13 +6893,13 @@ [p0, p1, i0] quasiimmut_field(p0, descr=quasiimmutdescr) guard_not_invalidated() [] - i1 = getfield_gc(p0, descr=quasifielddescr) + i1 = getfield_gc_pure(p0, descr=quasifielddescr) escape(i1) jump(p1, p0, i1) """ expected = """ [p0, p1, i0] - i1 = getfield_gc(p0, descr=quasifielddescr) + i1 = getfield_gc_pure(p0, descr=quasifielddescr) escape(i1) jump(p1, p0, i1) """ @@ -6910,7 +6910,7 @@ [] quasiimmut_field(ConstPtr(quasiptr), descr=quasiimmutdescr) guard_not_invalidated() [] - i1 = getfield_gc(ConstPtr(quasiptr), descr=quasifielddescr) + i1 = getfield_gc_pure(ConstPtr(quasiptr), descr=quasifielddescr) escape(i1) jump() """ @@ -6962,11 +6962,11 @@ [i0a, i0b] quasiimmut_field(ConstPtr(quasiptr), descr=quasiimmutdescr) guard_not_invalidated() [] - i1 = getfield_gc(ConstPtr(quasiptr), descr=quasifielddescr) + i1 = getfield_gc_pure(ConstPtr(quasiptr), descr=quasifielddescr) call_may_force(i0b, descr=mayforcevirtdescr) quasiimmut_field(ConstPtr(quasiptr), descr=quasiimmutdescr) guard_not_invalidated() [] - i2 = getfield_gc(ConstPtr(quasiptr), descr=quasifielddescr) + i2 = getfield_gc_pure(ConstPtr(quasiptr), descr=quasifielddescr) i3 = escape(i1) i4 = escape(i2) jump(i3, i4) @@ -6989,11 +6989,11 @@ setfield_gc(p, 421, descr=quasifielddescr) quasiimmut_field(p, descr=quasiimmutdescr) guard_not_invalidated() [] - i1 = getfield_gc(p, descr=quasifielddescr) + i1 = getfield_gc_pure(p, descr=quasifielddescr) call_may_force(i0b, descr=mayforcevirtdescr) quasiimmut_field(p, descr=quasiimmutdescr) guard_not_invalidated() [] - i2 = getfield_gc(p, descr=quasifielddescr) + i2 = getfield_gc_pure(p, descr=quasifielddescr) i3 = escape(i1) i4 = escape(i2) jump(i3, i4) @@ -8242,7 +8242,7 @@ quasiimmut_field(p69, descr=quasiimmutdescr) guard_not_invalidated() [] - p71 = getfield_gc(p69, descr=quasifielddescr) # inst_code + p71 = getfield_gc_pure(p69, descr=quasifielddescr) # inst_code guard_value(p71, -4247) [] p106 = new_with_vtable(ConstClass(node_vtable)) @@ -8253,30 +8253,18 @@ setfield_gc(p106, p108, descr=nextdescr) # inst_storage jump(p106) """ - expected = """ - [] - p72 = getfield_gc(ConstPtr(myptr2), descr=quasifielddescr) - guard_value(p72, -4247) [] - jump() - """ - self.optimize_loop(ops, expected) + self.raises(InvalidLoop, self.optimize_loop, ops, ops) def test_issue1080_infinitie_loop_simple(self): ops = """ [p69] quasiimmut_field(p69, descr=quasiimmutdescr) guard_not_invalidated() [] - p71 = getfield_gc(p69, descr=quasifielddescr) # inst_code + p71 = getfield_gc_pure(p69, descr=quasifielddescr) # inst_code guard_value(p71, -4247) [] jump(ConstPtr(myptr)) """ - expected = """ - [] - p72 = getfield_gc(ConstPtr(myptr), descr=quasifielddescr) - guard_value(p72, -4247) [] - jump() - """ - self.optimize_loop(ops, expected) + self.raises(InvalidLoop, self.optimize_loop, ops, ops) def test_only_strengthen_guard_if_class_matches(self): ops = """ diff --git a/rpython/jit/metainterp/test/test_quasiimmut.py b/rpython/jit/metainterp/test/test_quasiimmut.py --- a/rpython/jit/metainterp/test/test_quasiimmut.py +++ b/rpython/jit/metainterp/test/test_quasiimmut.py @@ -81,6 +81,27 @@ assert len(loop.quasi_immutable_deps) == 1 assert isinstance(loop.quasi_immutable_deps.keys()[0], QuasiImmut) + def test_simple_optimize_during_tracing(self): + myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total']) + class Foo: + _immutable_fields_ = ['a?'] + def __init__(self, a): + self.a = a + def f(a, x): + foo = Foo(a) + total = 0 + while x > 0: + myjitdriver.jit_merge_point(foo=foo, x=x, total=total) + # read a quasi-immutable field out of a Constant + total += foo.a + x -= 1 + return total + # + res = self.meta_interp(f, [100, 7], enable_opts="") + assert res == 700 + # there should be no getfields, even though optimizations are turned off + self.check_resops(guard_not_invalidated=1, getfield_gc=0) + def test_nonopt_1(self): myjitdriver = JitDriver(greens=[], reds=['x', 'total', 'lst']) class Foo: @@ -102,7 +123,7 @@ assert f(100, 7) == 721 res = self.meta_interp(f, [100, 7]) assert res == 721 - self.check_resops(guard_not_invalidated=0, getfield_gc=3) + self.check_resops(guard_not_invalidated=0, getfield_gc=1, getfield_gc_pure=2) # from rpython.jit.metainterp.warmspot import get_stats loops = get_stats().loops @@ -154,11 +175,12 @@ residual_call(foo) x -= 1 return total - # + assert f(100, 7) == 721 res = self.meta_interp(f, [100, 7]) assert res == 721 - self.check_resops(guard_not_invalidated=0, getfield_gc=2) + # the loop is invalid, so nothing is traced + self.check_aborted_count(2) def test_change_during_tracing_2(self): myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total']) @@ -184,7 +206,7 @@ assert f(100, 7) == 700 res = self.meta_interp(f, [100, 7]) assert res == 700 - self.check_resops(guard_not_invalidated=0, getfield_gc=2) + self.check_resops(guard_not_invalidated=0, getfield_gc=0) def test_change_invalidate_reentering(self): myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total']) @@ -347,7 +369,7 @@ res = self.meta_interp(f, [100, 7]) assert res == 700 self.check_resops(getarrayitem_gc_pure=0, guard_not_invalidated=2, - getarrayitem_gc=0, getfield_gc=0) + getarrayitem_gc=0, getfield_gc=0, getfield_gc_pure=0) # from rpython.jit.metainterp.warmspot import get_stats loops = get_stats().loops @@ -355,6 +377,30 @@ assert len(loop.quasi_immutable_deps) == 1 assert isinstance(loop.quasi_immutable_deps.keys()[0], QuasiImmut) + def test_list_optimized_while_tracing(self): + myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total']) + class Foo: + _immutable_fields_ = ['lst?[*]'] + def __init__(self, lst): + self.lst = lst + def f(a, x): + lst1 = [0, 0] + lst1[1] = a + foo = Foo(lst1) + total = 0 + while x > 0: + myjitdriver.jit_merge_point(foo=foo, x=x, total=total) + # read a quasi-immutable field out of a Constant + total += foo.lst[1] + x -= 1 + return total + # + res = self.meta_interp(f, [100, 7], enable_opts="") + assert res == 700 + # operations must have been removed by the frontend + self.check_resops(getarrayitem_gc_pure=0, guard_not_invalidated=1, + getarrayitem_gc=0, getfield_gc=0, getfield_gc_pure=0) + def test_list_length_1(self): myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total']) class Foo: diff --git a/rpython/rlib/_stacklet_n_a.py b/rpython/rlib/_stacklet_n_a.py --- a/rpython/rlib/_stacklet_n_a.py +++ b/rpython/rlib/_stacklet_n_a.py @@ -1,33 +1,35 @@ from rpython.rlib import _rffi_stacklet as _c -from rpython.rlib import objectmodel, debug +from rpython.rlib import debug +from rpython.rlib.objectmodel import we_are_translated, specialize from rpython.rtyper.annlowlevel import llhelper -from rpython.tool.staticmethods import StaticMethods -class StackletGcRootFinder: - __metaclass__ = StaticMethods - +class StackletGcRootFinder(object): + @staticmethod + @specialize.arg(1) def new(thrd, callback, arg): h = _c.new(thrd._thrd, llhelper(_c.run_fn, callback), arg) if not h: raise MemoryError return h - new._annspecialcase_ = 'specialize:arg(1)' + @staticmethod def switch(h): h = _c.switch(h) if not h: raise MemoryError return h + @staticmethod def destroy(thrd, h): _c.destroy(thrd._thrd, h) - if objectmodel.we_are_translated(): + if we_are_translated(): debug.debug_print("not using a framework GC: " "stacklet_destroy() may leak") - is_empty_handle = _c.is_empty_handle + is_empty_handle = staticmethod(_c.is_empty_handle) + @staticmethod def get_null_handle(): return _c.null_handle diff --git a/rpython/rlib/_stacklet_shadowstack.py b/rpython/rlib/_stacklet_shadowstack.py --- a/rpython/rlib/_stacklet_shadowstack.py +++ b/rpython/rlib/_stacklet_shadowstack.py @@ -3,7 +3,6 @@ from rpython.rtyper.annlowlevel import llhelper from rpython.rtyper.lltypesystem import lltype, llmemory from rpython.rtyper.lltypesystem.lloperation import llop -from rpython.tool.staticmethods import StaticMethods NULL_SUSPSTACK = lltype.nullptr(llmemory.GCREF.TO) @@ -68,9 +67,7 @@ return oldsuspstack -class StackletGcRootFinder: - __metaclass__ = StaticMethods - +class StackletGcRootFinder(object): def new(thrd, callback, arg): gcrootfinder.callback = callback thread_handle = thrd._thrd @@ -78,6 +75,7 @@ h = _c.new(thread_handle, llhelper(_c.run_fn, _new_callback), arg) return get_result_suspstack(h) new._dont_inline_ = True + new = staticmethod(new) def switch(suspstack): # suspstack has a handle to target, i.e. where to switch to @@ -90,10 +88,13 @@ h = _c.switch(h) return get_result_suspstack(h) switch._dont_inline_ = True + switch = staticmethod(switch) + @staticmethod def is_empty_handle(suspstack): return not suspstack + @staticmethod def get_null_handle(): return NULL_SUSPSTACK diff --git a/rpython/rlib/rmmap.py b/rpython/rlib/rmmap.py --- a/rpython/rlib/rmmap.py +++ b/rpython/rlib/rmmap.py @@ -134,8 +134,8 @@ if _CYGWIN: # XXX: macro=True hack for newer versions of Cygwin (as of 12/2012) - c_malloc, _ = external('malloc', [size_t], PTR, macro=True) - c_free, _ = external('free', [PTR], lltype.Void, macro=True) + _, c_malloc_safe = external('malloc', [size_t], PTR, macro=True) + _, c_free_safe = external('free', [PTR], lltype.Void, macro=True) c_memmove, _ = external('memmove', [PTR, PTR, size_t], lltype.Void) @@ -709,7 +709,7 @@ # XXX: JIT memory should be using mmap MAP_PRIVATE with # PROT_EXEC but Cygwin's fork() fails. mprotect() # cannot be used, but seems to be unnecessary there. - res = c_malloc(map_size) + res = c_malloc_safe(map_size) if res == rffi.cast(PTR, 0): raise MemoryError return res @@ -726,7 +726,7 @@ alloc._annenforceargs_ = (int,) if _CYGWIN: - free = c_free + free = c_free_safe else: free = c_munmap_safe diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py --- a/rpython/rlib/rsocket.py +++ b/rpython/rlib/rsocket.py @@ -18,9 +18,10 @@ from rpython.rlib import _rsocket_rffi as _c, jit, rgc from rpython.rlib.objectmodel import instantiate, keepalive_until_here from rpython.rlib.rarithmetic import intmask, r_uint -from rpython.rlib.rthread import dummy_lock +from rpython.rlib import rthread from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rtyper.lltypesystem.rffi import sizeof, offsetof +from rpython.rtyper.extregistry import ExtRegistryEntry # Usage of @jit.dont_look_inside in this file is possibly temporary @@ -51,6 +52,7 @@ def ntohs(x): + assert isinstance(x, int) return rffi.cast(lltype.Signed, _c.ntohs(x)) def ntohl(x): @@ -58,6 +60,7 @@ return rffi.cast(lltype.Unsigned, _c.ntohl(x)) def htons(x): + assert isinstance(x, int) return rffi.cast(lltype.Signed, _c.htons(x)) def htonl(x): @@ -220,7 +223,6 @@ def get_protocol(self): a = self.lock(_c.sockaddr_ll) proto = rffi.getintfield(a, 'c_sll_protocol') - proto = rffi.cast(rffi.USHORT, proto) res = ntohs(proto) self.unlock() return res @@ -256,7 +258,6 @@ def __init__(self, host, port): makeipaddr(host, self) a = self.lock(_c.sockaddr_in) - port = rffi.cast(rffi.USHORT, port) rffi.setintfield(a, 'c_sin_port', htons(port)) self.unlock() @@ -268,7 +269,7 @@ def get_port(self): a = self.lock(_c.sockaddr_in) - port = ntohs(a.c_sin_port) + port = ntohs(rffi.getintfield(a, 'c_sin_port')) self.unlock() return port @@ -321,7 +322,7 @@ def get_port(self): a = self.lock(_c.sockaddr_in6) - port = ntohs(a.c_sin6_port) + port = ntohs(rffi.getintfield(a, 'c_sin6_port')) self.unlock() return port @@ -1135,18 +1136,18 @@ paddr = h_addr_list[i] return (rffi.charp2str(hostent.c_h_name), aliases, address_list) -def gethostbyname_ex(name, lock=dummy_lock): +def gethostbyname_ex(name): # XXX use gethostbyname_r() if available instead of locks addr = gethostbyname(name) - with lock: + with _get_netdb_lock(): hostent = _c.gethostbyname(name) return gethost_common(name, hostent, addr) -def gethostbyaddr(ip, lock=dummy_lock): +def gethostbyaddr(ip): # XXX use gethostbyaddr_r() if available, instead of locks addr = makeipaddr(ip) assert isinstance(addr, IPAddress) - with lock: + with _get_netdb_lock(): p, size = addr.lock_in_addr() try: hostent = _c.gethostbyaddr(p, size, addr.family) @@ -1154,6 +1155,36 @@ addr.unlock() return gethost_common(ip, hostent, addr) +# RPython magic to make _netdb_lock turn either into a regular +# rthread.Lock or a rthread.DummyLock, depending on the config +def _get_netdb_lock(): + return rthread.dummy_lock + +class _Entry(ExtRegistryEntry): + _about_ = _get_netdb_lock + + def compute_annotation(self): + config = self.bookkeeper.annotator.translator.config + if config.translation.thread: + fn = _get_netdb_lock_thread + else: + fn = _get_netdb_lock_nothread + return self.bookkeeper.immutablevalue(fn) + +def _get_netdb_lock_nothread(): + return rthread.dummy_lock + +class _LockCache(object): + lock = None +_lock_cache = _LockCache() + [email protected] +def _get_netdb_lock_thread(): + if _lock_cache.lock is None: + _lock_cache.lock = rthread.allocate_lock() + return _lock_cache.lock +# done RPython magic + def getaddrinfo(host, port_or_service, family=AF_UNSPEC, socktype=0, proto=0, flags=0, address_to_fill=None): @@ -1201,13 +1232,13 @@ servent = _c.getservbyname(name, proto) if not servent: raise RSocketError("service/proto not found") - port = rffi.cast(rffi.UINT, servent.c_s_port) + port = rffi.getintfield(servent, 'c_s_port') return ntohs(port) def getservbyport(port, proto=None): # This function is only called from pypy/module/_socket and the range of # port is checked there - port = rffi.cast(rffi.USHORT, port) + assert isinstance(port, int) servent = _c.getservbyport(htons(port), proto) if not servent: raise RSocketError("port/proto not found") diff --git a/rpython/rlib/runicode.py b/rpython/rlib/runicode.py --- a/rpython/rlib/runicode.py +++ b/rpython/rlib/runicode.py @@ -8,8 +8,10 @@ if rffi.sizeof(lltype.UniChar) == 4: MAXUNICODE = 0x10ffff + allow_surrogate_by_default = False else: MAXUNICODE = 0xffff + allow_surrogate_by_default = True BYTEORDER = sys.byteorder @@ -122,7 +124,7 @@ ] def str_decode_utf_8(s, size, errors, final=False, - errorhandler=None, allow_surrogates=False): + errorhandler=None, allow_surrogates=allow_surrogate_by_default): if errorhandler is None: errorhandler = default_unicode_error_decode result = UnicodeBuilder(size) @@ -304,7 +306,7 @@ result.append((chr((0x80 | (ch & 0x3f))))) def unicode_encode_utf_8(s, size, errors, errorhandler=None, - allow_surrogates=False): + allow_surrogates=allow_surrogate_by_default): if errorhandler is None: errorhandler = default_unicode_error_encode return unicode_encode_utf_8_impl(s, size, errors, errorhandler, diff --git a/rpython/rlib/test/test_rsocket.py b/rpython/rlib/test/test_rsocket.py --- a/rpython/rlib/test/test_rsocket.py +++ b/rpython/rlib/test/test_rsocket.py @@ -2,6 +2,7 @@ from rpython.rlib import rsocket from rpython.rlib.rsocket import * import socket as cpy_socket +from rpython.translator.c.test.test_genc import compile def setup_module(mod): @@ -570,4 +571,17 @@ for i in range(nthreads): threads[i].join() assert sum(result) == nthreads - + +def test_translate_netdb_lock(): + def f(): + gethostbyaddr("localhost") + return 0 + fc = compile(f, []) + assert fc() == 0 + +def test_translate_netdb_lock_thread(): + def f(): + gethostbyaddr("localhost") + return 0 + fc = compile(f, [], thread=True) + assert fc() == 0 diff --git a/rpython/rtyper/lltypesystem/lltype.py b/rpython/rtyper/lltypesystem/lltype.py --- a/rpython/rtyper/lltypesystem/lltype.py +++ b/rpython/rtyper/lltypesystem/lltype.py @@ -191,6 +191,11 @@ def _is_varsize(self): return False + def _contains_value(self, value): + if self is Void: + return True + return isCompatibleType(typeOf(value), self) + NFOUND = object() class ContainerType(LowLevelType): diff --git a/rpython/rtyper/lltypesystem/rbytearray.py b/rpython/rtyper/lltypesystem/rbytearray.py --- a/rpython/rtyper/lltypesystem/rbytearray.py +++ b/rpython/rtyper/lltypesystem/rbytearray.py @@ -38,12 +38,14 @@ i += s.length() cls.ll_strsetitem_nonneg(s, i, item) + @staticmethod def ll_strsetitem_nonneg(s, i, item): chars = s.chars ll_assert(i >= 0, "negative str getitem index") ll_assert(i < len(chars), "str getitem index out of bound") chars[i] = chr(item) + @staticmethod def ll_stritem_nonneg(s, i): return ord(rstr.LLHelpers.ll_stritem_nonneg(s, i)) diff --git a/rpython/rtyper/lltypesystem/rstr.py b/rpython/rtyper/lltypesystem/rstr.py --- a/rpython/rtyper/lltypesystem/rstr.py +++ b/rpython/rtyper/lltypesystem/rstr.py @@ -270,6 +270,7 @@ class LLHelpers(AbstractLLHelpers): from rpython.rtyper.annlowlevel import llstr, llunicode + @staticmethod @jit.elidable def ll_str_mul(s, times): if times < 0: @@ -292,6 +293,7 @@ i += j return newstr + @staticmethod @jit.elidable def ll_char_mul(ch, times): if typeOf(ch) is Char: @@ -308,9 +310,11 @@ j += 1 return newstr + @staticmethod def ll_strlen(s): return len(s.chars) + @staticmethod @signature(types.any(), types.int(), returns=types.any()) def ll_stritem_nonneg(s, i): chars = s.chars @@ -318,6 +322,7 @@ ll_assert(i < len(chars), "str getitem index out of bound") return chars[i] + @staticmethod def ll_chr2str(ch): if typeOf(ch) is Char: malloc = mallocstr @@ -328,6 +333,7 @@ return s # @jit.look_inside_iff(lambda str: jit.isconstant(len(str.chars)) and len(str.chars) == 1) + @staticmethod @jit.oopspec("str.str2unicode(str)") def ll_str2unicode(str): lgt = len(str.chars) @@ -338,6 +344,7 @@ s.chars[i] = cast_primitive(UniChar, str.chars[i]) return s + @staticmethod def ll_str2bytearray(str): from rpython.rtyper.lltypesystem.rbytearray import BYTEARRAY @@ -347,6 +354,7 @@ b.chars[i] = str.chars[i] return b + @staticmethod @jit.elidable def ll_strhash(s): # unlike CPython, there is no reason to avoid to return -1 @@ -362,13 +370,17 @@ s.hash = x return x + @staticmethod def ll_length(s): return len(s.chars) + @staticmethod def ll_strfasthash(s): return s.hash # assumes that the hash is already computed + @staticmethod @jit.elidable + @jit.oopspec('stroruni.concat(s1, s2)') def ll_strconcat(s1, s2): len1 = s1.length() len2 = s2.length() @@ -386,8 +398,8 @@ else: newstr.copy_contents(s2, newstr, 0, len1, len2) return newstr - ll_strconcat.oopspec = 'stroruni.concat(s1, s2)' + @staticmethod @jit.elidable def ll_strip(s, ch, left, right): s_len = len(s.chars) @@ -408,6 +420,7 @@ s.copy_contents(s, result, lpos, 0, r_len) return result + @staticmethod @jit.elidable def ll_strip_default(s, left, right): s_len = len(s.chars) @@ -428,6 +441,7 @@ s.copy_contents(s, result, lpos, 0, r_len) return result + @staticmethod @jit.elidable def ll_strip_multiple(s, s2, left, right): s_len = len(s.chars) @@ -448,6 +462,7 @@ s.copy_contents(s, result, lpos, 0, r_len) return result + @staticmethod @jit.elidable def ll_upper(s): s_chars = s.chars @@ -462,6 +477,7 @@ i += 1 return result + @staticmethod @jit.elidable def ll_lower(s): s_chars = s.chars @@ -476,6 +492,7 @@ i += 1 return result + @staticmethod def ll_join(s, length, items): s_chars = s.chars s_len = len(s_chars) @@ -509,7 +526,9 @@ i += 1 return result + @staticmethod @jit.elidable + @jit.oopspec('stroruni.cmp(s1, s2)') def ll_strcmp(s1, s2): if not s1 and not s2: return True @@ -531,9 +550,10 @@ return diff i += 1 return len1 - len2 - ll_strcmp.oopspec = 'stroruni.cmp(s1, s2)' + @staticmethod @jit.elidable + @jit.oopspec('stroruni.equal(s1, s2)') def ll_streq(s1, s2): if s1 == s2: # also if both are NULLs return True @@ -551,8 +571,8 @@ return False j += 1 return True - ll_streq.oopspec = 'stroruni.equal(s1, s2)' + @staticmethod @jit.elidable def ll_startswith(s1, s2): len1 = len(s1.chars) @@ -569,11 +589,13 @@ return True + @staticmethod def ll_startswith_char(s, ch): if not len(s.chars): return False return s.chars[0] == ch + @staticmethod @jit.elidable def ll_endswith(s1, s2): len1 = len(s1.chars) @@ -591,11 +613,13 @@ return True + @staticmethod def ll_endswith_char(s, ch): if not len(s.chars): return False return s.chars[len(s.chars) - 1] == ch + @staticmethod @jit.elidable @signature(types.any(), types.any(), types.int(), types.int(), returns=types.int()) def ll_find_char(s, ch, start, end): @@ -608,6 +632,7 @@ i += 1 return -1 + @staticmethod @jit.elidable def ll_rfind_char(s, ch, start, end): if end > len(s.chars): @@ -619,6 +644,7 @@ return i return -1 + @staticmethod @jit.elidable def ll_count_char(s, ch, start, end): count = 0 @@ -631,6 +657,7 @@ i += 1 return count + @staticmethod @signature(types.any(), types.any(), types.int(), types.int(), returns=types.int()) def ll_find(s1, s2, start, end): if start < 0: @@ -646,6 +673,7 @@ return LLHelpers.ll_search(s1, s2, start, end, FAST_FIND) + @staticmethod @signature(types.any(), types.any(), types.int(), types.int(), returns=types.int()) def ll_rfind(s1, s2, start, end): if start < 0: @@ -681,6 +709,7 @@ res = 0 return res + @staticmethod @jit.elidable def ll_search(s1, s2, start, end, mode): count = 0 @@ -768,6 +797,7 @@ return -1 return count + @staticmethod @signature(types.int(), types.any(), returns=types.any()) @jit.look_inside_iff(lambda length, items: jit.loop_unrolling_heuristic( items, length)) @@ -802,6 +832,7 @@ i += 1 return result + @staticmethod @jit.look_inside_iff(lambda length, chars, RES: jit.isconstant(length) and jit.isvirtual(chars)) def ll_join_chars(length, chars, RES): # no need to optimize this, will be replaced by string builder @@ -821,6 +852,7 @@ i += 1 return result + @staticmethod @jit.oopspec('stroruni.slice(s1, start, stop)') @signature(types.any(), types.int(), types.int(), returns=types.any()) @jit.elidable @@ -836,9 +868,11 @@ s1.copy_contents(s1, newstr, start, 0, lgt) return newstr + @staticmethod def ll_stringslice_startonly(s1, start): return LLHelpers._ll_stringslice(s1, start, len(s1.chars)) + @staticmethod @signature(types.any(), types.int(), types.int(), returns=types.any()) def ll_stringslice_startstop(s1, start, stop): if jit.we_are_jitted(): @@ -851,10 +885,12 @@ stop = len(s1.chars) return LLHelpers._ll_stringslice(s1, start, stop) + @staticmethod def ll_stringslice_minusone(s1): newlen = len(s1.chars) - 1 return LLHelpers._ll_stringslice(s1, 0, newlen) + @staticmethod def ll_split_chr(LIST, s, c, max): chars = s.chars strlen = len(chars) @@ -889,6 +925,7 @@ item.copy_contents(s, item, i, 0, j - i) return res + @staticmethod def ll_split(LIST, s, c, max): count = 1 if max == -1: @@ -920,6 +957,7 @@ item.copy_contents(s, item, prev_pos, 0, last - prev_pos) return res + @staticmethod def ll_rsplit_chr(LIST, s, c, max): chars = s.chars strlen = len(chars) @@ -955,6 +993,7 @@ item.copy_contents(s, item, j, 0, i - j) return res + @staticmethod def ll_rsplit(LIST, s, c, max): count = 1 if max == -1: @@ -986,6 +1025,7 @@ item.copy_contents(s, item, 0, 0, prev_pos) return res + @staticmethod @jit.elidable def ll_replace_chr_chr(s, c1, c2): length = len(s.chars) @@ -1001,6 +1041,7 @@ j += 1 return newstr + @staticmethod @jit.elidable def ll_contains(s, c): chars = s.chars @@ -1012,6 +1053,7 @@ i += 1 return False + @staticmethod @jit.elidable def ll_int(s, base): if not 2 <= base <= 36: @@ -1068,23 +1110,29 @@ # ll_build_push(x, next_string, n-1) # s = ll_build_finish(x) + @staticmethod def ll_build_start(parts_count): return malloc(TEMP, parts_count) + @staticmethod def ll_build_push(builder, next_string, index): builder[index] = next_string + @staticmethod def ll_build_finish(builder): return LLHelpers.ll_join_strs(len(builder), builder) + @staticmethod @specialize.memo() def ll_constant(s): return string_repr.convert_const(s) + @staticmethod @specialize.memo() def ll_constant_unicode(s): return unicode_repr.convert_const(s) + @classmethod def do_stringformat(cls, hop, sourcevarsrepr): s_str = hop.args_s[0] assert s_str.is_constant() @@ -1150,8 +1198,8 @@ hop.exception_cannot_occur() # to ignore the ZeroDivisionError of '%' return hop.gendirectcall(cls.ll_join_strs, size, vtemp) - do_stringformat = classmethod(do_stringformat) + @staticmethod @jit.dont_look_inside def ll_string2list(RESLIST, src): length = len(src.chars) diff --git a/rpython/rtyper/rmodel.py b/rpython/rtyper/rmodel.py --- a/rpython/rtyper/rmodel.py +++ b/rpython/rtyper/rmodel.py @@ -2,8 +2,7 @@ from rpython.flowspace.model import Constant from rpython.rtyper.error import TyperError, MissingRTypeOperation from rpython.rtyper.lltypesystem import lltype -from rpython.rtyper.lltypesystem.lltype import (Void, Bool, typeOf, - LowLevelType, isCompatibleType) +from rpython.rtyper.lltypesystem.lltype import Void, Bool, LowLevelType from rpython.tool.pairtype import pairtype, extendabletype, pair @@ -120,14 +119,9 @@ def convert_const(self, value): "Convert the given constant value to the low-level repr of 'self'." - if self.lowleveltype is not Void: - try: - realtype = typeOf(value) - except (AssertionError, AttributeError, TypeError): - realtype = '???' - if realtype != self.lowleveltype: - raise TyperError("convert_const(self = %r, value = %r)" % ( - self, value)) + if not self.lowleveltype._contains_value(value): + raise TyperError("convert_const(self = %r, value = %r)" % ( + self, value)) return value def get_ll_eq_function(self): @@ -356,18 +350,9 @@ lltype = reqtype else: raise TypeError(repr(reqtype)) - # Void Constants can hold any value; - # non-Void Constants must hold a correctly ll-typed value - if lltype is not Void: - try: - realtype = typeOf(value) - except (AssertionError, AttributeError): - realtype = '???' - if not isCompatibleType(realtype, lltype): - raise TyperError("inputconst(reqtype = %s, value = %s):\n" - "expected a %r,\n" - " got a %r" % (reqtype, value, - lltype, realtype)) + if not lltype._contains_value(value): + raise TyperError("inputconst(): expected a %r, got %r" % + (lltype, value)) c = Constant(value) c.concretetype = lltype return c @@ -422,7 +407,8 @@ def __ne__(self, other): return not (self == other) - def build_ll_dummy_value(self): + @property + def ll_dummy_value(self): TYPE = self.TYPE try: return self.rtyper.cache_dummy_values[TYPE] @@ -435,8 +421,6 @@ self.rtyper.cache_dummy_values[TYPE] = p return p - ll_dummy_value = property(build_ll_dummy_value) - # logging/warning diff --git a/rpython/rtyper/rstr.py b/rpython/rtyper/rstr.py --- a/rpython/rtyper/rstr.py +++ b/rpython/rtyper/rstr.py @@ -9,7 +9,6 @@ from rpython.rtyper.rfloat import FloatRepr from rpython.tool.pairtype import pairtype, pair from rpython.tool.sourcetools import func_with_new_name -from rpython.tool.staticmethods import StaticMethods from rpython.rlib.rstring import UnicodeBuilder @@ -800,10 +799,8 @@ # get flowed and annotated, mostly with SomePtr. # -# this class contains low level helpers used both by lltypesystem -class AbstractLLHelpers: - __metaclass__ = StaticMethods - +class AbstractLLHelpers(object): + @staticmethod def ll_isdigit(s): from rpython.rtyper.annlowlevel import hlstr @@ -815,6 +812,7 @@ return False return True + @staticmethod def ll_isalpha(s): from rpython.rtyper.annlowlevel import hlstr @@ -826,6 +824,7 @@ return False return True + @staticmethod def ll_isalnum(s): from rpython.rtyper.annlowlevel import hlstr @@ -837,14 +836,17 @@ return False return True + @staticmethod def ll_char_isspace(ch): c = ord(ch) return c == 32 or (9 <= c <= 13) # c in (9, 10, 11, 12, 13, 32) + @staticmethod def ll_char_isdigit(ch): c = ord(ch) return c <= 57 and c >= 48 + @staticmethod def ll_char_isalpha(ch): c = ord(ch) if c >= 97: @@ -852,6 +854,7 @@ else: return 65 <= c <= 90 + @staticmethod def ll_char_isalnum(ch): c = ord(ch) if c >= 65: @@ -862,47 +865,54 @@ else: return 48 <= c <= 57 + @staticmethod def ll_char_isupper(ch): c = ord(ch) return 65 <= c <= 90 + @staticmethod def ll_char_islower(ch): c = ord(ch) return 97 <= c <= 122 + @staticmethod def ll_upper_char(ch): if 'a' <= ch <= 'z': ch = chr(ord(ch) - 32) return ch + @staticmethod def ll_lower_char(ch): if 'A' <= ch <= 'Z': ch = chr(ord(ch) + 32) return ch + @staticmethod def ll_char_hash(ch): return ord(ch) + @staticmethod def ll_unichar_hash(ch): return ord(ch) + @classmethod def ll_str_is_true(cls, s): # check if a string is True, allowing for None return bool(s) and cls.ll_strlen(s) != 0 - ll_str_is_true = classmethod(ll_str_is_true) + @classmethod def ll_stritem_nonneg_checked(cls, s, i): if i >= cls.ll_strlen(s): raise IndexError return cls.ll_stritem_nonneg(s, i) - ll_stritem_nonneg_checked = classmethod(ll_stritem_nonneg_checked) + @classmethod def ll_stritem(cls, s, i): if i < 0: i += cls.ll_strlen(s) return cls.ll_stritem_nonneg(s, i) - ll_stritem = classmethod(ll_stritem) + @classmethod def ll_stritem_checked(cls, s, i): length = cls.ll_strlen(s) if i < 0: @@ -910,8 +920,8 @@ if i >= length or i < 0: raise IndexError return cls.ll_stritem_nonneg(s, i) - ll_stritem_checked = classmethod(ll_stritem_checked) + @staticmethod def parse_fmt_string(fmt): # we support x, d, s, f, [r] it = iter(fmt) @@ -937,6 +947,7 @@ r.append(curstr) return r + @staticmethod def ll_float(ll_str): from rpython.rtyper.annlowlevel import hlstr from rpython.rlib.rfloat import rstring_to_float @@ -961,6 +972,7 @@ assert end >= 0 return rstring_to_float(s[beg:end + 1]) + @classmethod def ll_splitlines(cls, LIST, ll_str, keep_newlines): from rpython.rtyper.annlowlevel import hlstr s = hlstr(ll_str) @@ -991,4 +1003,3 @@ item = cls.ll_stringslice_startstop(ll_str, j, strlen) res.ll_setitem_fast(list_length, item) return res - ll_splitlines = classmethod(ll_splitlines) diff --git a/rpython/tool/staticmethods.py b/rpython/tool/staticmethods.py deleted file mode 100644 --- a/rpython/tool/staticmethods.py +++ /dev/null @@ -1,14 +0,0 @@ -import types -class AbstractMethods(type): - def __new__(cls, cls_name, bases, cls_dict): - for key, value in cls_dict.iteritems(): - if isinstance(value, types.FunctionType): - cls_dict[key] = cls.decorator(value) - return type.__new__(cls, cls_name, bases, cls_dict) - - -class StaticMethods(AbstractMethods): - """ - Metaclass that turns plain methods into staticmethods. - """ - decorator = staticmethod diff --git a/rpython/translator/platform/__init__.py b/rpython/translator/platform/__init__.py --- a/rpython/translator/platform/__init__.py +++ b/rpython/translator/platform/__init__.py @@ -354,8 +354,10 @@ platform = pick_platform(new_platform, cc) if not platform: raise ValueError("pick_platform(%r, %s) failed"%(new_platform, cc)) - log.msg("Set platform with %r cc=%s, using cc=%r" % (new_platform, cc, - getattr(platform, 'cc','Unknown'))) + log.msg("Set platform with %r cc=%s, using cc=%r, version=%r" % (new_platform, cc, + getattr(platform, 'cc','Unknown'), + getattr(platform, 'version','Unknown'), + )) if new_platform == 'host': global host diff --git a/rpython/translator/platform/windows.py b/rpython/translator/platform/windows.py --- a/rpython/translator/platform/windows.py +++ b/rpython/translator/platform/windows.py @@ -14,9 +14,11 @@ if not cc: cc = os.environ.get('CC','') if not cc: - return MsvcPlatform(cc=cc, x64=x64_flag) + return MsvcPlatform(x64=x64_flag) elif cc.startswith('mingw') or cc == 'gcc': return MingwPlatform(cc) + else: + return MsvcPlatform(cc=cc, x64=x64_flag) try: subprocess.check_output([cc, '--version']) except: @@ -108,11 +110,14 @@ def __init__(self, cc=None, x64=False): self.x64 = x64 - msvc_compiler_environ = find_msvc_env(x64) - Platform.__init__(self, 'cl.exe') - if msvc_compiler_environ: - self.c_environ = os.environ.copy() - self.c_environ.update(msvc_compiler_environ) + if cc is None: + msvc_compiler_environ = find_msvc_env(x64) + Platform.__init__(self, 'cl.exe') + if msvc_compiler_environ: + self.c_environ = os.environ.copy() + self.c_environ.update(msvc_compiler_environ) + else: + self.cc = cc # detect version of current compiler returncode, stdout, stderr = _run_subprocess(self.cc, '', _______________________________________________ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
