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

Reply via email to