Author: Richard Plangger <planri...@gmail.com> Branch: s390x-backend Changeset: r81423:b60fa730252e Date: 2015-12-22 18:45 +0100 http://bitbucket.org/pypy/pypy/changeset/b60fa730252e/
Log: catchup with default changes diff too long, truncating to 2000 out of 3312 lines diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO --- a/lib_pypy/cffi.egg-info/PKG-INFO +++ b/lib_pypy/cffi.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: cffi -Version: 1.4.0 +Version: 1.4.1 Summary: Foreign Function Interface for Python calling C code. Home-page: http://cffi.readthedocs.org Author: Armin Rigo, Maciej Fijalkowski diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py --- a/lib_pypy/cffi/__init__.py +++ b/lib_pypy/cffi/__init__.py @@ -4,8 +4,8 @@ from .api import FFI, CDefError, FFIError from .ffiplatform import VerificationError, VerificationMissing -__version__ = "1.4.0" -__version_info__ = (1, 4, 0) +__version__ = "1.4.1" +__version_info__ = (1, 4, 1) # The verifier module file names are based on the CRC32 of a string that # contains the following version number. It may be older than __version__ diff --git a/pypy/doc/embedding.rst b/pypy/doc/embedding.rst --- a/pypy/doc/embedding.rst +++ b/pypy/doc/embedding.rst @@ -130,8 +130,13 @@ More complete example --------------------- -.. note:: This example depends on pypy_execute_source_ptr which is not available - in PyPy <= 2.2.1. +.. note:: Note that we do not make use of ``extern "Python"``, the new + way to do callbacks in CFFI 1.4: this is because these examples use + the ABI mode, not the API mode, and with the ABI mode you still have + to use ``ffi.callback()``. It is work in progress to integrate + ``extern "Python"`` with the idea of embedding (and it is expected + to ultimately lead to a better way to do embedding than the one + described here, and that would work equally well on CPython and PyPy). Typically we need something more to do than simply execute source. The following is a fully fledged example, please consult cffi documentation for details. 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 @@ -73,3 +73,20 @@ Move wrappers for OS functions from `rpython/rtyper` to `rpython/rlib` and turn them into regular RPython functions. Most RPython-compatible `os.*` functions are now directly accessible as `rpython.rposix.*`. + +.. branch: always-enable-gil + +Simplify a bit the GIL handling in non-jitted code. Fixes issue #2205. + +.. branch: flowspace-cleanups + +Trivial cleanups in flowspace.operation : fix comment & duplicated method + +.. branch: test-AF_NETLINK +.. branch: small-cleanups-misc +.. branch: cpyext-slotdefs +.. branch: fix-missing-canraise + +.. branch: fix-2211 + +Fix the cryptic exception message when attempting to use extended slicing in rpython diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py --- a/pypy/module/_cffi_backend/__init__.py +++ b/pypy/module/_cffi_backend/__init__.py @@ -2,7 +2,7 @@ from pypy.interpreter.mixedmodule import MixedModule from rpython.rlib import rdynload, clibffi -VERSION = "1.4.0" +VERSION = "1.4.2" FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI try: diff --git a/pypy/module/_cffi_backend/call_python.py b/pypy/module/_cffi_backend/call_python.py --- a/pypy/module/_cffi_backend/call_python.py +++ b/pypy/module/_cffi_backend/call_python.py @@ -40,10 +40,9 @@ at least 8 bytes in size. """ from pypy.module._cffi_backend.ccallback import reveal_callback + from rpython.rlib import rgil - after = rffi.aroundstate.after - if after: - after() + rgil.acquire() rffi.stackcounter.stacks_counter += 1 llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py @@ -71,9 +70,7 @@ cerrno._errno_before(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO) rffi.stackcounter.stacks_counter -= 1 - before = rffi.aroundstate.before - if before: - before() + rgil.release() def get_ll_cffi_call_python(): diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -1,7 +1,7 @@ # ____________________________________________________________ import sys -assert __version__ == "1.4.0", ("This test_c.py file is for testing a version" +assert __version__ == "1.4.2", ("This test_c.py file is for testing a version" " of cffi that differs from the one that we" " get from 'import _cffi_backend'") if sys.version_info < (3,): diff --git a/pypy/module/_file/test/test_large_file.py b/pypy/module/_file/test/test_large_file.py --- a/pypy/module/_file/test/test_large_file.py +++ b/pypy/module/_file/test/test_large_file.py @@ -1,4 +1,4 @@ -import py +import py, sys from pypy.module._file.test.test_file import getfile @@ -13,6 +13,12 @@ def setup_method(self, meth): if getattr(meth, 'need_sparse_files', False): from rpython.translator.c.test.test_extfunc import need_sparse_files + if sys.maxsize < 2**32 and not self.runappdirect: + # this fails because it uses ll2ctypes to call the posix + # functions like 'open' and 'lseek', whereas a real compiled + # C program would macro-define them to their longlong versions + py.test.skip("emulation of files can't use " + "larger-than-long offsets") need_sparse_files() def test_large_seek_offsets(self): 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 @@ -251,7 +251,7 @@ from pypy.module._socket.interp_socket import addr_as_object if not hasattr(rsocket._c, 'sockaddr_ll'): py.test.skip("posix specific test") - # HACK: To get the correct interface numer of lo, which in most cases is 1, + # HACK: To get the correct interface number of lo, which in most cases is 1, # but can be anything (i.e. 39), we need to call the libc function # if_nametoindex to get the correct index import ctypes @@ -513,7 +513,7 @@ def test_getsetsockopt(self): import _socket as socket import struct - # A socket sould start with reuse == 0 + # A socket should start with reuse == 0 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) reuse = s.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR) assert reuse == 0 @@ -627,6 +627,26 @@ self.foo = _socket.socket() +class AppTestNetlink: + def setup_class(cls): + if not hasattr(os, 'getpid'): + py.test.skip("AF_NETLINK needs os.getpid()") + w_ok = space.appexec([], "(): import _socket; " + + "return hasattr(_socket, 'AF_NETLINK')") + if not space.is_true(w_ok): + py.test.skip("no AF_NETLINK on this platform") + cls.space = space + + def test_connect_to_kernel_netlink_routing_socket(self): + import _socket, os + s = _socket.socket(_socket.AF_NETLINK, _socket.SOCK_DGRAM, _socket.NETLINK_ROUTE) + assert s.getsockname() == (0L, 0L) + s.bind((0, 0)) + a, b = s.getsockname() + assert a == os.getpid() + assert b == 0 + + class AppTestPacket: def setup_class(cls): if not hasattr(os, 'getuid') or os.getuid() != 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 @@ -124,7 +124,7 @@ METH_COEXIST METH_STATIC METH_CLASS METH_NOARGS METH_VARARGS METH_KEYWORDS METH_O Py_TPFLAGS_HEAPTYPE Py_TPFLAGS_HAVE_CLASS -Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE +Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE Py_TPFLAGS_CHECKTYPES """.split() for name in constant_names: setattr(CConfig_constants, name, rffi_platform.ConstantInteger(name)) @@ -602,6 +602,7 @@ # Make the wrapper for the cases (1) and (2) def make_wrapper(space, callable, gil=None): "NOT_RPYTHON" + from rpython.rlib import rgil names = callable.api_func.argnames argtypes_enum_ui = unrolling_iterable(enumerate(zip(callable.api_func.argtypes, [name.startswith("w_") for name in names]))) @@ -617,9 +618,7 @@ # we hope that malloc removal removes the newtuple() that is # inserted exactly here by the varargs specializer if gil_acquire: - after = rffi.aroundstate.after - if after: - after() + rgil.acquire() rffi.stackcounter.stacks_counter += 1 llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py retval = fatal_value @@ -692,9 +691,7 @@ pypy_debug_catch_fatal_exception() rffi.stackcounter.stacks_counter -= 1 if gil_release: - before = rffi.aroundstate.before - if before: - before() + rgil.release() return retval callable._always_inline_ = 'try' wrapper.__name__ = "wrapper for %r" % (callable, ) diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -4,14 +4,14 @@ from rpython.rtyper.lltypesystem import rffi, lltype from pypy.module.cpyext.api import ( - cpython_api, generic_cpy_call, PyObject, Py_ssize_t) + cpython_api, generic_cpy_call, PyObject, Py_ssize_t, Py_TPFLAGS_CHECKTYPES) from pypy.module.cpyext.typeobjectdefs import ( unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc, getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc, inquiry, ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc, cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc, readbufferproc) -from pypy.module.cpyext.pyobject import from_ref +from pypy.module.cpyext.pyobject import from_ref, make_ref, Py_DecRef from pypy.module.cpyext.pyerrors import PyErr_Occurred from pypy.module.cpyext.state import State from pypy.interpreter.error import OperationError, oefmt @@ -65,22 +65,24 @@ func_binary = rffi.cast(binaryfunc, func) check_num_args(space, w_args, 1) args_w = space.fixedview(w_args) - - if not space.is_true(space.issubtype(space.type(args_w[0]), - space.type(w_self))): + ref = make_ref(space, w_self) + if (not ref.c_ob_type.c_tp_flags & Py_TPFLAGS_CHECKTYPES and + not space.is_true(space.issubtype(space.type(args_w[0]), + space.type(w_self)))): return space.w_NotImplemented - + Py_DecRef(space, ref) return generic_cpy_call(space, func_binary, w_self, args_w[0]) def wrap_binaryfunc_r(space, w_self, w_args, func): func_binary = rffi.cast(binaryfunc, func) check_num_args(space, w_args, 1) args_w = space.fixedview(w_args) - - if not space.is_true(space.issubtype(space.type(args_w[0]), - space.type(w_self))): + ref = make_ref(space, w_self) + if (not ref.c_ob_type.c_tp_flags & Py_TPFLAGS_CHECKTYPES and + not space.is_true(space.issubtype(space.type(args_w[0]), + space.type(w_self)))): return space.w_NotImplemented - + Py_DecRef(space, ref) return generic_cpy_call(space, func_binary, args_w[0], w_self) def wrap_inquirypred(space, w_self, w_args, func): diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -591,45 +591,92 @@ def test_binaryfunc(self): module = self.import_extension('foo', [ - ("new_obj", "METH_NOARGS", + ("newInt", "METH_VARARGS", """ - FooObject *fooObj; + IntLikeObject *intObj; + long intval; - Foo_Type.tp_as_number = &foo_as_number; - foo_as_number.nb_add = foo_nb_add_call; - if (PyType_Ready(&Foo_Type) < 0) return NULL; - fooObj = PyObject_New(FooObject, &Foo_Type); - if (!fooObj) { + if (!PyArg_ParseTuple(args, "i", &intval)) + return NULL; + + IntLike_Type.tp_as_number = &intlike_as_number; + IntLike_Type.tp_flags |= Py_TPFLAGS_CHECKTYPES; + intlike_as_number.nb_add = intlike_nb_add; + if (PyType_Ready(&IntLike_Type) < 0) return NULL; + intObj = PyObject_New(IntLikeObject, &IntLike_Type); + if (!intObj) { return NULL; } - return (PyObject *)fooObj; + intObj->ival = intval; + return (PyObject *)intObj; + """), + ("newIntNoOp", "METH_VARARGS", + """ + IntLikeObjectNoOp *intObjNoOp; + long intval; + + if (!PyArg_ParseTuple(args, "i", &intval)) + return NULL; + + IntLike_Type_NoOp.tp_flags |= Py_TPFLAGS_CHECKTYPES; + if (PyType_Ready(&IntLike_Type_NoOp) < 0) return NULL; + intObjNoOp = PyObject_New(IntLikeObjectNoOp, &IntLike_Type_NoOp); + if (!intObjNoOp) { + return NULL; + } + + intObjNoOp->ival = intval; + return (PyObject *)intObjNoOp; """)], """ typedef struct { PyObject_HEAD - } FooObject; + long ival; + } IntLikeObject; static PyObject * - foo_nb_add_call(PyObject *self, PyObject *other) + intlike_nb_add(PyObject *self, PyObject *other) { - return PyInt_FromLong(42); + long val1 = ((IntLikeObject *)(self))->ival; + if (PyInt_Check(other)) { + long val2 = PyInt_AsLong(other); + return PyInt_FromLong(val1+val2); + } + + long val2 = ((IntLikeObject *)(other))->ival; + return PyInt_FromLong(val1+val2); } - PyTypeObject Foo_Type = { + PyTypeObject IntLike_Type = { PyObject_HEAD_INIT(0) /*ob_size*/ 0, - /*tp_name*/ "Foo", - /*tp_basicsize*/ sizeof(FooObject), + /*tp_name*/ "IntLike", + /*tp_basicsize*/ sizeof(IntLikeObject), }; - static PyNumberMethods foo_as_number; + static PyNumberMethods intlike_as_number; + + typedef struct + { + PyObject_HEAD + long ival; + } IntLikeObjectNoOp; + + PyTypeObject IntLike_Type_NoOp = { + PyObject_HEAD_INIT(0) + /*ob_size*/ 0, + /*tp_name*/ "IntLikeNoOp", + /*tp_basicsize*/ sizeof(IntLikeObjectNoOp), + }; """) - a = module.new_obj() - b = module.new_obj() + a = module.newInt(1) + b = module.newInt(2) c = 3 - assert (a + b) == 42 - raises(TypeError, "b + c") + d = module.newIntNoOp(4) + assert (a + b) == 3 + assert (b + c) == 5 + assert (d + a) == 5 def test_tp_new_in_subclass_of_type(self): skip("BROKEN") diff --git a/pypy/module/mmap/test/test_mmap.py b/pypy/module/mmap/test/test_mmap.py --- a/pypy/module/mmap/test/test_mmap.py +++ b/pypy/module/mmap/test/test_mmap.py @@ -1,6 +1,6 @@ from __future__ import with_statement from rpython.tool.udir import udir -import os +import os, sys, py class AppTestMMap: spaceconfig = dict(usemodules=('mmap',)) @@ -8,6 +8,15 @@ def setup_class(cls): cls.w_tmpname = cls.space.wrap(str(udir.join('mmap-'))) + def setup_method(self, meth): + if getattr(meth, 'is_large', False): + if sys.maxsize < 2**32 and not self.runappdirect: + # this fails because it uses ll2ctypes to call the posix + # functions like 'open' and 'lseek', whereas a real compiled + # C program would macro-define them to their longlong versions + py.test.skip("emulation of files can't use " + "larger-than-long offsets") + def test_page_size(self): import mmap assert mmap.PAGESIZE > 0 @@ -648,6 +657,7 @@ assert m[0xFFFFFFF] == b'A' finally: m.close() + test_large_offset.is_large = True def test_large_filesize(self): import mmap @@ -665,6 +675,7 @@ assert m.size() == 0x180000000 finally: m.close() + test_large_filesize.is_large = True def test_all(self): # this is a global test, ported from test_mmap.py diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -93,6 +93,12 @@ def setup_method(self, meth): if getattr(meth, 'need_sparse_files', False): + if sys.maxsize < 2**32 and not self.runappdirect: + # this fails because it uses ll2ctypes to call the posix + # functions like 'open' and 'lseek', whereas a real compiled + # C program would macro-define them to their longlong versions + py.test.skip("emulation of files can't use " + "larger-than-long offsets") need_sparse_files() def test_posix_is_pypy_s(self): diff --git a/pypy/module/signal/__init__.py b/pypy/module/signal/__init__.py --- a/pypy/module/signal/__init__.py +++ b/pypy/module/signal/__init__.py @@ -48,3 +48,6 @@ use_bytecode_counter=False) space.actionflag.__class__ = interp_signal.SignalActionFlag # xxx yes I know the previous line is a hack + + def startup(self, space): + space.check_signal_action.startup(space) diff --git a/pypy/module/signal/interp_signal.py b/pypy/module/signal/interp_signal.py --- a/pypy/module/signal/interp_signal.py +++ b/pypy/module/signal/interp_signal.py @@ -63,19 +63,25 @@ AsyncAction.__init__(self, space) self.pending_signal = -1 self.fire_in_another_thread = False - if self.space.config.objspace.usemodules.thread: - from pypy.module.thread import gil - gil.after_thread_switch = self._after_thread_switch + # + @rgc.no_collect + def _after_thread_switch(): + if self.fire_in_another_thread: + if self.space.threadlocals.signals_enabled(): + self.fire_in_another_thread = False + self.space.actionflag.rearm_ticker() + # this occurs when we just switched to the main thread + # and there is a signal pending: we force the ticker to + # -1, which should ensure perform() is called quickly. + self._after_thread_switch = _after_thread_switch + # ^^^ so that 'self._after_thread_switch' can be annotated as a + # constant - @rgc.no_collect - def _after_thread_switch(self): - if self.fire_in_another_thread: - if self.space.threadlocals.signals_enabled(): - self.fire_in_another_thread = False - self.space.actionflag.rearm_ticker() - # this occurs when we just switched to the main thread - # and there is a signal pending: we force the ticker to - # -1, which should ensure perform() is called quickly. + def startup(self, space): + # this is translated + if space.config.objspace.usemodules.thread: + from rpython.rlib import rgil + rgil.invoke_after_thread_switch(self._after_thread_switch) def perform(self, executioncontext, frame): self._poll_for_signals() diff --git a/pypy/module/thread/gil.py b/pypy/module/thread/gil.py --- a/pypy/module/thread/gil.py +++ b/pypy/module/thread/gil.py @@ -11,7 +11,6 @@ from pypy.module.thread.error import wrap_thread_error from pypy.interpreter.executioncontext import PeriodicAsyncAction from pypy.module.thread.threadlocals import OSThreadLocals -from rpython.rlib.objectmodel import invoke_around_extcall class GILThreadLocals(OSThreadLocals): """A version of OSThreadLocals that enforces a GIL.""" @@ -23,34 +22,21 @@ space.actionflag.register_periodic_action(GILReleaseAction(space), use_bytecode_counter=True) - def _initialize_gil(self, space): - rgil.gil_allocate() - def setup_threads(self, space): """Enable threads in the object space, if they haven't already been.""" if not self.gil_ready: - self._initialize_gil(space) + # Note: this is a quasi-immutable read by module/pypyjit/interp_jit + # It must be changed (to True) only if it was really False before + rgil.allocate() self.gil_ready = True result = True else: result = False # already set up - - # add the GIL-releasing callback around external function calls. - # - # XXX we assume a single space, but this is not quite true during - # testing; for example, if you run the whole of test_lock you get - # a deadlock caused by the first test's space being reused by - # test_lock_again after the global state was cleared by - # test_compile_lock. As a workaround, we repatch these global - # fields systematically. - invoke_around_extcall(before_external_call, after_external_call) return result - def reinit_threads(self, space): - "Called in the child process after a fork()" - OSThreadLocals.reinit_threads(self, space) - if self.gil_ready: # re-initialize the gil if needed - self._initialize_gil(space) + ## def reinit_threads(self, space): + ## "Called in the child process after a fork()" + ## OSThreadLocals.reinit_threads(self, space) class GILReleaseAction(PeriodicAsyncAction): @@ -59,43 +45,4 @@ """ def perform(self, executioncontext, frame): - do_yield_thread() - - -after_thread_switch = lambda: None # hook for signal.py - -def before_external_call(): - # this function must not raise, in such a way that the exception - # transformer knows that it cannot raise! - rgil.gil_release() -before_external_call._gctransformer_hint_cannot_collect_ = True -before_external_call._dont_reach_me_in_del_ = True - -def after_external_call(): - rgil.gil_acquire() - rthread.gc_thread_run() - after_thread_switch() -after_external_call._gctransformer_hint_cannot_collect_ = True -after_external_call._dont_reach_me_in_del_ = True - -# The _gctransformer_hint_cannot_collect_ hack is needed for -# translations in which the *_external_call() functions are not inlined. -# They tell the gctransformer not to save and restore the local GC -# pointers in the shadow stack. This is necessary because the GIL is -# not held after the call to before_external_call() or before the call -# to after_external_call(). - -def do_yield_thread(): - # explicitly release the gil, in a way that tries to give more - # priority to other threads (as opposed to continuing to run in - # the same thread). - if rgil.gil_yield_thread(): - rthread.gc_thread_run() - after_thread_switch() -do_yield_thread._gctransformer_hint_close_stack_ = True -do_yield_thread._dont_reach_me_in_del_ = True -do_yield_thread._dont_inline_ = True - -# do_yield_thread() needs a different hint: _gctransformer_hint_close_stack_. -# The *_external_call() functions are themselves called only from the rffi -# module from a helper function that also has this hint. + rgil.yield_thread() diff --git a/pypy/module/thread/test/support.py b/pypy/module/thread/test/support.py --- a/pypy/module/thread/test/support.py +++ b/pypy/module/thread/test/support.py @@ -5,7 +5,7 @@ import errno from pypy.interpreter.gateway import interp2app, unwrap_spec -from pypy.module.thread import gil +from rpython.rlib import rgil NORMAL_TIMEOUT = 300.0 # 5 minutes @@ -15,9 +15,9 @@ adaptivedelay = 0.04 limit = time.time() + delay * NORMAL_TIMEOUT while time.time() <= limit: - gil.before_external_call() + rgil.release() time.sleep(adaptivedelay) - gil.after_external_call() + rgil.acquire() gc.collect() if space.is_true(space.call_function(w_condition)): return diff --git a/pypy/module/thread/test/test_gil.py b/pypy/module/thread/test/test_gil.py --- a/pypy/module/thread/test/test_gil.py +++ b/pypy/module/thread/test/test_gil.py @@ -1,5 +1,6 @@ import time from pypy.module.thread import gil +from rpython.rlib import rgil from rpython.rlib.test import test_rthread from rpython.rlib import rthread as thread from rpython.rlib.objectmodel import we_are_translated @@ -55,7 +56,7 @@ assert state.datalen3 == len(state.data) assert state.datalen4 == len(state.data) debug_print(main, i, state.datalen4) - gil.do_yield_thread() + rgil.yield_thread() assert i == j j += 1 def bootstrap(): @@ -82,9 +83,9 @@ if not still_waiting: raise ValueError("time out") still_waiting -= 1 - if not we_are_translated(): gil.before_external_call() + if not we_are_translated(): rgil.release() time.sleep(0.01) - if not we_are_translated(): gil.after_external_call() + if not we_are_translated(): rgil.acquire() debug_print("leaving!") i1 = i2 = 0 for tid, i in state.data: diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py --- a/pypy/objspace/std/listobject.py +++ b/pypy/objspace/std/listobject.py @@ -521,7 +521,6 @@ def descr_getitem(self, space, w_index): if isinstance(w_index, W_SliceObject): - # XXX consider to extend rlist's functionality? length = self.length() start, stop, step, slicelength = w_index.indices4(space, length) assert slicelength >= 0 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 @@ -3516,6 +3516,32 @@ s = a.build_types(f, [unicode]) assert isinstance(s, annmodel.SomeUnicodeString) + def test_extended_slice(self): + a = self.RPythonAnnotator() + def f(start, end, step): + return [1, 2, 3][start:end:step] + with py.test.raises(AnnotatorError): + a.build_types(f, [int, int, int]) + a = self.RPythonAnnotator() + with py.test.raises(AnnotatorError): + a.build_types(f, [annmodel.SomeInteger(nonneg=True), + annmodel.SomeInteger(nonneg=True), + annmodel.SomeInteger(nonneg=True)]) + def f(x): + return x[::-1] + a = self.RPythonAnnotator() + with py.test.raises(AnnotatorError): + a.build_types(f, [str]) + def f(x): + return x[::2] + a = self.RPythonAnnotator() + with py.test.raises(AnnotatorError): + a.build_types(f, [str]) + def f(x): + return x[1:2:1] + a = self.RPythonAnnotator() + with py.test.raises(AnnotatorError): + a.build_types(f, [str]) def test_negative_slice(self): def f(s, e): diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py --- a/rpython/annotator/unaryop.py +++ b/rpython/annotator/unaryop.py @@ -441,7 +441,7 @@ def dict_contains(s_dct, s_element, position): s_dct.dictdef.generalize_key(s_element) if s_dct._is_empty(position): - s_bool =SomeBool() + s_bool = SomeBool() s_bool.const = False return s_bool return s_Bool diff --git a/rpython/flowspace/operation.py b/rpython/flowspace/operation.py --- a/rpython/flowspace/operation.py +++ b/rpython/flowspace/operation.py @@ -1,5 +1,5 @@ """ -This module defines all the SpaceOeprations used in rpython.flowspace. +This module defines all the SpaceOperations used in rpython.flowspace. """ import __builtin__ @@ -196,21 +196,6 @@ return cls._dispatch(type(s_arg)) @classmethod - def get_specialization(cls, s_arg, *_ignored): - try: - impl = getattr(s_arg, cls.opname) - - def specialized(annotator, arg, *other_args): - return impl(*[annotator.annotation(x) for x in other_args]) - try: - specialized.can_only_throw = impl.can_only_throw - except AttributeError: - pass - return specialized - except AttributeError: - return cls._dispatch(type(s_arg)) - - @classmethod def register_transform(cls, Some_cls): def decorator(func): cls._transform[Some_cls] = func @@ -523,6 +508,14 @@ *[annotator.annotation(arg) for arg in self.args]) +class NewSlice(HLOperation): + opname = 'newslice' + canraise = [] + + def consider(self, annotator): + raise AnnotatorError("Cannot use extended slicing in rpython") + + class Pow(PureOperation): opname = 'pow' arity = 3 diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -19,7 +19,6 @@ from rpython.jit.backend.arm.locations import imm, RawSPStackLocation from rpython.jit.backend.llsupport import symbolic from rpython.jit.backend.llsupport.gcmap import allocate_gcmap -from rpython.jit.backend.llsupport.descr import InteriorFieldDescr from rpython.jit.backend.llsupport.assembler import GuardToken, BaseAssembler from rpython.jit.backend.llsupport.regalloc import get_scale from rpython.jit.metainterp.history import (AbstractFailDescr, ConstInt, @@ -655,31 +654,24 @@ pmc.B_offs(offset, c.EQ) return fcond - def emit_op_setfield_gc(self, op, arglocs, regalloc, fcond): - value_loc, base_loc, ofs, size = arglocs - scale = get_scale(size.value) - self._write_to_mem(value_loc, base_loc, - ofs, imm(scale), fcond) + def emit_op_gc_store(self, op, arglocs, regalloc, fcond): + value_loc, base_loc, ofs_loc, size_loc = arglocs + scale = get_scale(size_loc.value) + self._write_to_mem(value_loc, base_loc, ofs_loc, imm(scale), fcond) return fcond - emit_op_setfield_raw = emit_op_setfield_gc - emit_op_zero_ptr_field = emit_op_setfield_gc - - def _genop_getfield(self, op, arglocs, regalloc, fcond): - base_loc, ofs, res, size = arglocs - signed = op.getdescr().is_field_signed() - scale = get_scale(size.value) - self._load_from_mem(res, base_loc, ofs, imm(scale), signed, fcond) + def _emit_op_gc_load(self, op, arglocs, regalloc, fcond): + base_loc, ofs_loc, res_loc, nsize_loc = arglocs + nsize = nsize_loc.value + signed = (nsize < 0) + scale = get_scale(abs(nsize)) + self._load_from_mem(res_loc, base_loc, ofs_loc, imm(scale), + signed, fcond) return fcond - emit_op_getfield_gc_i = _genop_getfield - emit_op_getfield_gc_r = _genop_getfield - emit_op_getfield_gc_f = _genop_getfield - emit_op_getfield_gc_pure_i = _genop_getfield - emit_op_getfield_gc_pure_r = _genop_getfield - emit_op_getfield_gc_pure_f = _genop_getfield - emit_op_getfield_raw_i = _genop_getfield - emit_op_getfield_raw_f = _genop_getfield + emit_op_gc_load_i = _emit_op_gc_load + emit_op_gc_load_r = _emit_op_gc_load + emit_op_gc_load_f = _emit_op_gc_load def emit_op_increment_debug_counter(self, op, arglocs, regalloc, fcond): base_loc, value_loc = arglocs @@ -688,68 +680,21 @@ self.mc.STR_ri(value_loc.value, base_loc.value, 0, cond=fcond) return fcond - def _genop_getinteriorfield(self, op, arglocs, regalloc, fcond): - (base_loc, index_loc, res_loc, - ofs_loc, ofs, itemsize, fieldsize) = arglocs - scale = get_scale(fieldsize.value) - tmploc, save = self.get_tmp_reg([base_loc, ofs_loc]) - assert not save - self.mc.gen_load_int(tmploc.value, itemsize.value) - self.mc.MUL(tmploc.value, index_loc.value, tmploc.value) - descr = op.getdescr() - assert isinstance(descr, InteriorFieldDescr) - signed = descr.fielddescr.is_field_signed() - if ofs.value > 0: - if ofs_loc.is_imm(): - self.mc.ADD_ri(tmploc.value, tmploc.value, ofs_loc.value) - else: - self.mc.ADD_rr(tmploc.value, tmploc.value, ofs_loc.value) - ofs_loc = tmploc - self._load_from_mem(res_loc, base_loc, ofs_loc, - imm(scale), signed, fcond) - return fcond - - emit_op_getinteriorfield_gc_i = _genop_getinteriorfield - emit_op_getinteriorfield_gc_r = _genop_getinteriorfield - emit_op_getinteriorfield_gc_f = _genop_getinteriorfield - - def emit_op_setinteriorfield_gc(self, op, arglocs, regalloc, fcond): - (base_loc, index_loc, value_loc, - ofs_loc, ofs, itemsize, fieldsize) = arglocs - scale = get_scale(fieldsize.value) - tmploc, save = self.get_tmp_reg([base_loc, index_loc, value_loc, ofs_loc]) - assert not save - self.mc.gen_load_int(tmploc.value, itemsize.value) - self.mc.MUL(tmploc.value, index_loc.value, tmploc.value) - if ofs.value > 0: - if ofs_loc.is_imm(): - self.mc.ADD_ri(tmploc.value, tmploc.value, ofs_loc.value) - else: - self.mc.ADD_rr(tmploc.value, tmploc.value, ofs_loc.value) - self._write_to_mem(value_loc, base_loc, tmploc, imm(scale), fcond) - return fcond - emit_op_setinteriorfield_raw = emit_op_setinteriorfield_gc - - def emit_op_arraylen_gc(self, op, arglocs, regalloc, fcond): - res, base_loc, ofs = arglocs - self.load_reg(self.mc, res, base_loc, ofs.value) - return fcond - - def emit_op_setarrayitem_gc(self, op, arglocs, regalloc, fcond): - value_loc, base_loc, ofs_loc, scale, ofs = arglocs - assert ofs_loc.is_core_reg() - if scale.value > 0: - self.mc.LSL_ri(r.ip.value, ofs_loc.value, scale.value) - ofs_loc = r.ip - + def emit_op_gc_store_indexed(self, op, arglocs, regalloc, fcond): + value_loc, base_loc, index_loc, size_loc, ofs_loc = arglocs + assert index_loc.is_core_reg() # add the base offset - if ofs.value > 0: - self.mc.ADD_ri(r.ip.value, ofs_loc.value, imm=ofs.value) - ofs_loc = r.ip - self._write_to_mem(value_loc, base_loc, ofs_loc, scale, fcond) + if ofs_loc.value > 0: + self.mc.ADD_ri(r.ip.value, index_loc.value, imm=ofs_loc.value) + index_loc = r.ip + scale = get_scale(size_loc.value) + self._write_to_mem(value_loc, base_loc, index_loc, imm(scale), fcond) return fcond def _write_to_mem(self, value_loc, base_loc, ofs_loc, scale, fcond=c.AL): + # Write a value of size '1 << scale' at the address + # 'base_ofs + ofs_loc'. Note that 'scale' is not used to scale + # the offset! if scale.value == 3: assert value_loc.is_vfp_reg() # vstr only supports imm offsets @@ -789,43 +734,31 @@ else: assert 0 - emit_op_setarrayitem_raw = emit_op_setarrayitem_gc - - def emit_op_raw_store(self, op, arglocs, regalloc, fcond): - value_loc, base_loc, ofs_loc, scale, ofs = arglocs - assert ofs_loc.is_core_reg() - self._write_to_mem(value_loc, base_loc, ofs_loc, scale, fcond) + def _emit_op_gc_load_indexed(self, op, arglocs, regalloc, fcond): + res_loc, base_loc, index_loc, nsize_loc, ofs_loc = arglocs + assert index_loc.is_core_reg() + nsize = nsize_loc.value + signed = (nsize < 0) + # add the base offset + if ofs_loc.value > 0: + self.mc.ADD_ri(r.ip.value, index_loc.value, imm=ofs_loc.value) + index_loc = r.ip + # + scale = get_scale(abs(nsize)) + self._load_from_mem(res_loc, base_loc, index_loc, imm(scale), + signed, fcond) return fcond - def _genop_getarrayitem(self, op, arglocs, regalloc, fcond): - res_loc, base_loc, ofs_loc, scale, ofs = arglocs - assert ofs_loc.is_core_reg() - signed = op.getdescr().is_item_signed() - - # scale the offset as required - # XXX we should try to encode the scale inside the "shift" part of LDR - if scale.value > 0: - self.mc.LSL_ri(r.ip.value, ofs_loc.value, scale.value) - ofs_loc = r.ip - # add the base offset - if ofs.value > 0: - self.mc.ADD_ri(r.ip.value, ofs_loc.value, imm=ofs.value) - ofs_loc = r.ip - # - self._load_from_mem(res_loc, base_loc, ofs_loc, scale, signed, fcond) - return fcond - - emit_op_getarrayitem_gc_i = _genop_getarrayitem - emit_op_getarrayitem_gc_r = _genop_getarrayitem - emit_op_getarrayitem_gc_f = _genop_getarrayitem - emit_op_getarrayitem_gc_pure_i = _genop_getarrayitem - emit_op_getarrayitem_gc_pure_r = _genop_getarrayitem - emit_op_getarrayitem_gc_pure_f = _genop_getarrayitem - emit_op_getarrayitem_raw_i = _genop_getarrayitem - emit_op_getarrayitem_raw_f = _genop_getarrayitem + emit_op_gc_load_indexed_i = _emit_op_gc_load_indexed + emit_op_gc_load_indexed_r = _emit_op_gc_load_indexed + emit_op_gc_load_indexed_f = _emit_op_gc_load_indexed def _load_from_mem(self, res_loc, base_loc, ofs_loc, scale, signed=False, fcond=c.AL): + # Load a value of '1 << scale' bytes, from the memory location + # 'base_loc + ofs_loc'. Note that 'scale' is not used to scale + # the offset! + # if scale.value == 3: assert res_loc.is_vfp_reg() # vldr only supports imm offsets @@ -881,51 +814,6 @@ else: assert 0 - def _genop_raw_load(self, op, arglocs, regalloc, fcond): - res_loc, base_loc, ofs_loc, scale, ofs = arglocs - assert ofs_loc.is_core_reg() - # no base offset - assert ofs.value == 0 - signed = op.getdescr().is_item_signed() - self._load_from_mem(res_loc, base_loc, ofs_loc, scale, signed, fcond) - return fcond - - emit_op_raw_load_i = _genop_raw_load - emit_op_raw_load_f = _genop_raw_load - - def emit_op_strlen(self, op, arglocs, regalloc, fcond): - l0, l1, res = arglocs - if l1.is_imm(): - self.mc.LDR_ri(res.value, l0.value, l1.getint(), cond=fcond) - else: - self.mc.LDR_rr(res.value, l0.value, l1.value, cond=fcond) - return fcond - - def emit_op_strgetitem(self, op, arglocs, regalloc, fcond): - res, base_loc, ofs_loc, basesize = arglocs - if ofs_loc.is_imm(): - self.mc.ADD_ri(r.ip.value, base_loc.value, ofs_loc.getint(), - cond=fcond) - else: - self.mc.ADD_rr(r.ip.value, base_loc.value, ofs_loc.value, - cond=fcond) - - self.mc.LDRB_ri(res.value, r.ip.value, basesize.value, cond=fcond) - return fcond - - def emit_op_strsetitem(self, op, arglocs, regalloc, fcond): - value_loc, base_loc, ofs_loc, basesize = arglocs - if ofs_loc.is_imm(): - self.mc.ADD_ri(r.ip.value, base_loc.value, ofs_loc.getint(), - cond=fcond) - else: - self.mc.ADD_rr(r.ip.value, base_loc.value, ofs_loc.value, - cond=fcond) - - self.mc.STRB_ri(value_loc.value, r.ip.value, basesize.value, - cond=fcond) - return fcond - #from ../x86/regalloc.py:928 ff. def emit_op_copystrcontent(self, op, arglocs, regalloc, fcond): assert len(arglocs) == 0 @@ -1016,35 +904,6 @@ else: raise AssertionError("bad unicode item size") - emit_op_unicodelen = emit_op_strlen - - def emit_op_unicodegetitem(self, op, arglocs, regalloc, fcond): - res, base_loc, ofs_loc, scale, basesize, itemsize = arglocs - self.mc.ADD_rr(r.ip.value, base_loc.value, ofs_loc.value, cond=fcond, - imm=scale.value, shifttype=shift.LSL) - if scale.value == 2: - self.mc.LDR_ri(res.value, r.ip.value, basesize.value, cond=fcond) - elif scale.value == 1: - self.mc.LDRH_ri(res.value, r.ip.value, basesize.value, cond=fcond) - else: - assert 0, itemsize.value - return fcond - - def emit_op_unicodesetitem(self, op, arglocs, regalloc, fcond): - value_loc, base_loc, ofs_loc, scale, basesize, itemsize = arglocs - self.mc.ADD_rr(r.ip.value, base_loc.value, ofs_loc.value, cond=fcond, - imm=scale.value, shifttype=shift.LSL) - if scale.value == 2: - self.mc.STR_ri(value_loc.value, r.ip.value, basesize.value, - cond=fcond) - elif scale.value == 1: - self.mc.STRH_ri(value_loc.value, r.ip.value, basesize.value, - cond=fcond) - else: - assert 0, itemsize.value - - return fcond - def store_force_descr(self, op, fail_locs, frame_depth): pos = self.mc.currpos() guard_token = self.build_guard_token(op, frame_depth, fail_locs, pos, c.AL) diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -34,9 +34,6 @@ from rpython.rtyper.lltypesystem import lltype, rffi, rstr, llmemory from rpython.rtyper.lltypesystem.lloperation import llop from rpython.jit.codewriter.effectinfo import EffectInfo -from rpython.jit.backend.llsupport.descr import unpack_arraydescr -from rpython.jit.backend.llsupport.descr import unpack_fielddescr -from rpython.jit.backend.llsupport.descr import unpack_interiorfielddescr from rpython.rlib.rarithmetic import r_uint from rpython.jit.backend.llsupport.descr import CallDescr @@ -802,15 +799,12 @@ src_locations2, dst_locations2, vfptmploc) return [] - def prepare_op_setfield_gc(self, op, fcond): + def prepare_op_gc_store(self, op, fcond): boxes = op.getarglist() - ofs, size, sign = unpack_fielddescr(op.getdescr()) - return self._prepare_op_setfield(boxes, ofs, size) - - def _prepare_op_setfield(self, boxes, ofs, size): - a0, a1 = boxes - base_loc = self.make_sure_var_in_reg(a0, boxes) - value_loc = self.make_sure_var_in_reg(a1, boxes) + base_loc = self.make_sure_var_in_reg(boxes[0], boxes) + ofs = boxes[1].getint() + value_loc = self.make_sure_var_in_reg(boxes[2], boxes) + size = abs(boxes[3].getint()) ofs_size = default_imm_size if size < 8 else VMEM_imm_size if check_imm_arg(ofs, size=ofs_size): ofs_loc = imm(ofs) @@ -819,19 +813,13 @@ self.assembler.load(ofs_loc, imm(ofs)) return [value_loc, base_loc, ofs_loc, imm(size)] - prepare_op_setfield_raw = prepare_op_setfield_gc - - def prepare_op_zero_ptr_field(self, op, fcond): + def _prepare_op_gc_load(self, op, fcond): a0 = op.getarg(0) ofs = op.getarg(1).getint() - return self._prepare_op_setfield([a0, ConstInt(0)], ofs, WORD) - - def _prepare_op_getfield(self, op, fcond): - a0 = op.getarg(0) - ofs, size, sign = unpack_fielddescr(op.getdescr()) + nsize = op.getarg(2).getint() # negative for "signed" base_loc = self.make_sure_var_in_reg(a0) immofs = imm(ofs) - ofs_size = default_imm_size if size < 8 else VMEM_imm_size + ofs_size = default_imm_size if abs(nsize) < 8 else VMEM_imm_size if check_imm_arg(ofs, size=ofs_size): ofs_loc = immofs else: @@ -839,17 +827,12 @@ self.assembler.load(ofs_loc, immofs) self.possibly_free_vars_for_op(op) self.free_temp_vars() - res = self.force_allocate_reg(op) - return [base_loc, ofs_loc, res, imm(size)] + res_loc = self.force_allocate_reg(op) + return [base_loc, ofs_loc, res_loc, imm(nsize)] - prepare_op_getfield_gc_i = _prepare_op_getfield - prepare_op_getfield_gc_r = _prepare_op_getfield - prepare_op_getfield_gc_f = _prepare_op_getfield - prepare_op_getfield_raw_i = _prepare_op_getfield - prepare_op_getfield_raw_f = _prepare_op_getfield - prepare_op_getfield_gc_pure_i = _prepare_op_getfield - prepare_op_getfield_gc_pure_r = _prepare_op_getfield - prepare_op_getfield_gc_pure_f = _prepare_op_getfield + prepare_op_gc_load_i = _prepare_op_gc_load + prepare_op_gc_load_r = _prepare_op_gc_load + prepare_op_gc_load_f = _prepare_op_gc_load def prepare_op_increment_debug_counter(self, op, fcond): boxes = op.getarglist() @@ -859,188 +842,38 @@ self.free_temp_vars() return [base_loc, value_loc] - def _prepare_op_getinteriorfield(self, op, fcond): - t = unpack_interiorfielddescr(op.getdescr()) - ofs, itemsize, fieldsize, sign = t - args = op.getarglist() - base_loc = self.make_sure_var_in_reg(op.getarg(0), args) - index_loc = self.make_sure_var_in_reg(op.getarg(1), args) - immofs = imm(ofs) - ofs_size = default_imm_size if fieldsize < 8 else VMEM_imm_size - if check_imm_arg(ofs, size=ofs_size): - ofs_loc = immofs - else: - ofs_loc = self.get_scratch_reg(INT, args) - self.assembler.load(ofs_loc, immofs) + def prepare_op_gc_store_indexed(self, op, fcond): + boxes = op.getarglist() + base_loc = self.make_sure_var_in_reg(boxes[0], boxes) + value_loc = self.make_sure_var_in_reg(boxes[2], boxes) + index_loc = self.make_sure_var_in_reg(boxes[1], boxes) + assert boxes[3].getint() == 1 # scale + ofs = boxes[4].getint() + size = abs(boxes[5].getint()) + assert check_imm_arg(ofs) + return [value_loc, base_loc, index_loc, imm(size), imm(ofs)] + + def _prepare_op_gc_load_indexed(self, op, fcond): + boxes = op.getarglist() + base_loc = self.make_sure_var_in_reg(boxes[0], boxes) + index_loc = self.make_sure_var_in_reg(boxes[1], boxes) + assert boxes[2].getint() == 1 # scale + ofs = boxes[3].getint() + nsize = boxes[4].getint() + assert check_imm_arg(ofs) self.possibly_free_vars_for_op(op) self.free_temp_vars() - result_loc = self.force_allocate_reg(op) - return [base_loc, index_loc, result_loc, ofs_loc, imm(ofs), - imm(itemsize), imm(fieldsize)] + res_loc = self.force_allocate_reg(op) + return [res_loc, base_loc, index_loc, imm(nsize), imm(ofs)] - prepare_op_getinteriorfield_gc_i = _prepare_op_getinteriorfield - prepare_op_getinteriorfield_gc_r = _prepare_op_getinteriorfield - prepare_op_getinteriorfield_gc_f = _prepare_op_getinteriorfield - - def prepare_op_setinteriorfield_gc(self, op, fcond): - t = unpack_interiorfielddescr(op.getdescr()) - ofs, itemsize, fieldsize, sign = t - args = op.getarglist() - base_loc = self.make_sure_var_in_reg(op.getarg(0), args) - index_loc = self.make_sure_var_in_reg(op.getarg(1), args) - value_loc = self.make_sure_var_in_reg(op.getarg(2), args) - immofs = imm(ofs) - ofs_size = default_imm_size if fieldsize < 8 else VMEM_imm_size - if check_imm_arg(ofs, size=ofs_size): - ofs_loc = immofs - else: - ofs_loc = self.get_scratch_reg(INT, args) - self.assembler.load(ofs_loc, immofs) - return [base_loc, index_loc, value_loc, ofs_loc, imm(ofs), - imm(itemsize), imm(fieldsize)] - prepare_op_setinteriorfield_raw = prepare_op_setinteriorfield_gc - - def prepare_op_arraylen_gc(self, op, fcond): - arraydescr = op.getdescr() - assert isinstance(arraydescr, ArrayDescr) - ofs = arraydescr.lendescr.offset - arg = op.getarg(0) - base_loc = self.make_sure_var_in_reg(arg) - self.possibly_free_vars_for_op(op) - self.free_temp_vars() - res = self.force_allocate_reg(op) - return [res, base_loc, imm(ofs)] - - def prepare_op_setarrayitem_gc(self, op, fcond): - size, ofs, _ = unpack_arraydescr(op.getdescr()) - scale = get_scale(size) - args = op.getarglist() - base_loc = self.make_sure_var_in_reg(args[0], args) - value_loc = self.make_sure_var_in_reg(args[2], args) - ofs_loc = self.make_sure_var_in_reg(args[1], args) - assert check_imm_arg(ofs) - return [value_loc, base_loc, ofs_loc, imm(scale), imm(ofs)] - prepare_op_setarrayitem_raw = prepare_op_setarrayitem_gc - prepare_op_raw_store = prepare_op_setarrayitem_gc - - def _prepare_op_getarrayitem(self, op, fcond): - boxes = op.getarglist() - size, ofs, _ = unpack_arraydescr(op.getdescr()) - scale = get_scale(size) - base_loc = self.make_sure_var_in_reg(boxes[0], boxes) - ofs_loc = self.make_sure_var_in_reg(boxes[1], boxes) - self.possibly_free_vars_for_op(op) - self.free_temp_vars() - res = self.force_allocate_reg(op) - assert check_imm_arg(ofs) - return [res, base_loc, ofs_loc, imm(scale), imm(ofs)] - - prepare_op_getarrayitem_gc_i = _prepare_op_getarrayitem - prepare_op_getarrayitem_gc_r = _prepare_op_getarrayitem - prepare_op_getarrayitem_gc_f = _prepare_op_getarrayitem - prepare_op_getarrayitem_raw_i = _prepare_op_getarrayitem - prepare_op_getarrayitem_raw_f = _prepare_op_getarrayitem - prepare_op_getarrayitem_gc_pure_i = _prepare_op_getarrayitem - prepare_op_getarrayitem_gc_pure_r = _prepare_op_getarrayitem - prepare_op_getarrayitem_gc_pure_f = _prepare_op_getarrayitem - prepare_op_raw_load_i = _prepare_op_getarrayitem - prepare_op_raw_load_f = _prepare_op_getarrayitem - - def prepare_op_strlen(self, op, fcond): - args = op.getarglist() - l0 = self.make_sure_var_in_reg(op.getarg(0)) - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, - self.cpu.translate_support_code) - immofs = imm(ofs_length) - if check_imm_arg(ofs_length): - l1 = immofs - else: - l1 = self.get_scratch_reg(INT, args) - self.assembler.load(l1, immofs) - - self.possibly_free_vars_for_op(op) - self.free_temp_vars() - - res = self.force_allocate_reg(op) - self.possibly_free_var(op) - return [l0, l1, res] - - def prepare_op_strgetitem(self, op, fcond): - boxes = op.getarglist() - base_loc = self.make_sure_var_in_reg(boxes[0]) - - a1 = boxes[1] - imm_a1 = check_imm_box(a1) - if imm_a1: - ofs_loc = self.convert_to_imm(a1) - else: - ofs_loc = self.make_sure_var_in_reg(a1, boxes) - - self.possibly_free_vars_for_op(op) - self.free_temp_vars() - res = self.force_allocate_reg(op) - - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, - self.cpu.translate_support_code) - assert itemsize == 1 - return [res, base_loc, ofs_loc, imm(basesize)] - - def prepare_op_strsetitem(self, op, fcond): - boxes = op.getarglist() - base_loc = self.make_sure_var_in_reg(boxes[0], boxes) - ofs_loc = self.make_sure_var_in_reg(boxes[1], boxes) - value_loc = self.make_sure_var_in_reg(boxes[2], boxes) - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, - self.cpu.translate_support_code) - assert itemsize == 1 - return [value_loc, base_loc, ofs_loc, imm(basesize)] + prepare_op_gc_load_indexed_i = _prepare_op_gc_load_indexed + prepare_op_gc_load_indexed_r = _prepare_op_gc_load_indexed + prepare_op_gc_load_indexed_f = _prepare_op_gc_load_indexed prepare_op_copystrcontent = void prepare_op_copyunicodecontent = void prepare_op_zero_array = void - def prepare_op_unicodelen(self, op, fcond): - l0 = self.make_sure_var_in_reg(op.getarg(0)) - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, - self.cpu.translate_support_code) - immofs = imm(ofs_length) - if check_imm_arg(ofs_length): - l1 = immofs - else: - l1 = self.get_scratch_reg(INT, [op.getarg(0)]) - self.assembler.load(l1, immofs) - - self.possibly_free_vars_for_op(op) - self.free_temp_vars() - res = self.force_allocate_reg(op) - return [l0, l1, res] - - def prepare_op_unicodegetitem(self, op, fcond): - boxes = op.getarglist() - base_loc = self.make_sure_var_in_reg(boxes[0], boxes) - ofs_loc = self.make_sure_var_in_reg(boxes[1], boxes) - - self.possibly_free_vars_for_op(op) - self.free_temp_vars() - res = self.force_allocate_reg(op) - - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, - self.cpu.translate_support_code) - scale = itemsize / 2 - return [res, base_loc, ofs_loc, - imm(scale), imm(basesize), imm(itemsize)] - - def prepare_op_unicodesetitem(self, op, fcond): - boxes = op.getarglist() - base_loc = self.make_sure_var_in_reg(boxes[0], boxes) - ofs_loc = self.make_sure_var_in_reg(boxes[1], boxes) - value_loc = self.make_sure_var_in_reg(boxes[2], boxes) - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, - self.cpu.translate_support_code) - scale = itemsize / 2 - return [value_loc, base_loc, ofs_loc, - imm(scale), imm(basesize), imm(itemsize)] - def _prepare_op_same_as(self, op, fcond): arg = op.getarg(0) imm_arg = check_imm_box(arg) @@ -1142,8 +975,7 @@ def prepare_op_cond_call_gc_wb(self, op, fcond): # we force all arguments in a reg because it will be needed anyway by - # the following setfield_gc or setarrayitem_gc. It avoids loading it - # twice from the memory. + # the following gc_store. It avoids loading it twice from the memory. N = op.numargs() args = op.getarglist() arglocs = [self.make_sure_var_in_reg(op.getarg(i), args) diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -29,6 +29,10 @@ float_regs = VFPRegisterManager.all_regs frame_reg = fp + # can an ISA instruction handle a factor to the offset? + # XXX should be: tuple(1 << i for i in range(31)) + load_supported_factors = (1,) + def __init__(self, rtyper, stats, opts=None, translate_support_code=False, gcdescr=None): AbstractLLCPU.__init__(self, rtyper, stats, opts, 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 @@ -380,6 +380,8 @@ # the call that it is no longer equal to css. See description # in translator/c/src/thread_pthread.c. + # XXX some duplicated logic here, but note that rgil.acquire() + # does more than just RPyGilAcquire() if old_rpy_fastgil == 0: # this case occurs if some other thread stole the GIL but # released it again. What occurred here is that we changed @@ -390,9 +392,8 @@ elif old_rpy_fastgil == 1: # 'rpy_fastgil' was (and still is) locked by someone else. # We need to wait for the regular mutex. - after = rffi.aroundstate.after - if after: - after() + from rpython.rlib import rgil + rgil.acquire() else: # stole the GIL from a different thread that is also # currently in an external call from the jit. Attach @@ -421,9 +422,8 @@ # 'rpy_fastgil' contains only zero or non-zero, and this is only # called when the old value stored in 'rpy_fastgil' was non-zero # (i.e. still locked, must wait with the regular mutex) - after = rffi.aroundstate.after - if after: - after() + from rpython.rlib import rgil + rgil.acquire() _REACQGIL0_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void)) _REACQGIL2_FUNC = lltype.Ptr(lltype.FuncType([rffi.CCHARP, lltype.Signed], diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py --- a/rpython/jit/backend/llsupport/rewrite.py +++ b/rpython/jit/backend/llsupport/rewrite.py @@ -1,6 +1,6 @@ from rpython.rlib import rgc from rpython.rlib.objectmodel import we_are_translated -from rpython.rlib.rarithmetic import ovfcheck +from rpython.rlib.rarithmetic import ovfcheck, highest_bit from rpython.rtyper.lltypesystem import llmemory, lltype, rstr from rpython.jit.metainterp import history from rpython.jit.metainterp.history import ConstInt, ConstPtr @@ -165,7 +165,14 @@ if isinstance(index_box, ConstInt): index_box = ConstInt(index_box.value * factor) else: - index_box = ResOperation(rop.INT_MUL, [index_box, ConstInt(factor)]) + # x & (x - 1) == 0 is a quick test for power of 2 + assert factor > 0 + if (factor & (factor - 1)) == 0: + index_box = ResOperation(rop.INT_LSHIFT, + [index_box, ConstInt(highest_bit(factor))]) + else: + index_box = ResOperation(rop.INT_MUL, + [index_box, ConstInt(factor)]) self.emit_op(index_box) factor = 1 # adjust the constant offset @@ -296,13 +303,6 @@ self.cpu.translate_support_code) self.emit_gc_store_or_indexed(op, op.getarg(0), op.getarg(1), op.getarg(2), itemsize, itemsize, basesize) - elif op.getopnum() == rop.ZERO_PTR_FIELD: - ofs = op.getarg(1).getint() - size = WORD - index_box = ConstInt(0) - value_box = ConstInt(0) - self.emit_gc_store_or_indexed(op, op.getarg(0), index_box, value_box, - size, 1, ofs) return False @@ -532,7 +532,9 @@ return # the ZERO_ARRAY operation will be optimized according to what # SETARRAYITEM_GC we see before the next allocation operation. - # See emit_pending_zeros(). + # See emit_pending_zeros(). (This optimization is done by + # hacking the object 'o' in-place: e.g., o.getarg(1) may be + # replaced with another constant greater than 0.) o = ResOperation(rop.ZERO_ARRAY, [v_arr, self.c_zero, v_length], descr=arraydescr) self.emit_op(o) @@ -676,7 +678,7 @@ del self.last_zero_arrays[:] self._setarrayitems_occurred.clear() # - # Then write the ZERO_PTR_FIELDs that are still pending + # Then write the NULL-pointer-writing ops that are still pending for v, d in self._delayed_zero_setfields.iteritems(): v = self.get_box_replacement(v) for ofs in d.iterkeys(): diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py --- a/rpython/jit/backend/llsupport/test/test_gc_integration.py +++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py @@ -17,7 +17,6 @@ from rpython.jit.backend.llsupport.test.test_regalloc_integration import BaseTestRegalloc from rpython.jit.codewriter.effectinfo import EffectInfo from rpython.jit.codewriter import longlong -from rpython.rlib.objectmodel import invoke_around_extcall CPU = getcpuclass() @@ -625,9 +624,6 @@ self.S = S self.cpu = cpu - def teardown_method(self, meth): - rffi.aroundstate._cleanup_() - def test_shadowstack_call(self): cpu = self.cpu cpu.gc_ll_descr.init_nursery(100) diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py --- a/rpython/jit/backend/llsupport/test/test_rewrite.py +++ b/rpython/jit/backend/llsupport/test/test_rewrite.py @@ -37,6 +37,7 @@ return ','.join([str(n) for n in [descr.itemsize, descr.basesize, size]]) + WORD = globals()['WORD'] S = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed)) sdescr = get_size_descr(self.gc_ll_descr, S) @@ -71,6 +72,12 @@ itzdescr = get_interiorfield_descr(self.gc_ll_descr, S1I, 'z') itydescr = get_interiorfield_descr(self.gc_ll_descr, S1I, 'y') itxdescr = get_interiorfield_descr(self.gc_ll_descr, S1I, 'x') + S2I = lltype.GcArray(('x', lltype.Ptr(S1)), + ('y', lltype.Ptr(S1)), + ('z', lltype.Ptr(S1)), + ('t', lltype.Ptr(S1))) # size is a power of two + s2i_item_size_in_bits = (4 if WORD == 4 else 5) + ity2descr = get_interiorfield_descr(self.gc_ll_descr, S2I, 'y') R1 = lltype.GcStruct('R', ('x', lltype.Signed), ('y', lltype.Float), ('z', lltype.Ptr(S1))) @@ -90,7 +97,6 @@ # tiddescr = self.gc_ll_descr.fielddescr_tid wbdescr = self.gc_ll_descr.write_barrier_descr - WORD = globals()['WORD'] # F = lltype.GcArray(lltype.Float) fdescr = get_array_descr(self.gc_ll_descr, F) @@ -1224,6 +1230,13 @@ '%(itydescr.arraydescr.basesize' ' + itydescr.fielddescr.offset)d,' '%(itydescr.fielddescr.field_size)d)'], + [True, (1,2,4,8), 'i3 = setinteriorfield_gc(p0,i1,i2,descr=ity2descr)' '->' + 'i4 = int_lshift(i1,' + '%(s2i_item_size_in_bits)d);' + 'i3 = gc_store_indexed(p0,i4,i2,1,' + '%(ity2descr.arraydescr.basesize' + ' + itydescr.fielddescr.offset)d,' + '%(ity2descr.fielddescr.field_size)d)'], ]) def test_gc_load_store_transform(self, support_offset, factors, fromto): self.cpu.load_constant_offset = support_offset diff --git a/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py b/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py --- a/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py +++ b/rpython/jit/backend/llsupport/test/zrpy_releasegil_test.py @@ -1,6 +1,5 @@ from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.rlib.jit import dont_look_inside -from rpython.rlib.objectmodel import invoke_around_extcall from rpython.jit.metainterp.optimizeopt import ALL_OPTS_NAMES from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.rlib import rposix @@ -16,20 +15,10 @@ compile_kwds = dict(enable_opts=ALL_OPTS_NAMES, thread=True) def define_simple(self): - class Glob: - def __init__(self): - self.event = 0 - glob = Glob() - # - c_strchr = rffi.llexternal('strchr', [rffi.CCHARP, lltype.Signed], rffi.CCHARP) - def func(): - glob.event += 1 - def before(n, x): - invoke_around_extcall(func, func) return (n, None, None, None, None, None, None, None, None, None, None, None) # @@ -73,7 +62,8 @@ def f42(n): length = len(glob.lst) raw = alloc1() - fn = llhelper(CALLBACK, rffi._make_wrapper_for(CALLBACK, callback)) + wrapper = rffi._make_wrapper_for(CALLBACK, callback, None, True) + fn = llhelper(CALLBACK, wrapper) if n & 1: # to create a loop and a bridge, and also pass # to run the qsort() call in the blackhole interp c_qsort(rffi.cast(rffi.VOIDP, raw), rffi.cast(rffi.SIZE_T, 2), 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 @@ -4971,52 +4971,6 @@ [boxfloat(12.5)], 'int') assert res == struct.unpack("I", struct.pack("f", 12.5))[0] - def test_zero_ptr_field(self): - if not isinstance(self.cpu, AbstractLLCPU): - py.test.skip("llgraph can't do zero_ptr_field") - T = lltype.GcStruct('T') - S = lltype.GcStruct('S', ('x', lltype.Ptr(T))) - tdescr = self.cpu.sizeof(T) - sdescr = self.cpu.sizeof(S) - fielddescr = self.cpu.fielddescrof(S, 'x') - loop = parse(""" - [] - p0 = new(descr=tdescr) - p1 = new(descr=sdescr) - setfield_gc(p1, p0, descr=fielddescr) - zero_ptr_field(p1, %d) - finish(p1) - """ % fielddescr.offset, namespace=locals()) - looptoken = JitCellToken() - self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) - deadframe = self.cpu.execute_token(looptoken) - ref = self.cpu.get_ref_value(deadframe, 0) - s = lltype.cast_opaque_ptr(lltype.Ptr(S), ref) - assert not s.x - - def test_zero_ptr_field_2(self): - if not isinstance(self.cpu, AbstractLLCPU): - py.test.skip("llgraph does not do zero_ptr_field") - - from rpython.jit.backend.llsupport import symbolic - S = lltype.GcStruct('S', ('x', lltype.Signed), - ('p', llmemory.GCREF), - ('y', lltype.Signed)) - s = lltype.malloc(S) - s.x = -1296321 - s.y = -4398176 - s_ref = lltype.cast_opaque_ptr(llmemory.GCREF, s) - s.p = s_ref - ofs_p, _ = symbolic.get_field_token(S, 'p', False) - # - self.execute_operation(rop.ZERO_PTR_FIELD, [ - InputArgRef(s_ref), ConstInt(ofs_p)], # OK for now to assume that the - 'void') # 2nd argument is a constant - # - assert s.x == -1296321 - assert s.p == lltype.nullptr(llmemory.GCREF.TO) - assert s.y == -4398176 - def test_zero_array(self): if not isinstance(self.cpu, AbstractLLCPU): py.test.skip("llgraph does not do zero_array") diff --git a/rpython/jit/backend/test/test_ll_random.py b/rpython/jit/backend/test/test_ll_random.py --- a/rpython/jit/backend/test/test_ll_random.py +++ b/rpython/jit/backend/test/test_ll_random.py @@ -745,7 +745,6 @@ OPERATIONS.append(GetInteriorFieldOperation(rop.GETINTERIORFIELD_GC_I)) OPERATIONS.append(GetInteriorFieldOperation(rop.GETINTERIORFIELD_GC_I)) OPERATIONS.append(SetFieldOperation(rop.SETFIELD_GC)) - OPERATIONS.append(ZeroPtrFieldOperation(rop.ZERO_PTR_FIELD)) OPERATIONS.append(SetInteriorFieldOperation(rop.SETINTERIORFIELD_GC)) OPERATIONS.append(NewOperation(rop.NEW)) OPERATIONS.append(NewOperation(rop.NEW_WITH_VTABLE)) diff --git a/rpython/jit/backend/test/test_random.py b/rpython/jit/backend/test/test_random.py --- a/rpython/jit/backend/test/test_random.py +++ b/rpython/jit/backend/test/test_random.py @@ -57,19 +57,11 @@ def do(self, opnum, argboxes, descr=None): self.fakemetainterp._got_exc = None op = ResOperation(opnum, argboxes, descr) - if opnum != rop.ZERO_PTR_FIELD: - result = _execute_arglist(self.cpu, self.fakemetainterp, - opnum, argboxes, descr) - if result is not None: - c_result = wrap_constant(result) - op.copy_value_from(c_result) - else: - import ctypes - addr = self.cpu.cast_gcref_to_int(argboxes[0].getref_base()) - offset = argboxes[1].getint() - assert (offset % ctypes.sizeof(ctypes.c_long)) == 0 - ptr = ctypes.cast(addr, ctypes.POINTER(ctypes.c_long)) - ptr[offset / ctypes.sizeof(ctypes.c_long)] = 0 + result = _execute_arglist(self.cpu, self.fakemetainterp, + opnum, argboxes, descr) + if result is not None: + c_result = wrap_constant(result) + op.copy_value_from(c_result) self.loop.operations.append(op) return op diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py --- a/rpython/jit/backend/x86/regalloc.py +++ b/rpython/jit/backend/x86/regalloc.py @@ -1039,8 +1039,7 @@ base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args) size_box = op.getarg(3) assert isinstance(size_box, ConstInt) - size = size_box.value - itemsize = abs(size) + size = abs(size_box.value) if size == 1: need_lower_byte = True else: @@ -1049,7 +1048,7 @@ need_lower_byte=need_lower_byte) ofs_loc = self.rm.make_sure_var_in_reg(op.getarg(1), args) self.perform_discard(op, [base_loc, ofs_loc, value_loc, - imm(itemsize)]) + imm(size)]) def consider_gc_store_indexed(self, op): args = op.getarglist() @@ -1062,8 +1061,7 @@ assert isinstance(size_box, ConstInt) factor = scale_box.value offset = offset_box.value - size = size_box.value - itemsize = abs(size) + size = abs(size_box.value) if size == 1: need_lower_byte = True else: @@ -1072,7 +1070,7 @@ need_lower_byte=need_lower_byte) ofs_loc = self.rm.make_sure_var_in_reg(op.getarg(1), args) self.perform_discard(op, [base_loc, ofs_loc, value_loc, - imm(factor), imm(offset), imm(itemsize)]) + imm(factor), imm(offset), imm(size)]) def consider_increment_debug_counter(self, op): base_loc = self.loc(op.getarg(0)) diff --git a/rpython/jit/metainterp/executor.py b/rpython/jit/metainterp/executor.py --- a/rpython/jit/metainterp/executor.py +++ b/rpython/jit/metainterp/executor.py @@ -367,7 +367,6 @@ rop.INCREMENT_DEBUG_COUNTER, rop.COND_CALL_GC_WB, rop.COND_CALL_GC_WB_ARRAY, - rop.ZERO_PTR_FIELD, rop.ZERO_ARRAY, rop.DEBUG_MERGE_POINT, rop.JIT_DEBUG, diff --git a/rpython/jit/metainterp/optimizeopt/dependency.py b/rpython/jit/metainterp/optimizeopt/dependency.py --- a/rpython/jit/metainterp/optimizeopt/dependency.py +++ b/rpython/jit/metainterp/optimizeopt/dependency.py @@ -18,7 +18,6 @@ , (rop.SETINTERIORFIELD_RAW, 0, -1) , (rop.SETFIELD_GC, 0, -1) , (rop.SETFIELD_RAW, 0, -1) - , (rop.ZERO_PTR_FIELD, 0, -1) , (rop.ZERO_ARRAY, 0, -1) , (rop.STRSETITEM, 0, -1) , (rop.UNICODESETITEM, 0, -1) diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py --- a/rpython/jit/metainterp/resoperation.py +++ b/rpython/jit/metainterp/resoperation.py @@ -1170,10 +1170,11 @@ 'GC_LOAD/3/rfi', # parameters GC_LOAD_INDEXED # 1: pointer to complex object - # 2: integer describing the offset + # 2: integer describing the index # 3: constant integer scale factor - # 4: constant integer offset + # 4: constant integer base offset (final offset is 'base + scale * index') # 5: constant integer. byte size of datatype to load (negative if it is signed) + # (GC_LOAD is equivalent to GC_LOAD_INDEXED with arg3==1, arg4==0) 'GC_LOAD_INDEXED/5/rfi', '_RAW_LOAD_FIRST', @@ -1204,8 +1205,9 @@ # same paramters as GC_LOAD, but one additional for the value to store # note that the itemsize is not signed! + # (gcptr, index, value, [scale, base_offset,] itemsize) 'GC_STORE/4d/n', - 'GC_STORE_INDEXED/5d/n', + 'GC_STORE_INDEXED/6d/n', 'INCREMENT_DEBUG_COUNTER/1/n', '_RAW_STORE_FIRST', @@ -1219,8 +1221,6 @@ 'SETINTERIORFIELD_GC/3d/n', 'SETINTERIORFIELD_RAW/3d/n', # right now, only used by tests 'SETFIELD_GC/2d/n', - 'ZERO_PTR_FIELD/2/n', # only emitted by the rewrite, clears a pointer field - # at a given constant offset, no descr 'ZERO_ARRAY/3d/n', # only emitted by the rewrite, clears (part of) an array # [arraygcptr, firstindex, length], descr=ArrayDescr 'SETFIELD_RAW/2d/n', diff --git a/rpython/jit/metainterp/test/test_ajit.py b/rpython/jit/metainterp/test/test_ajit.py --- a/rpython/jit/metainterp/test/test_ajit.py +++ b/rpython/jit/metainterp/test/test_ajit.py @@ -4044,7 +4044,7 @@ self.interp_operations(f, []) def test_external_call(self): - from rpython.rlib.objectmodel import invoke_around_extcall + from rpython.rlib import rgil TIME_T = lltype.Signed # ^^^ some 32-bit platforms have a 64-bit rffi.TIME_T, but we @@ -4058,11 +4058,6 @@ pass state = State() - def before(): - if we_are_jitted(): - raise Oups - state.l.append("before") - def after(): if we_are_jitted(): raise Oups @@ -4070,14 +4065,14 @@ def f(): state.l = [] - invoke_around_extcall(before, after) + rgil.invoke_after_thread_switch(after) external(lltype.nullptr(T.TO)) return len(state.l) res = self.interp_operations(f, []) - assert res == 2 + assert res == 1 res = self.interp_operations(f, []) - assert res == 2 + assert res == 1 self.check_operations_history(call_release_gil_i=1, call_may_force_i=0) def test_unescaped_write_zero(self): diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -1124,8 +1124,8 @@ resultvar=op.result) def gct_gc_thread_run(self, hop): - assert self.translator.config.translation.thread - if hasattr(self.root_walker, 'thread_run_ptr'): + if (self.translator.config.translation.thread and + hasattr(self.root_walker, 'thread_run_ptr')): livevars = self.push_roots(hop) assert not livevars, "live GC var around %s!" % (hop.spaceop,) hop.genop("direct_call", [self.root_walker.thread_run_ptr]) diff --git a/rpython/memory/gcwrapper.py b/rpython/memory/gcwrapper.py --- a/rpython/memory/gcwrapper.py +++ b/rpython/memory/gcwrapper.py @@ -184,6 +184,9 @@ hdr.tid |= self.gc.gcflag_extra return (hdr.tid & self.gc.gcflag_extra) != 0 + def thread_run(self): + pass + # ____________________________________________________________ class LLInterpRootWalker: diff --git a/rpython/rlib/_rposix_repr.py b/rpython/rlib/_rposix_repr.py deleted file mode 100644 --- a/rpython/rlib/_rposix_repr.py +++ /dev/null @@ -1,122 +0,0 @@ -""" -RTyping support for os.stat_result objects. -They are rtyped just like a tuple of the correct length supporting -only indexing and the st_xxx attributes. We need a custom StatResultRepr -because when rtyping for LL backends we have extra platform-dependent -items at the end of the tuple, but for OO backends we only want the -portable items. This allows the OO backends to assume a fixed shape for -the tuples returned by os.stat(). -""" -from rpython.annotator import model as annmodel -from rpython.rtyper.llannotation import lltype_to_annotation -from rpython.flowspace.model import Constant -from rpython.flowspace.operation import op -from rpython.tool.pairtype import pairtype -from rpython.rtyper.rmodel import Repr -from rpython.rtyper.rint import IntegerRepr -from rpython.rtyper.error import TyperError -from rpython.rlib import rposix_stat - - -class StatResultRepr(Repr): - - def __init__(self, rtyper): - self.rtyper = rtyper - self.stat_fields = rposix_stat.STAT_FIELDS - - self.stat_field_indexes = {} - for i, (name, TYPE) in enumerate(self.stat_fields): - self.stat_field_indexes[name] = i - - self.s_tuple = annmodel.SomeTuple([lltype_to_annotation(TYPE) - for name, TYPE in self.stat_fields]) - self.r_tuple = rtyper.getrepr(self.s_tuple) - self.lowleveltype = self.r_tuple.lowleveltype - - def redispatch_getfield(self, hop, index): - rtyper = self.rtyper - s_index = rtyper.annotator.bookkeeper.immutablevalue(index) - hop2 = hop.copy() - spaceop = op.getitem(hop.args_v[0], Constant(index)) - spaceop.result = hop.spaceop.result - hop2.spaceop = spaceop - hop2.args_v = spaceop.args - hop2.args_s = [self.s_tuple, s_index] - hop2.args_r = [self.r_tuple, rtyper.getrepr(s_index)] - return hop2.dispatch() - - def rtype_getattr(self, hop): - s_attr = hop.args_s[1] - attr = s_attr.const - try: - index = self.stat_field_indexes[attr] - except KeyError: - raise TyperError("os.stat().%s: field not available" % (attr,)) - return self.redispatch_getfield(hop, index) - - -class __extend__(pairtype(StatResultRepr, IntegerRepr)): - - def rtype_getitem((r_sta, r_int), hop): - s_int = hop.args_s[1] - index = s_int.const - return r_sta.redispatch_getfield(hop, index) - - -def specialize_make_stat_result(hop): - r_StatResult = hop.rtyper.getrepr(rposix_stat.s_StatResult) - [v_result] = hop.inputargs(r_StatResult.r_tuple) - # no-op conversion from r_StatResult.r_tuple to r_StatResult - hop.exception_cannot_occur() - return v_result - - -class StatvfsResultRepr(Repr): - - def __init__(self, rtyper): - self.rtyper = rtyper - self.statvfs_fields = rposix_stat.STATVFS_FIELDS - - self.statvfs_field_indexes = {} - for i, (name, TYPE) in enumerate(self.statvfs_fields): - self.statvfs_field_indexes[name] = i - - self.s_tuple = annmodel.SomeTuple([lltype_to_annotation(TYPE) - for name, TYPE in self.statvfs_fields]) - self.r_tuple = rtyper.getrepr(self.s_tuple) - self.lowleveltype = self.r_tuple.lowleveltype - - def redispatch_getfield(self, hop, index): - rtyper = self.rtyper - s_index = rtyper.annotator.bookkeeper.immutablevalue(index) - hop2 = hop.copy() - spaceop = op.getitem(hop.args_v[0], Constant(index)) - spaceop.result = hop.spaceop.result - hop2.spaceop = spaceop - hop2.args_v = spaceop.args - hop2.args_s = [self.s_tuple, s_index] - hop2.args_r = [self.r_tuple, rtyper.getrepr(s_index)] - return hop2.dispatch() - - def rtype_getattr(self, hop): - s_attr = hop.args_s[1] - attr = s_attr.const - try: - index = self.statvfs_field_indexes[attr] - except KeyError: - raise TyperError("os.statvfs().%s: field not available" % (attr,)) - return self.redispatch_getfield(hop, index) - - -class __extend__(pairtype(StatvfsResultRepr, IntegerRepr)): - def rtype_getitem((r_sta, r_int), hop): - s_int = hop.args_s[1] - index = s_int.const - return r_sta.redispatch_getfield(hop, index) - - -def specialize_make_statvfs_result(hop): - r_StatvfsResult = hop.rtyper.getrepr(rposix_stat.s_StatvfsResult) - [v_result] = hop.inputargs(r_StatvfsResult.r_tuple) - hop.exception_cannot_occur() - return v_result diff --git a/rpython/rlib/entrypoint.py b/rpython/rlib/entrypoint.py --- a/rpython/rlib/entrypoint.py +++ b/rpython/rlib/entrypoint.py @@ -56,10 +56,11 @@ """ def deco(func): source = py.code.Source(""" + from rpython.rlib import rgil + def wrapper(%(args)s): # acquire the GIL - after = rffi.aroundstate.after - if after: after() + rgil.acquire() # rffi.stackcounter.stacks_counter += 1 llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py @@ -78,8 +79,7 @@ assert 0 # dead code rffi.stackcounter.stacks_counter -= 1 # release the GIL - before = rffi.aroundstate.before - if before: before() + rgil.release() # return res """ % {'args': ', '.join(['arg%d' % i for i in range(len(argtypes))])}) diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py --- a/rpython/rlib/objectmodel.py +++ b/rpython/rlib/objectmodel.py @@ -599,22 +599,10 @@ _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit