Author: Carl Friedrich Bolz <cfb...@gmx.de> Branch: value-profiling Changeset: r79750:95fb006bbdff Date: 2015-09-22 10:57 +0200 http://bitbucket.org/pypy/pypy/changeset/95fb006bbdff/
Log: merge default diff too long, truncating to 2000 out of 3446 lines diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -92,6 +92,8 @@ if sys.platform == "win32": module_suggests["cpyext"].append(("translation.shared", True)) + +# NOTE: this dictionary is not used any more module_import_dependencies = { # no _rawffi if importing rpython.rlib.clibffi raises ImportError # or CompilationError or py.test.skip.Exception @@ -108,6 +110,7 @@ } def get_module_validator(modname): + # NOTE: this function is not used any more if modname in module_import_dependencies: modlist = module_import_dependencies[modname] def validator(config): diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst --- a/pypy/doc/faq.rst +++ b/pypy/doc/faq.rst @@ -67,7 +67,7 @@ The other commands of ``setup.py`` are available too, like ``build``. .. _PyPI: https://pypi.python.org/pypi -.. _`use virtualenv (as documented here)`: getting-started.html#installing-using-virtualenv +.. _`use virtualenv (as documented here)`: install.html#installing-using-virtualenv Module xyz does not work in the sandboxed PyPy? diff --git a/pypy/doc/jit-hooks.rst b/pypy/doc/jit-hooks.rst --- a/pypy/doc/jit-hooks.rst +++ b/pypy/doc/jit-hooks.rst @@ -5,19 +5,8 @@ understanding what's pypy's JIT doing while running your program. There are three functions related to that coming from the ``pypyjit`` module: -.. function:: set_optimize_hook(callable) - Set a compiling hook that will be called each time a loop is optimized, - but before assembler compilation. This allows adding additional - optimizations on Python level. - - The callable will be called with the ``pypyjit.JitLoopInfo`` object. - Refer to it's documentation for details. - - Result value will be the resulting list of operations, or None - - -.. function:: set_compile_hook(callable) +.. function:: set_compile_hook(callable, operations=True) Set a compiling hook that will be called each time a loop is compiled. @@ -28,6 +17,9 @@ inside the jit hook is itself jitted, it will get compiled, but the jit hook won't be called for that. + if operations=False, no list of operations will be available. Useful + if the hook is supposed to be very lighweight. + .. function:: set_abort_hook(hook) Set a hook (callable) that will be called each time there is tracing @@ -66,3 +58,25 @@ * ``loop_run_times`` - counters for number of times loops are run, only works when ``enable_debug`` is called. + +.. class:: JitLoopInfo + + A class containing information about the compiled loop. Usable attributes: + + * ``operations`` - list of operations, if requested + + * ``jitdriver_name`` - the name of jitdriver associated with this loop + + * ``greenkey`` - a key at which the loop got compiled (e.g. code position, + is_being_profiled, pycode tuple for python jitdriver) + + * ``loop_no`` - loop cardinal number + + * ``bridge_no`` - id of the fail descr + + * ``type`` - "entry bridge", "loop" or "bridge" + + * ``asmaddr`` - an address in raw memory where assembler resides + + * ``asmlen`` - length of raw memory with assembler associated + 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 @@ -21,3 +21,15 @@ .. branch: missing_openssl_include Fix for missing headers in OpenBSD, already applied in downstream ports + +.. branch: gc-more-incremental +Remove a source of non-incremental-ness in the GC: now +external_malloc() no longer runs gc_step_until() any more. If there +is a currently-running major collection, we do only so many steps +before returning. This number of steps depends on the size of the +allocated object. It is controlled by tracking the general progress +of these major collection steps and the size of old objects that +keep adding up between them. + +.. branch: remember-tracing-counts +Reenable jithooks diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py --- a/pypy/goal/targetpypystandalone.py +++ b/pypy/goal/targetpypystandalone.py @@ -341,8 +341,8 @@ def jitpolicy(self, driver): from pypy.module.pypyjit.policy import PyPyJitPolicy - #from pypy.module.pypyjit.hooks import pypy_hooks - return PyPyJitPolicy()#pypy_hooks) + from pypy.module.pypyjit.hooks import pypy_hooks + return PyPyJitPolicy(pypy_hooks) def get_entry_point(self, config): from pypy.tool.lib_pypy import import_from_lib_pypy diff --git a/pypy/module/micronumpy/base.py b/pypy/module/micronumpy/base.py --- a/pypy/module/micronumpy/base.py +++ b/pypy/module/micronumpy/base.py @@ -1,6 +1,7 @@ from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter.error import OperationError, oefmt from rpython.tool.pairtype import extendabletype +from rpython.rlib.rarithmetic import ovfcheck from pypy.module.micronumpy import support from pypy.module.micronumpy import constants as NPY @@ -44,9 +45,9 @@ raise oefmt(space.w_ValueError, "sequence too large; must be smaller than %d", NPY.MAXDIMS) try: - support.product(shape) * dtype.elsize + ovfcheck(support.product_check(shape) * dtype.elsize) except OverflowError as e: - raise oefmt(space.w_ValueError, "array is too big") + raise oefmt(space.w_ValueError, "array is too big.") strides, backstrides = calc_strides(shape, dtype.base, order) impl = concrete.ConcreteArray(shape, dtype.base, order, strides, backstrides, zero=zero) @@ -68,9 +69,9 @@ raise oefmt(space.w_ValueError, "sequence too large; must be smaller than %d", NPY.MAXDIMS) try: - totalsize = support.product(shape) * isize + totalsize = ovfcheck(support.product_check(shape) * isize) except OverflowError as e: - raise oefmt(space.w_ValueError, "array is too big") + raise oefmt(space.w_ValueError, "array is too big.") if storage_bytes > 0 : if totalsize > storage_bytes: raise OperationError(space.w_TypeError, space.wrap( diff --git a/pypy/module/micronumpy/concrete.py b/pypy/module/micronumpy/concrete.py --- a/pypy/module/micronumpy/concrete.py +++ b/pypy/module/micronumpy/concrete.py @@ -1,5 +1,6 @@ from pypy.interpreter.error import OperationError, oefmt from rpython.rlib import jit, rgc +from rpython.rlib.rarithmetic import ovfcheck from rpython.rlib.buffer import Buffer from rpython.rlib.debug import make_sure_not_resized from rpython.rlib.rawstorage import alloc_raw_storage, free_raw_storage, \ @@ -409,6 +410,7 @@ make_sure_not_resized(strides) make_sure_not_resized(backstrides) self.shape = shape + # already tested for overflow in from_shape_and_storage self.size = support.product(shape) * dtype.elsize self.order = order self.dtype = dtype @@ -428,9 +430,9 @@ raise oefmt(space.w_ValueError, "sequence too large; must be smaller than %d", NPY.MAXDIMS) try: - support.product(new_shape) * self.dtype.elsize + ovfcheck(support.product_check(new_shape) * self.dtype.elsize) except OverflowError as e: - raise oefmt(space.w_ValueError, "array is too big") + raise oefmt(space.w_ValueError, "array is too big.") strides, backstrides = calc_strides(new_shape, self.dtype, self.order) return SliceArray(self.start, strides, backstrides, new_shape, self, @@ -457,8 +459,11 @@ storage=lltype.nullptr(RAW_STORAGE), zero=True): gcstruct = V_OBJECTSTORE flags = NPY.ARRAY_ALIGNED | NPY.ARRAY_WRITEABLE - length = support.product(shape) - self.size = length * dtype.elsize + try: + length = support.product_check(shape) + self.size = ovfcheck(length * dtype.elsize) + except OverflowError: + raise oefmt(dtype.itemtype.space.w_ValueError, "array is too big.") if storage == lltype.nullptr(RAW_STORAGE): if dtype.num == NPY.OBJECT: storage = dtype.itemtype.malloc(length * dtype.elsize, zero=True) @@ -542,7 +547,10 @@ self.gcstruct = parent.gcstruct self.order = parent.order self.dtype = dtype - self.size = support.product(shape) * self.dtype.elsize + try: + self.size = ovfcheck(support.product_check(shape) * self.dtype.elsize) + except OverflowError: + raise oefmt(dtype.itemtype.space.w_ValueError, "array is too big.") self.start = start self.orig_arr = orig_arr flags = parent.flags & NPY.ARRAY_ALIGNED @@ -564,9 +572,9 @@ raise oefmt(space.w_ValueError, "sequence too large; must be smaller than %d", NPY.MAXDIMS) try: - support.product(new_shape) * self.dtype.elsize + ovfcheck(support.product_check(new_shape) * self.dtype.elsize) except OverflowError as e: - raise oefmt(space.w_ValueError, "array is too big") + raise oefmt(space.w_ValueError, "array is too big.") if len(self.get_shape()) < 2 or self.size == 0: # TODO: this code could be refactored into calc_strides # but then calc_strides would have to accept a stepping factor 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 @@ -153,7 +153,7 @@ dtype = descriptor.variable_dtype(space, dtype.char + '1') w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order) - if support.product(shape) == 1: + if support.product(shape) == 1: # safe from overflow since from_shape checks w_arr.set_scalar_value(dtype.coerce(space, elems_w[0])) else: loop.assign(space, w_arr, elems_w) @@ -213,10 +213,9 @@ raise OperationError(space.w_ValueError, space.wrap( "negative dimensions are not allowed")) try: - support.product(shape) + support.product_check(shape) except OverflowError: - raise OperationError(space.w_ValueError, space.wrap( - "array is too big.")) + raise oefmt(space.w_ValueError, "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/ndarray.py b/pypy/module/micronumpy/ndarray.py --- a/pypy/module/micronumpy/ndarray.py +++ b/pypy/module/micronumpy/ndarray.py @@ -6,6 +6,7 @@ from rpython.rlib import jit from rpython.rlib.rstring import StringBuilder from rpython.rlib.rawstorage import RAW_STORAGE_PTR +from rpython.rlib.rarithmetic import ovfcheck from rpython.rtyper.lltypesystem import rffi from rpython.tool.sourcetools import func_with_new_name from pypy.module.micronumpy import descriptor, ufuncs, boxes, arrayops, loop, \ @@ -611,6 +612,7 @@ "__array__(dtype) not implemented")) if type(self) is W_NDimArray: return self + # sz cannot overflow since self is valid sz = support.product(self.get_shape()) * self.get_dtype().elsize return W_NDimArray.from_shape_and_storage( space, self.get_shape(), self.implementation.storage, @@ -1405,9 +1407,9 @@ return W_NDimArray.from_shape(space, shape, dtype, order) strides, backstrides = calc_strides(shape, dtype.base, order) try: - totalsize = support.product(shape) * dtype.base.elsize + totalsize = ovfcheck(support.product_check(shape) * dtype.base.elsize) except OverflowError as e: - raise oefmt(space.w_ValueError, "array is too big") + raise oefmt(space.w_ValueError, "array is too big.") impl = ConcreteArray(shape, dtype.base, order, strides, backstrides) w_ret = space.allocate_instance(W_NDimArray, w_subtype) W_NDimArray.__init__(w_ret, impl) 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 @@ -32,10 +32,16 @@ def product(s): i = 1 for x in s: + i *= x + return i + +@jit.unroll_safe +def product_check(s): + i = 1 + for x in s: i = ovfcheck(i * x) return i - def check_and_adjust_index(space, index, size, axis): if index < -size or index >= size: if axis >= 0: 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 @@ -270,7 +270,7 @@ exc = raises(ValueError, ndarray, [1,2,256]*10000) assert exc.value[0] == 'sequence too large; must be smaller than 32' exc = raises(ValueError, ndarray, [1,2,256]*10) - assert exc.value[0] == 'array is too big' + assert exc.value[0] == 'array is too big.' def test_ndmin(self): from numpy import array diff --git a/pypy/module/micronumpy/ufuncs.py b/pypy/module/micronumpy/ufuncs.py --- a/pypy/module/micronumpy/ufuncs.py +++ b/pypy/module/micronumpy/ufuncs.py @@ -1006,7 +1006,6 @@ assert isinstance(curarg, W_NDimArray) if len(arg_shapes[i]) != curarg.ndims(): # reshape - sz = product(curarg.get_shape()) * curarg.get_dtype().elsize with curarg.implementation as storage: inargs[i] = W_NDimArray.from_shape_and_storage( diff --git a/pypy/module/pypyjit/__init__.py b/pypy/module/pypyjit/__init__.py --- a/pypy/module/pypyjit/__init__.py +++ b/pypy/module/pypyjit/__init__.py @@ -8,16 +8,18 @@ 'set_param': 'interp_jit.set_param', 'residual_call': 'interp_jit.residual_call', 'not_from_assembler': 'interp_jit.W_NotFromAssembler', - #'set_compile_hook': 'interp_resop.set_compile_hook', - #'set_optimize_hook': 'interp_resop.set_optimize_hook', - #'set_abort_hook': 'interp_resop.set_abort_hook', - #'get_stats_snapshot': 'interp_resop.get_stats_snapshot', - #'enable_debug': 'interp_resop.enable_debug', - #'disable_debug': 'interp_resop.disable_debug', - #'ResOperation': 'interp_resop.WrappedOp', - #'DebugMergePoint': 'interp_resop.DebugMergePoint', - #'JitLoopInfo': 'interp_resop.W_JitLoopInfo', - #'Box': 'interp_resop.WrappedBox', + 'get_jitcell_at_key': 'interp_jit.get_jitcell_at_key', + 'dont_trace_here': 'interp_jit.dont_trace_here', + 'trace_next_iteration': 'interp_jit.trace_next_iteration', + 'trace_next_iteration_hash': 'interp_jit.trace_next_iteration_hash', + 'set_compile_hook': 'interp_resop.set_compile_hook', + 'set_abort_hook': 'interp_resop.set_abort_hook', + 'get_stats_snapshot': 'interp_resop.get_stats_snapshot', + 'enable_debug': 'interp_resop.enable_debug', + 'disable_debug': 'interp_resop.disable_debug', + 'ResOperation': 'interp_resop.WrappedOp', + 'DebugMergePoint': 'interp_resop.DebugMergePoint', + 'JitLoopInfo': 'interp_resop.W_JitLoopInfo', 'PARAMETER_DOCS': 'space.wrap(rpython.rlib.jit.PARAMETER_DOCS)', } diff --git a/pypy/module/pypyjit/hooks.py b/pypy/module/pypyjit/hooks.py --- a/pypy/module/pypyjit/hooks.py +++ b/pypy/module/pypyjit/hooks.py @@ -35,10 +35,10 @@ self._compile_hook(debug_info, is_bridge=True) def before_compile(self, debug_info): - self._optimize_hook(debug_info, is_bridge=False) + pass def before_compile_bridge(self, debug_info): - self._optimize_hook(debug_info, is_bridge=True) + pass def _compile_hook(self, debug_info, is_bridge): space = self.space @@ -46,7 +46,8 @@ if cache.in_recursion: return if space.is_true(cache.w_compile_hook): - w_debug_info = W_JitLoopInfo(space, debug_info, is_bridge) + w_debug_info = W_JitLoopInfo(space, debug_info, is_bridge, + cache.compile_hook_with_ops) cache.in_recursion = True try: try: @@ -57,33 +58,4 @@ finally: cache.in_recursion = False - def _optimize_hook(self, debug_info, is_bridge=False): - space = self.space - cache = space.fromcache(Cache) - if cache.in_recursion: - return - if space.is_true(cache.w_optimize_hook): - w_debug_info = W_JitLoopInfo(space, debug_info, is_bridge) - cache.in_recursion = True - try: - try: - w_res = space.call_function(cache.w_optimize_hook, - space.wrap(w_debug_info)) - if space.is_w(w_res, space.w_None): - return - l = [] - for w_item in space.listview(w_res): - item = space.interp_w(WrappedOp, w_item) - l.append(jit_hooks._cast_to_resop(item.op)) - del debug_info.operations[:] # modifying operations above is - # probably not a great idea since types may not work - # and we'll end up with half-working list and - # a segfault/fatal RPython error - for elem in l: - debug_info.operations.append(elem) - except OperationError, e: - e.write_unraisable(space, "jit hook ", cache.w_compile_hook) - finally: - cache.in_recursion = False - pypy_hooks = PyPyJitIface() diff --git a/pypy/module/pypyjit/interp_jit.py b/pypy/module/pypyjit/interp_jit.py --- a/pypy/module/pypyjit/interp_jit.py +++ b/pypy/module/pypyjit/interp_jit.py @@ -5,11 +5,14 @@ from rpython.rlib.rarithmetic import r_uint, intmask from rpython.rlib.jit import JitDriver, hint, we_are_jitted, dont_look_inside -from rpython.rlib import jit -from rpython.rlib.jit import current_trace_length, unroll_parameters +from rpython.rlib import jit, jit_hooks +from rpython.rlib.jit import current_trace_length, unroll_parameters,\ + JitHookInterface +from rpython.rtyper.annlowlevel import cast_instance_to_gcref import pypy.interpreter.pyopcode # for side-effects from pypy.interpreter.error import OperationError, oefmt from pypy.interpreter.pycode import CO_GENERATOR, PyCode +from pypy.interpreter.gateway import unwrap_spec from pypy.interpreter.pyframe import PyFrame from pypy.interpreter.pyopcode import ExitFrame, Yield from pypy.interpreter.baseobjspace import W_Root @@ -188,3 +191,100 @@ __call__ = interp2app(W_NotFromAssembler.descr_call), ) W_NotFromAssembler.typedef.acceptable_as_base_class = False + +@unwrap_spec(next_instr=int, is_being_profiled=bool, w_pycode=PyCode) +@dont_look_inside +def get_jitcell_at_key(space, next_instr, is_being_profiled, w_pycode): + ll_pycode = cast_instance_to_gcref(w_pycode) + return space.wrap(bool(jit_hooks.get_jitcell_at_key( + 'pypyjit', r_uint(next_instr), int(is_being_profiled), ll_pycode))) + +@unwrap_spec(next_instr=int, is_being_profiled=bool, w_pycode=PyCode) +@dont_look_inside +def dont_trace_here(space, next_instr, is_being_profiled, w_pycode): + ll_pycode = cast_instance_to_gcref(w_pycode) + jit_hooks.dont_trace_here( + 'pypyjit', r_uint(next_instr), int(is_being_profiled), ll_pycode) + return space.w_None + +@unwrap_spec(next_instr=int, is_being_profiled=bool, w_pycode=PyCode) +@dont_look_inside +def trace_next_iteration(space, next_instr, is_being_profiled, w_pycode): + ll_pycode = cast_instance_to_gcref(w_pycode) + jit_hooks.trace_next_iteration( + 'pypyjit', r_uint(next_instr), int(is_being_profiled), ll_pycode) + return space.w_None + +@unwrap_spec(hash=r_uint) +@dont_look_inside +def trace_next_iteration_hash(space, hash): + jit_hooks.trace_next_iteration_hash('pypyjit', hash) + return space.w_None + +# class Cache(object): +# in_recursion = False + +# def __init__(self, space): +# self.w_compile_bridge = space.w_None +# self.w_compile_loop = space.w_None + +# def set_compile_bridge(space, w_hook): +# cache = space.fromcache(Cache) +# assert w_hook is not None +# cache.w_compile_bridge = w_hook + +# def set_compile_loop(space, w_hook): +# from rpython.rlib.nonconst import NonConstant + +# cache = space.fromcache(Cache) +# assert w_hook is not None +# cache.w_compile_loop = w_hook +# cache.in_recursion = NonConstant(False) + +# class PyPyJitHookInterface(JitHookInterface): +# def after_compile(self, debug_info): +# space = self.space +# cache = space.fromcache(Cache) +# if cache.in_recursion: +# return +# l_w = [] +# if not space.is_true(cache.w_compile_loop): +# return +# for i, op in enumerate(debug_info.operations): +# if op.is_guard(): +# w_t = space.newtuple([space.wrap(i), space.wrap(op.getopnum()), space.wrap(op.getdescr().get_jitcounter_hash())]) +# l_w.append(w_t) +# try: +# cache.in_recursion = True +# try: +# space.call_function(cache.w_compile_loop, space.newlist(l_w)) +# except OperationError, e: +# e.write_unraisable(space, "jit hook ", cache.w_compile_bridge) +# finally: +# cache.in_recursion = False + +# def after_compile_bridge(self, debug_info): +# space = self.space +# cache = space.fromcache(Cache) +# if cache.in_recursion: +# return +# if not space.is_true(cache.w_compile_bridge): +# return +# w_hash = space.wrap(debug_info.fail_descr.get_jitcounter_hash()) +# try: +# cache.in_recursion = True +# try: +# space.call_function(cache.w_compile_bridge, w_hash) +# except OperationError, e: +# e.write_unraisable(space, "jit hook ", cache.w_compile_bridge) +# finally: +# cache.in_recursion = False + +# def before_compile(self, debug_info): +# pass + +# def before_compile_bridge(self, debug_info): +# pass + +# pypy_hooks = PyPyJitHookInterface() + diff --git a/pypy/module/pypyjit/interp_resop.py b/pypy/module/pypyjit/interp_resop.py --- a/pypy/module/pypyjit/interp_resop.py +++ b/pypy/module/pypyjit/interp_resop.py @@ -22,7 +22,6 @@ def __init__(self, space): self.w_compile_hook = space.w_None self.w_abort_hook = space.w_None - self.w_optimize_hook = space.w_None def getno(self): self.no += 1 @@ -43,8 +42,9 @@ else: return space.wrap(greenkey_repr) -def set_compile_hook(space, w_hook): - """ set_compile_hook(hook) +@unwrap_spec(operations=bool) +def set_compile_hook(space, w_hook, operations=True): + """ set_compile_hook(hook, operations=True) Set a compiling hook that will be called each time a loop is compiled. @@ -58,25 +58,9 @@ cache = space.fromcache(Cache) assert w_hook is not None cache.w_compile_hook = w_hook + cache.compile_hook_with_ops = operations cache.in_recursion = NonConstant(False) -def set_optimize_hook(space, w_hook): - """ set_optimize_hook(hook) - - Set a compiling hook that will be called each time a loop is optimized, - but before assembler compilation. This allows adding additional - optimizations on Python level. - - The hook will be called with the pypyjit.JitLoopInfo object. Refer to it's - docstring for details. - - Result value will be the resulting list of operations, or None - """ - cache = space.fromcache(Cache) - cache.w_optimize_hook = w_hook - cache.in_recursion = NonConstant(False) - - def set_abort_hook(space, w_hook): """ set_abort_hook(hook) @@ -96,6 +80,9 @@ cache.in_recursion = NonConstant(False) def wrap_oplist(space, logops, operations, ops_offset=None): + # this function is called from the JIT + from rpython.jit.metainterp.resoperation import rop + l_w = [] jitdrivers_sd = logops.metainterp_sd.jitdrivers_sd for op in operations: @@ -103,117 +90,58 @@ ofs = -1 else: ofs = ops_offset.get(op, 0) - if op.opnum == rop.DEBUG_MERGE_POINT: + num = op.getopnum() + name = op.getopname() + if num == rop.DEBUG_MERGE_POINT: jd_sd = jitdrivers_sd[op.getarg(0).getint()] greenkey = op.getarglist()[3:] repr = jd_sd.warmstate.get_location_str(greenkey) w_greenkey = wrap_greenkey(space, jd_sd.jitdriver, greenkey, repr) - l_w.append(DebugMergePoint(space, jit_hooks._cast_to_gcref(op), + l_w.append(DebugMergePoint(space, name, logops.repr_of_resop(op), jd_sd.jitdriver.name, op.getarg(1).getint(), op.getarg(2).getint(), w_greenkey)) else: - l_w.append(WrappedOp(jit_hooks._cast_to_gcref(op), ofs, - logops.repr_of_resop(op))) + l_w.append(WrappedOp(name, ofs, logops.repr_of_resop(op))) return l_w +@unwrap_spec(offset=int, repr=str, name=str) +def descr_new_resop(space, w_tp, name, offset=-1, repr=''): + return WrappedOp(name, offset, repr) -class WrappedBox(W_Root): - """ A class representing a single box - """ - def __init__(self, llbox): - self.llbox = llbox - - def descr_getint(self, space): - if not jit_hooks.box_isint(self.llbox): - raise OperationError(space.w_NotImplementedError, - space.wrap("Box has no int value")) - return space.wrap(jit_hooks.box_getint(self.llbox)) - -@unwrap_spec(no=int) -def descr_new_box(space, w_tp, no): - return WrappedBox(jit_hooks.boxint_new(no)) - -WrappedBox.typedef = TypeDef( - 'Box', - __new__ = interp2app(descr_new_box), - getint = interp2app(WrappedBox.descr_getint), -) - -@unwrap_spec(num=int, offset=int, repr=str, w_res=W_Root) -def descr_new_resop(space, w_tp, num, w_args, w_res, offset=-1, - repr=''): - args = [space.interp_w(WrappedBox, w_arg).llbox for w_arg in - space.listview(w_args)] - if space.is_none(w_res): - llres = jit_hooks.emptyval() - else: - if not isinstance(w_res, WrappedBox): - raise OperationError(space.w_TypeError, space.wrap( - "expected box type, got %s" % space.type(w_res))) - llres = w_res.llbox - return WrappedOp(jit_hooks.resop_new(num, args, llres), offset, repr) - -@unwrap_spec(repr=str, jd_name=str, call_depth=int, call_id=int) -def descr_new_dmp(space, w_tp, w_args, repr, jd_name, call_depth, call_id, +@unwrap_spec(repr=str, name=str, jd_name=str, call_depth=int, call_id=int) +def descr_new_dmp(space, w_tp, name, repr, jd_name, call_depth, call_id, w_greenkey): - args = [space.interp_w(WrappedBox, w_arg).llbox for w_arg in - space.listview(w_args)] - num = rop.DEBUG_MERGE_POINT - return DebugMergePoint(space, - jit_hooks.resop_new(num, args, jit_hooks.emptyval()), + return DebugMergePoint(space, name, repr, jd_name, call_depth, call_id, w_greenkey) class WrappedOp(W_Root): """ A class representing a single ResOperation, wrapped nicely """ - def __init__(self, op, offset, repr_of_resop): - self.op = op + def __init__(self, name, offset, repr_of_resop): self.offset = offset + self.name = name self.repr_of_resop = repr_of_resop def descr_repr(self, space): return space.wrap(self.repr_of_resop) - def descr_num(self, space): - return space.wrap(jit_hooks.resop_getopnum(self.op)) - def descr_name(self, space): - return space.wrap(hlstr(jit_hooks.resop_getopname(self.op))) - - @unwrap_spec(no=int) - def descr_getarg(self, space, no): - try: - box = jit_hooks.resop_getarg(self.op, no) - except IndexError: - raise OperationError(space.w_IndexError, - space.wrap("Index out of range")) - return WrappedBox(box) - - @unwrap_spec(no=int, w_box=WrappedBox) - def descr_setarg(self, space, no, w_box): - jit_hooks.resop_setarg(self.op, no, w_box.llbox) - - def descr_getresult(self, space): - return WrappedBox(jit_hooks.resop_getresult(self.op)) - - def descr_setresult(self, space, w_box): - box = space.interp_w(WrappedBox, w_box) - jit_hooks.resop_setresult(self.op, box.llbox) + return space.wrap(self.name) class DebugMergePoint(WrappedOp): """ A class representing Debug Merge Point - the entry point to a jitted loop. """ - def __init__(self, space, op, repr_of_resop, jd_name, call_depth, call_id, - w_greenkey): + def __init__(self, space, name, repr_of_resop, jd_name, call_depth, + call_id, w_greenkey): - WrappedOp.__init__(self, op, -1, repr_of_resop) + WrappedOp.__init__(self, name, -1, repr_of_resop) self.jd_name = jd_name self.call_depth = call_depth self.call_id = call_id @@ -237,12 +165,7 @@ __doc__ = WrappedOp.__doc__, __new__ = interp2app(descr_new_resop), __repr__ = interp2app(WrappedOp.descr_repr), - num = GetSetProperty(WrappedOp.descr_num), name = GetSetProperty(WrappedOp.descr_name), - getarg = interp2app(WrappedOp.descr_getarg), - setarg = interp2app(WrappedOp.descr_setarg), - result = GetSetProperty(WrappedOp.descr_getresult, - WrappedOp.descr_setresult), offset = interp_attrproperty("offset", cls=WrappedOp), ) WrappedOp.typedef.acceptable_as_base_class = False @@ -278,14 +201,18 @@ asmaddr = 0 asmlen = 0 - def __init__(self, space, debug_info, is_bridge=False): - logops = debug_info.logger._make_log_operations() - if debug_info.asminfo is not None: - ofs = debug_info.asminfo.ops_offset + def __init__(self, space, debug_info, is_bridge=False, wrap_ops=True): + if wrap_ops: + memo = {} + logops = debug_info.logger._make_log_operations(memo) + if debug_info.asminfo is not None: + ofs = debug_info.asminfo.ops_offset + else: + ofs = {} + ops = debug_info.operations + self.w_ops = space.newlist(wrap_oplist(space, logops, ops, ofs)) else: - ofs = {} - self.w_ops = space.newlist( - wrap_oplist(space, logops, debug_info.operations, ofs)) + self.w_ops = space.w_None self.jd_name = debug_info.get_jitdriver().name self.type = debug_info.type diff --git a/pypy/module/pypyjit/test/test_jit_hook.py b/pypy/module/pypyjit/test/test_jit_hook.py --- a/pypy/module/pypyjit/test/test_jit_hook.py +++ b/pypy/module/pypyjit/test/test_jit_hook.py @@ -136,7 +136,6 @@ assert dmp.call_id == 0 assert dmp.offset == -1 assert int_add.name == 'int_add' - assert int_add.num == self.int_add_num assert int_add.offset == 0 self.on_compile_bridge() expected = ('<JitLoopInfo pypyjit, 4 operations, starting at ' @@ -173,10 +172,7 @@ self.on_compile() loop = loops[0] op = loop.operations[2] - # Should not crash the interpreter - raises(IndexError, op.getarg, 2) assert op.name == 'guard_nonnull' - raises(NotImplementedError, op.getarg(0).getint) def test_non_reentrant(self): import pypyjit @@ -234,35 +230,28 @@ assert l == ['pypyjit'] def test_creation(self): - from pypyjit import Box, ResOperation + from pypyjit import ResOperation - op = ResOperation(self.int_add_num, [Box(1), Box(3)], Box(4)) - assert op.num == self.int_add_num + op = ResOperation("int_add", -1, "int_add(1, 2)") assert op.name == 'int_add' - box = op.getarg(0) - assert box.getint() == 1 - box2 = op.result - assert box2.getint() == 4 - op.setarg(0, box2) - assert op.getarg(0).getint() == 4 - op.result = box - assert op.result.getint() == 1 + assert repr(op) == "int_add(1, 2)" def test_creation_dmp(self): - from pypyjit import DebugMergePoint, Box + from pypyjit import DebugMergePoint def f(): pass - op = DebugMergePoint([Box(0)], 'repr', 'pypyjit', 2, 3, (f.func_code, 0, 0)) + op = DebugMergePoint("debug_merge_point", 'repr', 'pypyjit', 2, 3, (f.func_code, 0, 0)) assert op.bytecode_no == 0 assert op.pycode is f.func_code assert repr(op) == 'repr' assert op.jitdriver_name == 'pypyjit' - assert op.num == self.dmp_num + assert op.name == 'debug_merge_point' assert op.call_depth == 2 assert op.call_id == 3 - op = DebugMergePoint([Box(0)], 'repr', 'notmain', 5, 4, ('str',)) + op = DebugMergePoint('debug_merge_point', 'repr', 'notmain', + 5, 4, ('str',)) raises(AttributeError, 'op.pycode') assert op.call_depth == 5 diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py --- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py +++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py @@ -422,11 +422,11 @@ i114 = int_ne(i160, i112) guard_false(i114, descr=...) --TICK-- + i123 = arraylen_gc(p67, descr=<ArrayP .>) i119 = call_i(ConstClass(_ll_1_raw_malloc_varsize__Signed), 6, descr=<Calli . i EF=5 OS=110>) raw_store(i119, 0, i160, descr=<ArrayS 2>) raw_store(i119, 2, i160, descr=<ArrayS 2>) raw_store(i119, 4, i160, descr=<ArrayS 2>) setfield_gc(p167, i119, descr=<FieldU pypy.module._cffi_backend.cdataobj.W_CData.inst__ptr .+>) - i123 = arraylen_gc(p67, descr=<ArrayP .>) jump(..., descr=...) """) diff --git a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py --- a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py +++ b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py @@ -47,7 +47,7 @@ i31 = getfield_gc_pure_i(p1, descr=<FieldS pypy.module.micronumpy.iterators.ArrayIter.inst_size \d+>) i32 = int_ge(i25, i31) guard_false(i32, descr=...) - p34 = new_with_vtable(#) + p34 = new_with_vtable(descr=...) {{{ setfield_gc(p34, p1, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_iterator \d+>) setfield_gc(p34, i25, descr=<FieldS pypy.module.micronumpy.iterators.IterState.inst_index \d+>) @@ -154,7 +154,7 @@ f86 = float_add(f74, f85) i87 = int_add(i76, 1) --TICK-- - jump(p0, p1, p6, p7, p8, p11, p13, f86, p17, i87, i62, p42, i58, p48, i41, i64, i70, descr=...) + jump(..., descr=...) """) def test_array_flatiter_next(self): diff --git a/pypy/module/pypyjit/test_pypy_c/test_misc.py b/pypy/module/pypyjit/test_pypy_c/test_misc.py --- a/pypy/module/pypyjit/test_pypy_c/test_misc.py +++ b/pypy/module/pypyjit/test_pypy_c/test_misc.py @@ -148,6 +148,7 @@ i18 = force_token() setfield_gc(p9, i17, descr=<.* .*W_XRangeIterator.inst_current .*>) guard_not_invalidated(descr=...) + i84 = int_sub(i14, 1) i21 = int_lt(i10, 0) guard_false(i21, descr=...) i22 = int_lt(i10, i14) @@ -180,6 +181,7 @@ i21 = force_token() setfield_gc(p4, i20, descr=<.* .*W_AbstractSeqIterObject.inst_index .*>) guard_not_invalidated? + i88 = int_sub(i9, 1) i25 = int_ge(i11, i9) guard_false(i25, descr=...) i27 = int_add_ovf(i7, i11) @@ -212,6 +214,7 @@ i21 = force_token() setfield_gc(p4, i20, descr=<.* .*W_AbstractSeqIterObject.inst_index .*>) guard_not_invalidated? + i95 = int_sub(i9, 1) i23 = int_lt(i18, 0) guard_false(i23, descr=...) i25 = int_ge(i18, i9) diff --git a/rpython/annotator/binaryop.py b/rpython/annotator/binaryop.py --- a/rpython/annotator/binaryop.py +++ b/rpython/annotator/binaryop.py @@ -385,7 +385,8 @@ class __extend__(pairtype(SomeUnicodeCodePoint, SomeUnicodeCodePoint)): def union((uchr1, uchr2)): - return SomeUnicodeCodePoint() + no_nul = uchr1.no_nul and uchr2.no_nul + return SomeUnicodeCodePoint(no_nul=no_nul) def add((chr1, chr2)): return SomeUnicodeString() @@ -598,32 +599,33 @@ class __extend__(pairtype(SomeUnicodeString, SomeInteger)): def getitem((str1, int2)): - return SomeUnicodeCodePoint() + return SomeUnicodeCodePoint(no_nul=str1.no_nul) getitem.can_only_throw = [] def getitem_idx((str1, int2)): - return SomeUnicodeCodePoint() + return SomeUnicodeCodePoint(no_nul=str1.no_nul) getitem_idx.can_only_throw = [IndexError] def mul((str1, int2)): # xxx do we want to support this - return SomeUnicodeString() + return SomeUnicodeString(no_nul=str1.no_nul) class __extend__(pairtype(SomeInteger, SomeString), pairtype(SomeInteger, SomeUnicodeString)): def mul((int1, str2)): # xxx do we want to support this - return str2.basestringclass() + return str2.basestringclass(no_nul=str2.no_nul) class __extend__(pairtype(SomeUnicodeCodePoint, SomeUnicodeString), pairtype(SomeUnicodeString, SomeUnicodeCodePoint), pairtype(SomeUnicodeString, SomeUnicodeString)): def union((str1, str2)): - return SomeUnicodeString(can_be_None=str1.can_be_none() or - str2.can_be_none()) + can_be_None = str1.can_be_None or str2.can_be_None + no_nul = str1.no_nul and str2.no_nul + return SomeUnicodeString(can_be_None=can_be_None, no_nul=no_nul) def add((str1, str2)): # propagate const-ness to help getattr(obj, 'prefix' + const_name) - result = SomeUnicodeString() + result = SomeUnicodeString(no_nul=str1.no_nul and str2.no_nul) if str1.is_immutable_constant() and str2.is_immutable_constant(): result.const = str1.const + str2.const return result diff --git a/rpython/annotator/bookkeeper.py b/rpython/annotator/bookkeeper.py --- a/rpython/annotator/bookkeeper.py +++ b/rpython/annotator/bookkeeper.py @@ -237,10 +237,11 @@ else: result = SomeString(no_nul=no_nul) elif tp is unicode: + no_nul = not u'\x00' in x if len(x) == 1: - result = SomeUnicodeCodePoint() + result = SomeUnicodeCodePoint(no_nul=no_nul) else: - result = SomeUnicodeString() + result = SomeUnicodeString(no_nul=no_nul) elif tp is bytearray: result = SomeByteArray() elif tp is tuple: 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 @@ -438,6 +438,18 @@ assert s.knowntype == str assert s.no_nul + def test_unicode_join(self): + a = self.RPythonAnnotator() + def g(n): + if n: + return [u"foo", u"bar"] + def f(n): + g(0) + return u''.join(g(n)) + s = a.build_types(f, [int]) + assert s.knowntype == unicode + assert s.no_nul + def test_str_split(self): a = self.RPythonAnnotator() def g(n): @@ -451,6 +463,19 @@ s_item = s.listdef.listitem.s_value assert s_item.no_nul + def test_unicode_split(self): + a = self.RPythonAnnotator() + def g(n): + if n: + return u"test string" + def f(n): + if n: + return g(n).split(u' ') + s = a.build_types(f, [int]) + assert isinstance(s, annmodel.SomeList) + s_item = s.listdef.listitem.s_value + assert s_item.no_nul + def test_str_split_nul(self): def f(n): return n.split('\0')[0] @@ -470,6 +495,27 @@ assert not s.can_be_None assert not s.no_nul + def test_unicode_split_nul(self): + def f(n): + return n.split(u'\0')[0] + a = self.RPythonAnnotator() + a.translator.config.translation.check_str_without_nul = True + s = a.build_types(f, [annmodel.SomeUnicodeString( + no_nul=False, can_be_None=False)]) + assert isinstance(s, annmodel.SomeUnicodeString) + assert not s.can_be_None + assert s.no_nul + + def g(n): + return n.split(u'\0', 1)[0] + a = self.RPythonAnnotator() + a.translator.config.translation.check_str_without_nul = True + s = a.build_types(g, [annmodel.SomeUnicodeString( + no_nul=False, can_be_None=False)]) + assert isinstance(s, annmodel.SomeUnicodeString) + assert not s.can_be_None + assert not s.no_nul + def test_str_splitlines(self): a = self.RPythonAnnotator() def f(a_str): @@ -490,6 +536,18 @@ s = a.build_types(f, [int, annmodel.SomeString(no_nul=True)]) assert s.no_nul + def test_unicode_strip(self): + a = self.RPythonAnnotator() + def f(n, a_str): + if n == 0: + return a_str.strip(u' ') + elif n == 1: + return a_str.rstrip(u' ') + else: + return a_str.lstrip(u' ') + s = a.build_types(f, [int, annmodel.SomeUnicodeString(no_nul=True)]) + assert s.no_nul + def test_str_mul(self): a = self.RPythonAnnotator() def f(a_str): @@ -2042,6 +2100,17 @@ assert s.can_be_None assert s.no_nul + def test_unicode_noNUL_canbeNone(self): + def f(a): + if a: + return u"abc" + else: + return None + a = self.RPythonAnnotator() + s = a.build_types(f, [int]) + assert s.can_be_None + assert s.no_nul + def test_str_or_None(self): def f(a): if a: @@ -2058,6 +2127,22 @@ assert s.can_be_None assert s.no_nul + def test_unicode_or_None(self): + def f(a): + if a: + return u"abc" + else: + return None + def g(a): + x = f(a) + if x is None: + return u"abcd" + return x + a = self.RPythonAnnotator() + s = a.build_types(f, [int]) + assert s.can_be_None + assert s.no_nul + def test_emulated_pbc_call_simple(self): def f(a,b): return a + b @@ -2124,6 +2209,19 @@ assert isinstance(s, annmodel.SomeString) assert s.no_nul + def test_iteritems_unicode0(self): + def it(d): + return d.iteritems() + def f(): + d0 = {u'1a': u'2a', u'3': u'4'} + for item in it(d0): + return u"%s=%s" % item + raise ValueError + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeUnicodeString) + assert s.no_nul + def test_no_nul_mod(self): def f(x): s = "%d" % x @@ -2133,6 +2231,14 @@ assert isinstance(s, annmodel.SomeString) assert s.no_nul + def test_no_nul_mod_unicode(self): + def f(x): + s = u"%d" % x + return s + a = self.RPythonAnnotator() + s = a.build_types(f, [int]) + assert isinstance(s, annmodel.SomeUnicodeString) + assert s.no_nul def test_mul_str0(self): def f(s): @@ -2142,6 +2248,24 @@ assert isinstance(s, annmodel.SomeString) assert s.no_nul + a = self.RPythonAnnotator() + s = a.build_types(f, [annmodel.SomeUnicodeString(no_nul=True)]) + assert isinstance(s, annmodel.SomeUnicodeString) + assert s.no_nul + + def test_reverse_mul_str0(self): + def f(s): + return 10*s + a = self.RPythonAnnotator() + s = a.build_types(f, [annmodel.SomeString(no_nul=True)]) + assert isinstance(s, annmodel.SomeString) + assert s.no_nul + + a = self.RPythonAnnotator() + s = a.build_types(f, [annmodel.SomeUnicodeString(no_nul=True)]) + assert isinstance(s, annmodel.SomeUnicodeString) + assert s.no_nul + def test_getitem_str0(self): def f(s, n): if n == 1: @@ -2153,12 +2277,18 @@ return s a = self.RPythonAnnotator() a.translator.config.translation.check_str_without_nul = True - s = a.build_types(f, [annmodel.SomeString(no_nul=True), annmodel.SomeInteger()]) assert isinstance(s, annmodel.SomeString) assert s.no_nul + a = self.RPythonAnnotator() + a.translator.config.translation.check_str_without_nul = True + s = a.build_types(f, [annmodel.SomeUnicodeString(no_nul=True), + annmodel.SomeInteger()]) + assert isinstance(s, annmodel.SomeUnicodeString) + assert s.no_nul + def test_non_none_and_none_with_isinstance(self): class A(object): pass @@ -3411,6 +3541,7 @@ a = self.RPythonAnnotator() s = a.build_types(f, [unicode]) assert isinstance(s, annmodel.SomeUnicodeString) + assert s.no_nul def test_unicode_char(self): def f(x, i): @@ -3916,6 +4047,19 @@ assert s.can_be_None assert s.no_nul + def test_contains_no_nul_unicode(self): + def f(i): + if u"\0" in i: + return None + else: + return i + a = self.RPythonAnnotator() + a.translator.config.translation.check_str_without_nul = True + s = a.build_types(f, [annmodel.SomeUnicodeString(no_nul=False)]) + assert isinstance(s, annmodel.SomeUnicodeString) + assert s.can_be_None + assert s.no_nul + def test_no___call__(self): class X(object): def __call__(self): diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py --- a/rpython/annotator/unaryop.py +++ b/rpython/annotator/unaryop.py @@ -574,7 +574,9 @@ return self.basecharclass() def method_split(self, patt, max=-1): - if max == -1 and patt.is_constant() and patt.const == "\0": + # special-case for .split( '\x00') or .split(u'\x00') + if max == -1 and patt.is_constant() and ( + len(patt.const) == 1 and ord(patt.const) == 0): no_nul = True else: no_nul = self.no_nul diff --git a/rpython/config/translationoption.py b/rpython/config/translationoption.py --- a/rpython/config/translationoption.py +++ b/rpython/config/translationoption.py @@ -16,10 +16,11 @@ DEFL_GC = "incminimark" # XXX +DEFL_ROOTFINDER_WITHJIT = "shadowstack" if sys.platform.startswith("linux"): - DEFL_ROOTFINDER_WITHJIT = "asmgcc" -else: - DEFL_ROOTFINDER_WITHJIT = "shadowstack" + _mach = os.popen('uname -m', 'r').read().strip() + if _mach.startswith('x86') or _mach in ['i386', 'i486', 'i586', 'i686']: + DEFL_ROOTFINDER_WITHJIT = "asmgcc" # only for Linux on x86 / x86-64 IS_64_BITS = sys.maxint > 2147483647 diff --git a/rpython/jit/backend/arm/test/support.py b/rpython/jit/backend/arm/test/support.py --- a/rpython/jit/backend/arm/test/support.py +++ b/rpython/jit/backend/arm/test/support.py @@ -10,7 +10,9 @@ class JitARMMixin(support.LLJitMixin): type_system = 'lltype' CPUClass = getcpuclass() - basic = True + # we have to disable unroll + enable_opts = "intbounds:rewrite:virtualize:string:earlyforce:pure:heap" + basic = False def check_jumps(self, maxcount): pass diff --git a/rpython/jit/backend/arm/test/test_helper.py b/rpython/jit/backend/arm/test/test_helper.py --- a/rpython/jit/backend/arm/test/test_helper.py +++ b/rpython/jit/backend/arm/test/test_helper.py @@ -1,6 +1,8 @@ from rpython.jit.backend.arm.helper.assembler import count_reg_args -from rpython.jit.metainterp.history import (BoxInt, BoxPtr, BoxFloat, - INT, REF, FLOAT) +from rpython.jit.metainterp.history import INT, REF, FLOAT +from rpython.jit.metainterp.resoperation import InputArgInt as BoxInt +from rpython.jit.metainterp.resoperation import InputArgRef as BoxPtr +from rpython.jit.metainterp.resoperation import InputArgFloat as BoxFloat def test_count_reg_args(): diff --git a/rpython/jit/backend/arm/test/test_regalloc.py b/rpython/jit/backend/arm/test/test_regalloc.py --- a/rpython/jit/backend/arm/test/test_regalloc.py +++ b/rpython/jit/backend/arm/test/test_regalloc.py @@ -215,14 +215,14 @@ def test_exception_bridge_no_exception(self): ops = ''' [i0] - i1 = same_as(1) - call(ConstClass(raising_fptr), i0, descr=raising_calldescr) + i1 = same_as_i(1) + call_n(ConstClass(raising_fptr), i0, descr=raising_calldescr) guard_exception(ConstClass(zero_division_error)) [i1] finish(0) ''' bridge_ops = ''' [i3] - i2 = same_as(2) + i2 = same_as_i(2) guard_no_exception() [i2] finish(1) ''' @@ -379,7 +379,7 @@ def test_bug_wrong_stack_adj(self): ops = ''' [i0, i1, i2, i3, i4, i5, i6, i7, i8] - i9 = same_as(0) + i9 = same_as_i(0) guard_true(i0) [i9, i0, i1, i2, i3, i4, i5, i6, i7, i8] finish(1) ''' @@ -387,7 +387,7 @@ assert self.getint(0) == 0 bridge_ops = ''' [i9, i0, i1, i2, i3, i4, i5, i6, i7, i8] - call(ConstClass(raising_fptr), 0, descr=raising_calldescr) + call_n(ConstClass(raising_fptr), 0, descr=raising_calldescr) guard_true(i0) [i0, i1, i2, i3, i4, i5, i6, i7, i8] finish(1) ''' @@ -430,7 +430,7 @@ def test_cmp_op_0(self): ops = ''' [i0, i3] - i1 = same_as(1) + i1 = same_as_i(1) i2 = int_lt(i0, 100) guard_true(i3) [i1, i2] finish(i2) @@ -630,7 +630,7 @@ def test_one_call(self): ops = ''' [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9] - i10 = call(ConstClass(f1ptr), i0, descr=f1_calldescr) + i10 = call_i(ConstClass(f1ptr), i0, descr=f1_calldescr) guard_true(i10), [i10, i1, i2, i3, i4, i5, i6, i7, i8, i9] ''' self.interpret(ops, [4, 7, 9, 9, 9, 9, 9, 9, 9, 9]) @@ -639,8 +639,8 @@ def test_two_calls(self): ops = ''' [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9] - i10 = call(ConstClass(f1ptr), i0, descr=f1_calldescr) - i11 = call(ConstClass(f2ptr), i10, i1, descr=f2_calldescr) + i10 = call_i(ConstClass(f1ptr), i0, descr=f1_calldescr) + i11 = call_i(ConstClass(f2ptr), i10, i1, descr=f2_calldescr) guard_true(i11) [i11, i1, i2, i3, i4, i5, i6, i7, i8, i9] ''' self.interpret(ops, [4, 7, 9, 9, 9, 9, 9, 9, 9, 9]) @@ -649,7 +649,7 @@ def test_call_many_arguments(self): ops = ''' [i0, i1, i2, i3, i4, i5, i6, i7] - i8 = call(ConstClass(f10ptr), 1, i0, i1, i2, i3, i4, i5, i6, i7, 10, descr=f10_calldescr) + i8 = call_i(ConstClass(f10ptr), 1, i0, i1, i2, i3, i4, i5, i6, i7, 10, descr=f10_calldescr) finish(i8) ''' self.interpret(ops, [2, 3, 4, 5, 6, 7, 8, 9]) @@ -658,7 +658,7 @@ def test_bridge_calls_1(self): ops = ''' [i0, i1] - i2 = call(ConstClass(f1ptr), i0, descr=f1_calldescr) + i2 = call_i(ConstClass(f1ptr), i0, descr=f1_calldescr) guard_value(i2, 0, descr=fdescr1) [i2, i1] finish(i1) ''' @@ -666,7 +666,7 @@ assert self.getint(0) == 5 ops = ''' [i2, i1] - i3 = call(ConstClass(f2ptr), i2, i1, descr=f2_calldescr) + i3 = call_i(ConstClass(f2ptr), i2, i1, descr=f2_calldescr) finish(i3) ''' self.attach_bridge(ops, loop, -2) @@ -677,7 +677,7 @@ def test_bridge_calls_2(self): ops = ''' [i0, i1] - i2 = call(ConstClass(f2ptr), i0, i1, descr=f2_calldescr) + i2 = call_i(ConstClass(f2ptr), i0, i1, descr=f2_calldescr) guard_value(i2, 0, descr=fdescr1) [i2] finish(i1) ''' @@ -685,7 +685,7 @@ assert self.getint(0) == 4 * 7 ops = ''' [i2] - i3 = call(ConstClass(f1ptr), i2, descr=f1_calldescr) + i3 = call_i(ConstClass(f1ptr), i2, descr=f1_calldescr) finish(i3) ''' self.attach_bridge(ops, loop, -2) @@ -734,7 +734,7 @@ loop2 = """ [i0] i1 = force_token() - i2 = call_assembler(1,2,3,4,5,6,7,8,9,10,11, descr=looptoken) + i2 = call_assembler_i(1,2,3,4,5,6,7,8,9,10,11, descr=looptoken) guard_not_forced() [i0] guard_false(i0) [i0, i2] """ @@ -749,23 +749,23 @@ label(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, descr=targettoken) i11 = int_add(i0, 1) i12 = int_lt(i11, 2) - i13 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i14 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i15 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i16 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i17 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i18 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i19 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i20 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i21 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i22 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i23 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i24 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i26 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i27 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i28 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i29 = call(ConstClass(f_fptr), i12, descr=f_calldescr) - i30 = call(ConstClass(f_fptr), i12, descr=f_calldescr) + i13 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i14 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i15 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i16 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i17 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i18 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i19 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i20 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i21 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i22 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i23 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i24 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i26 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i27 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i28 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i29 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) + i30 = call_i(ConstClass(f_fptr), i12, descr=f_calldescr) guard_true(i12) [i11, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10] jump(i11, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, descr=targettoken) """ diff --git a/rpython/jit/backend/arm/test/test_regalloc2.py b/rpython/jit/backend/arm/test/test_regalloc2.py deleted file mode 100644 --- a/rpython/jit/backend/arm/test/test_regalloc2.py +++ /dev/null @@ -1,281 +0,0 @@ -import py -from rpython.jit.metainterp.history import ResOperation, BoxInt, ConstInt,\ - BoxPtr, ConstPtr, BasicFailDescr, BasicFinalDescr -from rpython.jit.metainterp.history import JitCellToken -from rpython.jit.metainterp.resoperation import rop -from rpython.jit.backend.detect_cpu import getcpuclass -from rpython.jit.backend.arm.arch import WORD -CPU = getcpuclass() - -def test_bug_rshift(): - v1 = BoxInt() - v2 = BoxInt() - v3 = BoxInt() - v4 = BoxInt() - inputargs = [v1] - operations = [ - ResOperation(rop.INT_ADD, [v1, v1], v2), - ResOperation(rop.INT_INVERT, [v2], v3), - ResOperation(rop.UINT_RSHIFT, [v1, ConstInt(3)], v4), - ResOperation(rop.GUARD_FALSE, [v1], None, descr=BasicFailDescr()), - ResOperation(rop.FINISH, [], None, descr=BasicFinalDescr(1)), - ] - operations[-2].setfailargs([v4, v3]) - cpu = CPU(None, None) - cpu.setup_once() - looptoken = JitCellToken() - cpu.compile_loop(inputargs, operations, looptoken) - deadframe = cpu.execute_token(looptoken, 9) - assert cpu.get_int_value(deadframe, 0) == (9 >> 3) - assert cpu.get_int_value(deadframe, 1) == (~18) - -def test_bug_int_is_true_1(): - v1 = BoxInt() - v2 = BoxInt() - v3 = BoxInt() - v4 = BoxInt() - tmp5 = BoxInt() - inputargs = [v1] - operations = [ - ResOperation(rop.INT_MUL, [v1, v1], v2), - ResOperation(rop.INT_MUL, [v2, v1], v3), - ResOperation(rop.INT_IS_TRUE, [v2], tmp5), - ResOperation(rop.INT_IS_ZERO, [tmp5], v4), - ResOperation(rop.GUARD_FALSE, [v1], None, descr=BasicFailDescr()), - ResOperation(rop.FINISH, [], None, descr=BasicFinalDescr()), - ] - operations[-2].setfailargs([v4, v3, tmp5]) - cpu = CPU(None, None) - cpu.setup_once() - looptoken = JitCellToken() - cpu.compile_loop(inputargs, operations, looptoken) - deadframe = cpu.execute_token(looptoken, -10) - assert cpu.get_int_value(deadframe, 0) == 0 - assert cpu.get_int_value(deadframe, 1) == -1000 - assert cpu.get_int_value(deadframe, 2) == 1 - -def test_bug_0(): - v1 = BoxInt() - v2 = BoxInt() - v3 = BoxInt() - v4 = BoxInt() - v5 = BoxInt() - v6 = BoxInt() - v7 = BoxInt() - v8 = BoxInt() - v9 = BoxInt() - v10 = BoxInt() - v11 = BoxInt() - v12 = BoxInt() - v13 = BoxInt() - v14 = BoxInt() - v15 = BoxInt() - v16 = BoxInt() - v17 = BoxInt() - v18 = BoxInt() - v19 = BoxInt() - v20 = BoxInt() - v21 = BoxInt() - v22 = BoxInt() - v23 = BoxInt() - v24 = BoxInt() - v25 = BoxInt() - v26 = BoxInt() - v27 = BoxInt() - v28 = BoxInt() - v29 = BoxInt() - v30 = BoxInt() - v31 = BoxInt() - v32 = BoxInt() - v33 = BoxInt() - v34 = BoxInt() - v35 = BoxInt() - v36 = BoxInt() - v37 = BoxInt() - v38 = BoxInt() - v39 = BoxInt() - v40 = BoxInt() - tmp41 = BoxInt() - tmp42 = BoxInt() - tmp43 = BoxInt() - tmp44 = BoxInt() - tmp45 = BoxInt() - tmp46 = BoxInt() - inputargs = [v1, v2, v3, v4, v5, v6, v7, v8, v9, v10] - operations = [ - ResOperation(rop.UINT_GT, [v3, ConstInt(-48)], v11), - ResOperation(rop.INT_XOR, [v8, v1], v12), - ResOperation(rop.INT_GT, [v6, ConstInt(-9)], v13), - ResOperation(rop.INT_LE, [v13, v2], v14), - ResOperation(rop.INT_LE, [v11, v5], v15), - ResOperation(rop.UINT_GE, [v13, v13], v16), - ResOperation(rop.INT_OR, [v9, ConstInt(-23)], v17), - ResOperation(rop.INT_LT, [v10, v13], v18), - ResOperation(rop.INT_OR, [v15, v5], v19), - ResOperation(rop.INT_XOR, [v17, ConstInt(54)], v20), - ResOperation(rop.INT_MUL, [v8, v10], v21), - ResOperation(rop.INT_OR, [v3, v9], v22), - ResOperation(rop.INT_AND, [v11, ConstInt(-4)], tmp41), - ResOperation(rop.INT_OR, [tmp41, ConstInt(1)], tmp42), - ResOperation(rop.INT_MOD, [v12, tmp42], v23), - ResOperation(rop.INT_IS_TRUE, [v6], v24), - ResOperation(rop.UINT_RSHIFT, [v15, ConstInt(6)], v25), - ResOperation(rop.INT_OR, [ConstInt(-4), v25], v26), - ResOperation(rop.INT_INVERT, [v8], v27), - ResOperation(rop.INT_SUB, [ConstInt(-113), v11], v28), - ResOperation(rop.INT_NEG, [v7], v29), - ResOperation(rop.INT_NEG, [v24], v30), - ResOperation(rop.INT_FLOORDIV, [v3, ConstInt(53)], v31), - ResOperation(rop.INT_MUL, [v28, v27], v32), - ResOperation(rop.INT_AND, [v18, ConstInt(-4)], tmp43), - ResOperation(rop.INT_OR, [tmp43, ConstInt(1)], tmp44), - ResOperation(rop.INT_MOD, [v26, tmp44], v33), - ResOperation(rop.INT_OR, [v27, v19], v34), - ResOperation(rop.UINT_LT, [v13, ConstInt(1)], v35), - ResOperation(rop.INT_AND, [v21, ConstInt(31)], tmp45), - ResOperation(rop.INT_RSHIFT, [v21, tmp45], v36), - ResOperation(rop.INT_AND, [v20, ConstInt(31)], tmp46), - ResOperation(rop.UINT_RSHIFT, [v4, tmp46], v37), - ResOperation(rop.UINT_GT, [v33, ConstInt(-11)], v38), - ResOperation(rop.INT_NEG, [v7], v39), - ResOperation(rop.INT_GT, [v24, v32], v40), - ResOperation(rop.GUARD_FALSE, [v1], None, descr=BasicFailDescr()), - ] - operations[-1].setfailargs([v40, v36, v37, v31, v16, v34, v35, v23, v22, v29, v14, v39, v30, v38]) - cpu = CPU(None, None) - cpu.setup_once() - looptoken = JitCellToken() - cpu.compile_loop(inputargs, operations, looptoken) - args = [-13 , 10 , 10 , 8 , -8 , -16 , -18 , 46 , -12 , 26] - deadframe = cpu.execute_token(looptoken, *args) - assert cpu.get_int_value(deadframe, 0) == 0 - assert cpu.get_int_value(deadframe, 1) == 0 - assert cpu.get_int_value(deadframe, 2) == 0 - assert cpu.get_int_value(deadframe, 3) == 0 - assert cpu.get_int_value(deadframe, 4) == 1 - assert cpu.get_int_value(deadframe, 5) == -7 - assert cpu.get_int_value(deadframe, 6) == 1 - assert cpu.get_int_value(deadframe, 7) == 0 - assert cpu.get_int_value(deadframe, 8) == -2 - assert cpu.get_int_value(deadframe, 9) == 18 - assert cpu.get_int_value(deadframe, 10) == 1 - assert cpu.get_int_value(deadframe, 11) == 18 - assert cpu.get_int_value(deadframe, 12) == -1 - assert cpu.get_int_value(deadframe, 13) == 0 - -def test_bug_1(): - v1 = BoxInt() - v2 = BoxInt() - v3 = BoxInt() - v4 = BoxInt() - v5 = BoxInt() - v6 = BoxInt() - v7 = BoxInt() - v8 = BoxInt() - v9 = BoxInt() - v10 = BoxInt() - v11 = BoxInt() - v12 = BoxInt() - v13 = BoxInt() - v14 = BoxInt() - v15 = BoxInt() - v16 = BoxInt() - v17 = BoxInt() - v18 = BoxInt() - v19 = BoxInt() - v20 = BoxInt() - v21 = BoxInt() - v22 = BoxInt() - v23 = BoxInt() - v24 = BoxInt() - v25 = BoxInt() - v26 = BoxInt() - v27 = BoxInt() - v28 = BoxInt() - v29 = BoxInt() - v30 = BoxInt() - v31 = BoxInt() - v32 = BoxInt() - v33 = BoxInt() - v34 = BoxInt() - v35 = BoxInt() - v36 = BoxInt() - v37 = BoxInt() - v38 = BoxInt() - v39 = BoxInt() - v40 = BoxInt() - tmp41 = BoxInt() - tmp42 = BoxInt() - tmp43 = BoxInt() - tmp44 = BoxInt() - tmp45 = BoxInt() - inputargs = [v1, v2, v3, v4, v5, v6, v7, v8, v9, v10] - operations = [ - ResOperation(rop.UINT_LT, [v6, ConstInt(0)], v11), - ResOperation(rop.INT_AND, [v3, ConstInt(31)], tmp41), - ResOperation(rop.INT_RSHIFT, [v3, tmp41], v12), - ResOperation(rop.INT_NEG, [v2], v13), - ResOperation(rop.INT_ADD, [v11, v7], v14), - ResOperation(rop.INT_OR, [v3, v2], v15), - ResOperation(rop.INT_OR, [v12, v12], v16), - ResOperation(rop.INT_NE, [v2, v5], v17), - ResOperation(rop.INT_AND, [v5, ConstInt(31)], tmp42), - ResOperation(rop.UINT_RSHIFT, [v14, tmp42], v18), - ResOperation(rop.INT_AND, [v14, ConstInt(31)], tmp43), - ResOperation(rop.INT_LSHIFT, [ConstInt(7), tmp43], v19), - ResOperation(rop.INT_NEG, [v19], v20), - ResOperation(rop.INT_MOD, [v3, ConstInt(1)], v21), - ResOperation(rop.UINT_GE, [v15, v1], v22), - ResOperation(rop.INT_AND, [v16, ConstInt(31)], tmp44), - ResOperation(rop.INT_LSHIFT, [v8, tmp44], v23), - ResOperation(rop.INT_IS_TRUE, [v17], v24), - ResOperation(rop.INT_AND, [v5, ConstInt(31)], tmp45), - ResOperation(rop.INT_LSHIFT, [v14, tmp45], v25), - ResOperation(rop.INT_LSHIFT, [v5, ConstInt(17)], v26), - ResOperation(rop.INT_EQ, [v9, v15], v27), - ResOperation(rop.INT_GE, [ConstInt(0), v6], v28), - ResOperation(rop.INT_NEG, [v15], v29), - ResOperation(rop.INT_NEG, [v22], v30), - ResOperation(rop.INT_ADD, [v7, v16], v31), - ResOperation(rop.UINT_LT, [v19, v19], v32), - ResOperation(rop.INT_ADD, [v2, ConstInt(1)], v33), - ResOperation(rop.INT_NEG, [v5], v34), - ResOperation(rop.INT_ADD, [v17, v24], v35), - ResOperation(rop.UINT_LT, [ConstInt(2), v16], v36), - ResOperation(rop.INT_NEG, [v9], v37), - ResOperation(rop.INT_GT, [v4, v11], v38), - ResOperation(rop.INT_LT, [v27, v22], v39), - ResOperation(rop.INT_NEG, [v27], v40), - ResOperation(rop.GUARD_FALSE, [v1], None, descr=BasicFailDescr()), - ] - operations[-1].setfailargs([v40, v10, v36, v26, v13, v30, v21, v33, v18, v25, v31, v32, v28, v29, v35, v38, v20, v39, v34, v23, v37]) - cpu = CPU(None, None) - cpu.setup_once() - looptoken = JitCellToken() - cpu.compile_loop(inputargs, operations, looptoken) - args = [17 , -20 , -6 , 6 , 1 , 13 , 13 , 9 , 49 , 8] - deadframe = cpu.execute_token(looptoken, *args) - assert cpu.get_int_value(deadframe, 0) == 0 - assert cpu.get_int_value(deadframe, 1) == 8 - assert cpu.get_int_value(deadframe, 2) == 1 - assert cpu.get_int_value(deadframe, 3) == 131072 - assert cpu.get_int_value(deadframe, 4) == 20 - assert cpu.get_int_value(deadframe, 5) == -1 - assert cpu.get_int_value(deadframe, 6) == 0 - assert cpu.get_int_value(deadframe, 7) == -19 - assert cpu.get_int_value(deadframe, 8) == 6 - assert cpu.get_int_value(deadframe, 9) == 26 - assert cpu.get_int_value(deadframe, 10) == 12 - assert cpu.get_int_value(deadframe, 11) == 0 - assert cpu.get_int_value(deadframe, 12) == 0 - assert cpu.get_int_value(deadframe, 13) == 2 - assert cpu.get_int_value(deadframe, 14) == 2 - assert cpu.get_int_value(deadframe, 15) == 1 - assert cpu.get_int_value(deadframe, 16) == -57344 - assert cpu.get_int_value(deadframe, 17) == 1 - assert cpu.get_int_value(deadframe, 18) == -1 - if WORD == 4: - assert cpu.get_int_value(deadframe, 19) == -2147483648 - elif WORD == 8: - assert cpu.get_int_value(deadframe, 19) == 19327352832 - assert cpu.get_int_value(deadframe, 20) == -49 diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -80,8 +80,8 @@ self.gc_size_of_header = gc_ll_descr.gcheaderbuilder.size_gc_header else: self.gc_size_of_header = WORD # for tests - self.memcpy_addr = self.cpu.cast_ptr_to_int(memcpy_fn) - self.memset_addr = self.cpu.cast_ptr_to_int(memset_fn) + self.memcpy_addr = rffi.cast(lltype.Signed, memcpy_fn) + self.memset_addr = rffi.cast(lltype.Signed, memset_fn) self._build_failure_recovery(False, withfloats=False) self._build_failure_recovery(True, withfloats=False) self._build_wb_slowpath(False) diff --git a/rpython/jit/backend/llsupport/codemap.py b/rpython/jit/backend/llsupport/codemap.py --- a/rpython/jit/backend/llsupport/codemap.py +++ b/rpython/jit/backend/llsupport/codemap.py @@ -15,7 +15,7 @@ from rpython.rlib.entrypoint import jit_entrypoint from rpython.rlib.rbisect import bisect_right, bisect_right_addr from rpython.rlib.rbisect import bisect_left, bisect_left_addr -from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.translator import cdir @@ -74,11 +74,12 @@ stack_depth_at_loc = llexternal('pypy_jit_stack_depth_at_loc', [lltype.Signed], lltype.Signed) find_codemap_at_addr = llexternal('pypy_find_codemap_at_addr', - [lltype.Signed, rffi.CArrayPtr(lltype.Signed)], lltype.Signed) + [lltype.Signed, rffi.CArrayPtr(lltype.Signed)], + llmemory.Address) yield_bytecode_at_addr = llexternal('pypy_yield_codemap_at_addr', - [lltype.Signed, lltype.Signed, + [llmemory.Address, lltype.Signed, rffi.CArrayPtr(lltype.Signed)], - lltype.Signed) + lltype.Signed) class CodemapStorage(object): 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 @@ -600,16 +600,22 @@ @specialize.argtype(1) def bh_getfield_gc_i(self, struct, fielddescr): ofs, size, sign = self.unpack_fielddescr_size(fielddescr) + if isinstance(lltype.typeOf(struct), lltype.Ptr): + fielddescr.check_correct_type(struct) return self.read_int_at_mem(struct, ofs, size, sign) @specialize.argtype(1) def bh_getfield_gc_r(self, struct, fielddescr): ofs = self.unpack_fielddescr(fielddescr) + if isinstance(lltype.typeOf(struct), lltype.Ptr): + fielddescr.check_correct_type(struct) return self.read_ref_at_mem(struct, ofs) @specialize.argtype(1) def bh_getfield_gc_f(self, struct, fielddescr): ofs = self.unpack_fielddescr(fielddescr) + if isinstance(lltype.typeOf(struct), lltype.Ptr): + fielddescr.check_correct_type(struct) return self.read_float_at_mem(struct, ofs) bh_getfield_raw_i = bh_getfield_gc_i diff --git a/rpython/jit/backend/test/calling_convention_test.py b/rpython/jit/backend/test/calling_convention_test.py --- a/rpython/jit/backend/test/calling_convention_test.py +++ b/rpython/jit/backend/test/calling_convention_test.py @@ -152,6 +152,7 @@ res = self.execute_operation(rop.CALL_F, [funcbox] + argslist, 'float', descr=calldescr) + res = longlong.getrealfloat(res) assert abs(res - result) < 0.0001 def test_call_aligned_with_args_on_the_stack(self): @@ -194,6 +195,7 @@ res = self.execute_operation(rop.CALL_F, [funcbox] + argslist, 'float', descr=calldescr) + res = longlong.getrealfloat(res) assert abs(res - result) < 0.0001 def test_call_alignment_call_assembler(self): diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -2293,6 +2293,7 @@ func_ptr = llhelper(lltype.Ptr(FUNC), func_void) calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, EffectInfo.MOST_GENERAL) + gfs = longlong.getfloatstorage for (operation, arg1, arg2_if_true, arg2_if_false) in [ ('int_lt', -5, 2, -5), @@ -2303,8 +2304,8 @@ ('int_xor', 7, 3, 7), # test without a comparison at all ('int_is_true', 4242, 1, 0), ('int_is_zero', 4242, 0, 1), - ('float_lt', -0.5, 0.2, -0.5), - ('float_eq', 1.1, 1.1, 1.2), + ('float_lt', gfs(-0.5), gfs(0.2), gfs(-0.5)), + ('float_eq', gfs(1.1), gfs(1.1), gfs(1.2)), ]: called = [] @@ -3788,10 +3789,61 @@ assert called == [finish_descr] del called[:] - # compile a replacement + # compile a replacement which needs more jitframe stack space ops = ''' [f0, f1] f2 = float_sub(f0, f1) + f3 = float_sub(f0, f1) + f4 = float_sub(f0, f1) + f5 = float_sub(f0, f1) + f6 = float_sub(f0, f1) + f7 = float_sub(f0, f1) + f8 = float_sub(f0, f1) + f9 = float_sub(f0, f1) + f10 = float_sub(f0, f1) + f11 = float_sub(f0, f1) + f12 = float_sub(f0, f1) + f13 = float_sub(f0, f1) + f14 = float_sub(f0, f1) + f15 = float_sub(f0, f1) + f16 = float_sub(f0, f1) + f17 = float_sub(f0, f1) + f18 = float_sub(f0, f1) + f19 = float_sub(f0, f1) + i3 = float_eq(f2, f3) + i4 = float_eq(f2, f4) + i5 = float_eq(f2, f5) + i6 = float_eq(f2, f6) + i7 = float_eq(f2, f7) + i8 = float_eq(f2, f8) + i9 = float_eq(f2, f9) + i10 = float_eq(f2, f10) + i11 = float_eq(f2, f11) + i12 = float_eq(f2, f12) + i13 = float_eq(f2, f13) + i14 = float_eq(f2, f14) + i15 = float_eq(f2, f15) + i16 = float_eq(f2, f16) + i17 = float_eq(f2, f17) + i18 = float_eq(f2, f18) + i19 = float_eq(f2, f19) + guard_true(i3) [] + guard_true(i4) [] + guard_true(i5) [] + guard_true(i6) [] + guard_true(i7) [] + guard_true(i8) [] + guard_true(i9) [] + guard_true(i10) [] + guard_true(i11) [] + guard_true(i12) [] + guard_true(i13) [] + guard_true(i14) [] + guard_true(i15) [] + guard_true(i16) [] + guard_true(i17) [] + guard_true(i18) [] + guard_true(i19) [] finish(f2)''' loop2 = parse(ops) looptoken2 = JitCellToken() @@ -3799,9 +3851,21 @@ self.cpu.compile_loop(loop2.inputargs, loop2.operations, looptoken2) finish_descr2 = loop2.operations[-1].getdescr() + # check the jitframeinfo + if isinstance(self.cpu, AbstractLLCPU): + num1 = looptoken.compiled_loop_token.frame_info.jfi_frame_depth + num2 = looptoken2.compiled_loop_token.frame_info.jfi_frame_depth + assert num1 < num2 + # install it self.cpu.redirect_call_assembler(looptoken, looptoken2) + # check that the jitframeinfo was updated + if isinstance(self.cpu, AbstractLLCPU): + num1 = looptoken.compiled_loop_token.frame_info.jfi_frame_depth + num2 = looptoken2.compiled_loop_token.frame_info.jfi_frame_depth + assert num1 == num2 + # now, our call_assembler should go to looptoken2 args = [longlong.getfloatstorage(6.0), longlong.getfloatstorage(1.5)] # 6.0-1.5 == 1.25+3.25 @@ -5000,3 +5064,56 @@ ]: self.execute_operation(rop.GUARD_SUBCLASS, [arg, klass], 'void') assert self.guard_failed == (not is_subclass) + + def test_bug_from_optimize_cond_call(self): + loop = parse(""" + [i0, i1] + i99 = int_sub(i0, i0) + force_spill(i99) + i2 = int_add(i0, i1) + i3 = int_add(i0, i1) + i4 = int_add(i0, i1) + i5 = int_add(i0, i1) + i6 = int_add(i0, i1) + i7 = int_add(i0, i1) + i8 = int_add(i0, i1) + i9 = int_add(i0, i1) + i10 = int_add(i0, i1) + i11 = int_add(i0, i1) + i12 = int_add(i0, i1) + i13 = int_add(i0, i1) + i14 = int_add(i0, i1) + i15 = int_add(i0, i1) + i16 = int_add(i0, i1) + i17 = int_add(i0, i1) + i18 = int_add(i0, i1) + i19 = int_add(i0, i1) + i20 = int_is_true(i99) + force_spill(i0) + force_spill(i1) + force_spill(i2) + force_spill(i3) + force_spill(i4) + force_spill(i5) + force_spill(i6) + force_spill(i7) + force_spill(i8) + force_spill(i9) + force_spill(i10) + force_spill(i11) + force_spill(i12) + force_spill(i13) + force_spill(i14) + force_spill(i15) + force_spill(i16) + force_spill(i17) + force_spill(i18) + force_spill(i19) + finish(i20, descr=finaldescr) + """, namespace={"finaldescr": BasicFinalDescr(1)}) + looptoken = JitCellToken() + self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) + deadframe = self.cpu.execute_token(looptoken, 40, 2) + fail = self.cpu.get_latest_descr(deadframe) + res = self.cpu.get_int_value(deadframe, 0) + assert res == 0 diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -175,12 +175,12 @@ for i in range(4): mc.MOV_sr(i * WORD, cond_call_register_arguments[i].value) mc.CALL(eax) + self._reload_frame_if_necessary(mc) if IS_X86_64: mc.ADD(esp, imm(WORD)) else: mc.ADD(esp, imm(WORD * 7)) self.set_extra_stack_depth(mc, 0) - self._reload_frame_if_necessary(mc, align_stack=True) self.pop_gcmap(mc) # cancel the push_gcmap(store=True) in the caller self._pop_all_regs_from_frame(mc, [], supports_floats, callee_only) mc.RET() @@ -244,14 +244,15 @@ mc.MOV_rs(edi.value, WORD * 3) # load the itemsize self.set_extra_stack_depth(mc, 16) mc.CALL(imm(follow_jump(addr))) + self._reload_frame_if_necessary(mc) mc.ADD_ri(esp.value, 16 - WORD) + self.set_extra_stack_depth(mc, 0) + # mc.TEST_rr(eax.value, eax.value) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit