Author: Matti Picus <[email protected]>
Branch: release-pypy2.7-v7.x
Changeset: r98294:285307a0f5a7
Date: 2019-12-15 12:10 +0200
http://bitbucket.org/pypy/pypy/changeset/285307a0f5a7/

Log:    merge default into release

diff too long, truncating to 2000 out of 13046 lines

diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -57,3 +57,5 @@
 4a68d8d3d2fc1faec2e83bcb4d28559099092574 release-pypy2.7-v7.2.0rc2
 4a68d8d3d2fc1faec2e83bcb4d28559099092574 release-pypy2.7-v7.2.0
 5da45ced70e515f94686be0df47c59abd1348ebc release-pypy3.6-v7.2.0
+e6471221abc16f4584a07fbfeece7ebcaeb7fc38 release-pypy2.7-v7.3.0rc1
+533398cfd64e5146a07c4824e90a1b629c8b6523 release-pypy3.6-v7.3.0rc1
diff --git a/lib_pypy/_cffi_ssl/_stdssl/__init__.py 
b/lib_pypy/_cffi_ssl/_stdssl/__init__.py
--- a/lib_pypy/_cffi_ssl/_stdssl/__init__.py
+++ b/lib_pypy/_cffi_ssl/_stdssl/__init__.py
@@ -1,4 +1,5 @@
 import sys
+import os
 import time
 import thread as _thread
 import weakref
@@ -82,6 +83,11 @@
 OP_NO_SSLv2 = lib.SSL_OP_NO_SSLv2
 OP_NO_SSLv3 = lib.SSL_OP_NO_SSLv3
 OP_NO_TLSv1_3 = lib.SSL_OP_NO_TLSv1_3
+if OPENSSL_VERSION_INFO > (1, 1, 0, 0, 0):
+    # OP_ENABLE_MIDDLEBOX_COMPAT = lib.SSL_OP_ENABLE_MIDDLEBOX_COMPAT
+    # XXX should be conditionally compiled into lib
+    OP_ENABLE_MIDDLEBOX_COMPAT = 0x00100000
+
  
 
 SSL_CLIENT = 0
@@ -109,6 +115,7 @@
     PROTOCOL_TLSv1_2 = 5
 # PROTOCOL_TLS_CLIENT = 0x10
 # PROTOCOL_TLS_SERVER = 0x11
+HAS_TLSv1_3 = bool(lib.Cryptography_HAS_TLSv1_3)
 
 _PROTOCOL_NAMES = (name for name in dir(lib) if name.startswith('PROTOCOL_'))
 
@@ -264,6 +271,20 @@
             mode |= lib.SSL_MODE_AUTO_RETRY
         lib.SSL_set_mode(ssl, mode)
 
+        if HAS_TLSv1_3:
+            if sslctx._post_handshake_auth:
+                if socket_type == SSL_SERVER:
+                    # bpo-37428: OpenSSL does not ignore 
SSL_VERIFY_POST_HANDSHAKE.
+                    # Set SSL_VERIFY_POST_HANDSHAKE flag only for server 
sockets and
+                    # only in combination with SSL_VERIFY_PEER flag.
+                    mode = 
lib.SSL_CTX_get_verify_mode(lib.SSL_get_SSL_CTX(self.ssl))
+                    if (mode & lib.SSL_VERIFY_PEER):
+                        verify_cb = lib.SSL_get_verify_callback(self.ssl)
+                        mode |= lib.SSL_VERIFY_POST_HANDSHAKE
+                        lib.SSL_set_verify(ssl, mode, verify_cb)
+                else:
+                    lib.SSL_set_post_handshake_auth(ssl, 1)
+
         if HAS_SNI and self.server_hostname:
             name = _str_to_ffi_buffer(self.server_hostname)
             lib.SSL_set_tlsext_host_name(ssl, name)
@@ -651,6 +672,15 @@
         else:
             return None
 
+    def verify_client_post_handshake(self):
+
+        if not HAS_TLSv1_3:
+            raise NotImplementedError("Post-handshake auth is not supported by 
"
+                                      "your OpenSSL version.")
+        err = lib.SSL_verify_client_post_handshake(self.ssl);
+        if err == 0:
+            raise pyssl_error(self, err)
+
     def pending(self):
         count = lib.SSL_pending(self.ssl)
         if count < 0:
@@ -707,6 +737,7 @@
         return bool(lib.SSL_session_reused(self.ssl))
 
 
+
 def _fs_decode(name):
     return name.decode(sys.getfilesystemencoding())
 def _fs_converter(name):
@@ -762,13 +793,13 @@
     if OPENSSL_VERSION_INFO > (1, 1, 0, 0, 0):
         aead = lib.SSL_CIPHER_is_aead(cipher)
         nid = lib.SSL_CIPHER_get_cipher_nid(cipher)
-        skcipher = OBJ_nid2ln(nid) if nid != NID_undef else None
+        skcipher = lib.OBJ_nid2ln(nid) if nid != lib.NID_undef else None
         nid = lib.SSL_CIPHER_get_digest_nid(cipher);
-        digest = OBJ_nid2ln(nid) if nid != NID_undef else None
+        digest = lib.OBJ_nid2ln(nid) if nid != lib.NID_undef else None
         nid = lib.SSL_CIPHER_get_kx_nid(cipher);
-        kx = OBJ_nid2ln(nid) if nid != NID_undef else None
-        nid = SSL_CIPHER_get_auth_nid(cipher);
-        auth = OBJ_nid2ln(nid) if nid != NID_undef else None
+        kx = lib.OBJ_nid2ln(nid) if nid != lib.NID_undef else None
+        nid = lib.SSL_CIPHER_get_auth_nid(cipher);
+        auth = lib.OBJ_nid2ln(nid) if nid != lib.NID_undef else None
         ret.update({'aead' : bool(aead),
             'symmmetric'   : skcipher,
             'digest'       : digest,
@@ -828,9 +859,8 @@
 class _SSLContext(object):
     __slots__ = ('ctx', '_check_hostname', 'servername_callback',
                  'alpn_protocols', '_alpn_protocols_handle',
-                 'npn_protocols', 'set_hostname',
+                 'npn_protocols', 'set_hostname', '_post_handshake_auth',
                  '_set_hostname_handle', '_npn_protocols_handle')
-
     def __new__(cls, protocol):
         self = object.__new__(cls)
         self.ctx = ffi.NULL
@@ -907,6 +937,9 @@
         if lib.Cryptography_HAS_X509_V_FLAG_TRUSTED_FIRST:
             store = lib.SSL_CTX_get_cert_store(self.ctx)
             lib.X509_STORE_set_flags(store, lib.X509_V_FLAG_TRUSTED_FIRST)
+        if HAS_TLSv1_3:
+            self.post_handshake_auth = 0;
+            lib.SSL_CTX_set_post_handshake_auth(self.ctx, 
self.post_handshake_auth)
         return self
 
     @property
@@ -992,6 +1025,7 @@
                              "CERT_OPTIONAL or CERT_REQUIRED")
         self._check_hostname = check_hostname
 
+
     def set_ciphers(self, cipherlist):
         cipherlistbuf = _str_to_ffi_buffer(cipherlist)
         ret = lib.SSL_CTX_set_cipher_list(self.ctx, cipherlistbuf)
@@ -1205,6 +1239,12 @@
         return stats
 
     def set_default_verify_paths(self):
+        if (not os.environ.get('SSL_CERT_FILE') and 
+            not os.environ.get('SSL_CERT_DIR') and
+            not sys.platform == 'win32'):
+                locations = get_default_verify_paths()
+                self.load_verify_locations(locations[1], locations[3])
+                return
         if not lib.SSL_CTX_set_default_verify_paths(self.ctx):
             raise ssl_error("")
 
@@ -1324,6 +1364,25 @@
         sock = _SSLSocket._new__ssl_socket(self, None, server_side, hostname, 
incoming, outgoing)
         return sock
 
+    @property
+    def post_handshake_auth(self):
+        if HAS_TLSv1_3:
+            return bool(self._post_handshake_auth)
+        return None
+
+    @post_handshake_auth.setter
+    def post_handshake_auth(self, arg):
+        if arg is None:
+            raise AttributeError("cannot delete attribute")
+
+        pha = bool(arg)
+        self._post_handshake_auth = pha;
+
+        # bpo-37428: newPySSLSocket() sets SSL_VERIFY_POST_HANDSHAKE flag for
+        # server sockets and SSL_set_post_handshake_auth() for client
+
+        return 0;
+
 
 
 # cryptography constraint: OPENSSL_NO_TLSEXT will never be set!
@@ -1548,20 +1607,69 @@
     lib.RAND_add(buf, len(buf), entropy)
 
 def get_default_verify_paths():
+    '''
+    Find a certificate store and associated values
 
+    Returns something like 
+    `('SSL_CERT_FILE', '/usr/lib/ssl/cert.pem', 'SSL_CERT_DIR', 
'/usr/lib/ssl/certs')`
+    on Ubuntu and windows10
+
+    `('SSL_CERT_FILE', '/usr/local/cert.pem', 'SSL_CERT_DIR', 
'/usr/local/certs')`
+    on CentOS
+
+    `('SSL_CERT_FILE', 
'/Library/Frameworks/Python.framework/Versions/2.7/etc/openssl/cert.pem',
+      'SSL_CERT_DIR', 
'/Library/Frameworks/Python.framework/Versions/2.7/etc/openssl/certs')`
+    on Darwin
+
+    For portable builds (based on CentOS, but could be running on any glibc
+    linux) we need to check other locations. The list of places to try was 
taken
+    from golang in Dec 2018:
+     https://golang.org/src/crypto/x509/root_unix.go (for the directories),
+     https://golang.org/src/crypto/x509/root_linux.go (for the files)
+    '''
+    certFiles = [
+        "/etc/ssl/certs/ca-certificates.crt",                # 
Debian/Ubuntu/Gentoo etc.
+        "/etc/pki/tls/certs/ca-bundle.crt",                  # Fedora/RHEL 6
+        "/etc/ssl/ca-bundle.pem",                            # OpenSUSE
+        "/etc/pki/tls/cacert.pem",                           # OpenELEC
+        "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", # CentOS/RHEL 7
+        "/etc/ssl/cert.pem",                                 # Alpine Linux
+    ]
+    certDirectories = [
+        "/etc/ssl/certs",               # SLES10/SLES11
+        "/system/etc/security/cacerts", # Android
+        "/usr/local/share/certs",       # FreeBSD
+        "/etc/pki/tls/certs",           # Fedora/RHEL
+        "/etc/openssl/certs",           # NetBSD
+        "/var/ssl/certs",               # AIX
+    ]
+
+    # optimization: reuse the values from a local varaible
+    if getattr(get_default_verify_paths, 'retval', None):
+        return get_default_verify_paths.retval
+
+    # This should never fail, it should always return SSL_CERT_FILE and 
SSL_CERT_DIR
     ofile_env = _str_from_buf(lib.X509_get_default_cert_file_env())
-    if ofile_env is None:
-        return None
+    odir_env = _str_from_buf(lib.X509_get_default_cert_dir_env())
+
+    # Platform depenedent
     ofile = _str_from_buf(lib.X509_get_default_cert_file())
-    if ofile is None:
-        return None
-    odir_env = _str_from_buf(lib.X509_get_default_cert_dir_env())
-    if odir_env is None:
-        return None
     odir = _str_from_buf(lib.X509_get_default_cert_dir())
-    if odir is None:
-        return odir
-    return (ofile_env, ofile, odir_env, odir);
+
+    if os.path.exists(ofile) and os.path.exists(odir):
+        get_default_verify_paths.retval = (ofile_env, ofile, odir_env, odir)
+        return get_default_verify_paths.retval
+
+    # OpenSSL didn't supply the goods. Try some other options
+    for f in certFiles:
+        if os.path.exists(f):
+            ofile = f 
+    for f in certDirectories:
+        if os.path.exists(f):
+            odir = f 
+    get_default_verify_paths.retval = (ofile_env, ofile, odir_env, odir)
+    return get_default_verify_paths.retval
+
 
 @ffi.callback("int(SSL*,unsigned char **,unsigned char *,const unsigned char 
*,unsigned int,void *)")
 def select_alpn_callback(ssl, out, outlen, client_protocols, 
client_protocols_len, args):
diff --git a/pypy/config/test/test_pypyoption.py 
b/pypy/config/test/test_pypyoption.py
--- a/pypy/config/test/test_pypyoption.py
+++ b/pypy/config/test/test_pypyoption.py
@@ -14,7 +14,7 @@
     conf = get_pypy_config()
     conf.translation.gc = "boehm"
     with py.test.raises(ConfigError):
-        conf.translation.gcrootfinder = 'asmgcc'
+        conf.translation.gcrootfinder = 'shadowstack'
 
 def test_frameworkgc():
     for name in ["minimark", "semispace"]:
diff --git a/pypy/doc/config/translation.gcrootfinder.txt 
b/pypy/doc/config/translation.gcrootfinder.txt
--- a/pypy/doc/config/translation.gcrootfinder.txt
+++ b/pypy/doc/config/translation.gcrootfinder.txt
@@ -1,16 +1,7 @@
 Choose the method used to find the roots in the GC.  This only
-applies to our framework GCs.  You have a choice of two
-alternatives:
+applies to our framework GCs.
 
 - ``--gcrootfinder=shadowstack``: use a so-called "shadow
   stack", which is an explicitly maintained custom stack of
-  root pointers.  This is the most portable solution.
-
-- ``--gcrootfinder=asmgcc``: use assembler hackery to find the
-  roots directly from the normal stack.  This is a bit faster,
-  but platform specific.  It works so far with GCC or MSVC,
-  on i386 and x86-64.  It is tested only on Linux 
-  so other platforms (as well as MSVC) may need
-  various fixes before they can be used. Note asmgcc will be deprecated
-  at some future date, and does not work with clang.
-
+  root pointers.  This is the most portable solution, and also
+  the only one available now.
diff --git a/pypy/doc/contributing.rst b/pypy/doc/contributing.rst
--- a/pypy/doc/contributing.rst
+++ b/pypy/doc/contributing.rst
@@ -311,16 +311,13 @@
 directory or even the top level subdirectory ``pypy``.  It takes
 hours and uses huge amounts of RAM and is not recommended.
 
-To run CPython regression tests you can point to the ``lib-python``
-directory::
-
-    py.test lib-python/2.7/test/test_datetime.py
-
-This will usually take a long time because this will run
-the PyPy Python interpreter on top of CPython.  On the plus
-side, it's usually still faster than doing a full translation
-and running the regression test with the translated PyPy Python
-interpreter.
+To run CPython regression tests, you should start with a translated PyPy and
+run the tests as you would with CPython (see below).  You can, however, also
+attempt to run the tests before translation, but be aware that it is done with
+a hack that doesn't work in all cases and it is usually extremely slow:
+``py.test lib-python/2.7/test/test_datetime.py``.  Usually, a better idea is to
+extract a minimal failing test of at most a few lines, and put it into one of
+our own tests in ``pypy/*/test/``.
 
 .. _py.test testing tool: http://pytest.org
 .. _py.test usage and invocations: http://pytest.org/latest/usage.html#usage
@@ -350,6 +347,11 @@
 
     cpython2 pytest.py -A pypy/module/cpyext/test --python=path/to/pypy3
 
+To run a test from the standard CPython regression test suite, use the regular
+Python way, i.e. (replace "pypy" with the exact binary name, if needed)::
+
+    pypy -m test.test_datetime
+
 
 Tooling & Utilities
 ^^^^^^^^^^^^^^^^^^^
diff --git a/pypy/doc/release-v7.3.0.rst b/pypy/doc/release-v7.3.0.rst
--- a/pypy/doc/release-v7.3.0.rst
+++ b/pypy/doc/release-v7.3.0.rst
@@ -133,6 +133,11 @@
 * Better support and report MSVC versions used to compile on windows
 * Allow any kind of buffer in socket.setsockopt(), like CPython (`issue 3114`_)
 * Fix importing a module with unicode in ``sys.path`` (`issue 3112`_)
+* Support OpenSSL 1.1 and TLSv1_3
+* Remove the (deprecated since 5.7) asmgcc rootfinder from the GC
+* Overflow in RPython when converting ``2<<32`` into a ``Signed`` on 32-bit
+  platforms rather than automatically using a ``SignedLongLong``, require an
+  explicit ``r_int64()`` call instead
 
 C-API (cpyext) and c-extensions
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -177,13 +182,18 @@
 * Adds encoding, decoding codepages on win32
 * Remove socket error attributes from ``_ssl`` (`issue 3119`_)
 * Add missing ``os.getgrouplist`` (part of `issue 2375`_)
+* Back-port the tentative fix from cpython: "Import deadlock detection causes
+  deadlock" (part of `issue 3111`_)
+* Fix handling of ``sys.exc_info()`` in generators
+* Return ``W_IntObject`` when converting from ``float`` to ``int`` when
+  possible, which speeds up many code paths.
 
 Python 3.6 C-API
 ~~~~~~~~~~~~~~~~
 
 * Add ``PyObject_GenericGetDict``, ``PyObject_GenericSetDict``, ``_Py_strhex``,
   ``_Py_strhex_bytes``, ``PyUnicodeNew``, ``_PyFinalizing``,
-  ``PySlice_Unpack``, ``PySlice_AdjustIndices``
+  ``PySlice_Unpack``, ``PySlice_AdjustIndices``, ``PyOS_FSPath``
 * Implement ``pystrhex.h`` (`issue 2687`_)
 * Make ``PyUnicodeObject`` slightly more compact
 * Fix memory leak when releasing a ``PyUnicodeObject``
@@ -210,6 +220,7 @@
 .. _`issue 3100`: https://bitbucket.com/pypy/pypy/issues/3100
 .. _`issue 3108`: https://bitbucket.com/pypy/pypy/issues/3108
 .. _`issue 3109`: https://bitbucket.com/pypy/pypy/issues/3109
+.. _`issue 3111`: https://bitbucket.com/pypy/pypy/issues/3111
 .. _`issue 3112`: https://bitbucket.com/pypy/pypy/issues/3112
 .. _`issue 3114`: https://bitbucket.com/pypy/pypy/issues/3114
 .. _`issue 3117`: https://bitbucket.com/pypy/pypy/issues/3117
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
@@ -3,8 +3,5 @@
 ============================
 
 .. this is a revision shortly after release-pypy-7.3.0
-.. startrev: dbbbae99135f 
+.. startrev: 994c42529580 
 
-.. branch: backport-decode_timeval_ns-py3.7
-
-Backport ``rtime.decode_timeval_ns`` from py3.7 to rpython
diff --git a/pypy/doc/whatsnew-pypy2-7.3.0.rst 
b/pypy/doc/whatsnew-pypy2-7.3.0.rst
--- a/pypy/doc/whatsnew-pypy2-7.3.0.rst
+++ b/pypy/doc/whatsnew-pypy2-7.3.0.rst
@@ -31,3 +31,11 @@
 anonymous struct/unions, cmake fragments for distribution, optimizations for
 PODs, and faster wrapper calls.
 
+.. branch: backport-decode_timeval_ns-py3.7
+
+Backport ``rtime.decode_timeval_ns`` from py3.7 to rpython
+
+.. branch: kill-asmgcc
+
+Completely remove the deprecated translation option ``--gcrootfinder=asmgcc``
+because it no longer works with a recent enough ``gcc``.
diff --git a/pypy/doc/whatsnew-pypy3-7.3.0.rst 
b/pypy/doc/whatsnew-pypy3-7.3.0.rst
--- a/pypy/doc/whatsnew-pypy3-7.3.0.rst
+++ b/pypy/doc/whatsnew-pypy3-7.3.0.rst
@@ -5,3 +5,20 @@
 .. this is the revision after release-pypy3.6-v7.2
 .. startrev: 6d2f8470165b
 
+
+.. branch: py3.6-asyncgen
+
+Fix asyncgen_hooks and refactor coroutine execution
+
+.. branch: py3.6-exc-info
+
+Follow CPython's use of exc_info more closely (issue 3096)
+
+.. branch: code_page-utf8
+
+Add encoding, decoding of codepages on windows
+
+.. branch: py3.6-exc-info-2
+
+Fix handling of sys.exc_info() in generators
+
diff --git a/pypy/doc/whatsnew-pypy3-head.rst b/pypy/doc/whatsnew-pypy3-head.rst
--- a/pypy/doc/whatsnew-pypy3-head.rst
+++ b/pypy/doc/whatsnew-pypy3-head.rst
@@ -3,5 +3,5 @@
 ==========================
 
 .. this is the revision after release-pypy3.6-v7.3.0
-.. startrev: 78b4d0a7cf2e
+.. startrev: a56889d5df88
 
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
@@ -43,8 +43,7 @@
     from rpython.rlib import rgil
 
     rgil.acquire()
-    rffi.stackcounter.stacks_counter += 1
-    llop.gc_stack_bottom(lltype.Void)   # marker for trackgcroot.py
+    llop.gc_stack_bottom(lltype.Void)   # marker to enter RPython from C
 
     cerrno._errno_after(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)
 
@@ -69,7 +68,6 @@
 
     cerrno._errno_before(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)
 
-    rffi.stackcounter.stacks_counter -= 1
     rgil.release()
 
 
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
@@ -1026,8 +1026,7 @@
         else:
             gilstate = pystate.PyGILState_IGNORE
 
-        rffi.stackcounter.stacks_counter += 1
-        llop.gc_stack_bottom(lltype.Void)   # marker for trackgcroot.py
+        llop.gc_stack_bottom(lltype.Void)   # marker to enter RPython from C
         retval = fatal_value
         boxed_args = ()
         tb = None
@@ -1104,7 +1103,6 @@
             return fatal_value
 
         assert lltype.typeOf(retval) == restype
-        rffi.stackcounter.stacks_counter -= 1
 
         _restore_gil_state(pygilstate_release, gilstate, gil_release, 
_gil_auto, tid)
         return retval
diff --git a/pypy/module/thread/os_thread.py b/pypy/module/thread/os_thread.py
--- a/pypy/module/thread/os_thread.py
+++ b/pypy/module/thread/os_thread.py
@@ -30,7 +30,7 @@
 #   called from the rffi-generated wrapper).  The gc_thread_run()
 #   operation will automatically notice that the current thread id was
 #   not seen before, and (in shadowstack) it will allocate and use a
-#   fresh new stack.  Again, this has no effect in asmgcc.
+#   fresh new stack.
 #
 # * Only then does bootstrap() really run.  The first thing it does
 #   is grab the start-up information (app-level callable and args)
@@ -43,7 +43,7 @@
 #   thread.
 #
 # * Just before a thread finishes, gc_thread_die() is called to free
-#   its shadow stack.  This has no effect in asmgcc.
+#   its shadow stack.
 
 
 class Bootstrapper(object):
diff --git a/pypy/tool/release/repackage.sh b/pypy/tool/release/repackage.sh
--- a/pypy/tool/release/repackage.sh
+++ b/pypy/tool/release/repackage.sh
@@ -2,8 +2,8 @@
 pmaj=2  # python main version: 2 or 3
 pmin=7  # python minor version
 maj=7
-min=2
-rev=0rc2
+min=3
+rev=0rc1
 
 case $pmaj in
     "2") exe=pypy;;
diff --git a/rpython/config/test/test_translationoption.py 
b/rpython/config/test/test_translationoption.py
--- a/rpython/config/test/test_translationoption.py
+++ b/rpython/config/test/test_translationoption.py
@@ -13,13 +13,6 @@
     config.translation.gcrootfinder = "shadowstack"
     py.test.raises(ConflictConfigError, set_opt_level, config, '0')
 
-if compiler.name == 'msvc' or sys.platform == 'darwin':
-    def test_no_asmgcrot_on_msvc():
-        config = get_combined_translation_config()
-        config.translation.gcrootfinder = "asmgcc"
-        py.test.raises(ConfigError, set_opt_level, config, 'jit') 
-
-
 def test_get_translation_config():
     from rpython.translator.interactive import Translation
     from rpython.config import config
diff --git a/rpython/config/translationoption.py 
b/rpython/config/translationoption.py
--- a/rpython/config/translationoption.py
+++ b/rpython/config/translationoption.py
@@ -18,10 +18,6 @@
 DEFL_GC = "incminimark"   # XXX
 
 DEFL_ROOTFINDER_WITHJIT = "shadowstack"
-## if sys.platform.startswith("linux"):
-##     _mach = os.popen('uname -m', 'r').read().strip()
-##     if _mach.startswith('x86') or _mach in ['i386', 'i486', 'i586', 'i686']:
-##         DEFL_ROOTFINDER_WITHJIT = "asmgcc"   # only for Linux on x86 / 
x86-64
 
 IS_64_BITS = sys.maxint > 2147483647
 
@@ -100,13 +96,11 @@
                default=IS_64_BITS, cmdline="--gcremovetypeptr"),
     ChoiceOption("gcrootfinder",
                  "Strategy for finding GC Roots (framework GCs only)",
-                 ["n/a", "shadowstack", "asmgcc"],
+                 ["n/a", "shadowstack"],
                  "shadowstack",
                  cmdline="--gcrootfinder",
                  requires={
                      "shadowstack": [("translation.gctransformer", 
"framework")],
-                     "asmgcc": [("translation.gctransformer", "framework"),
-                                ("translation.backend", "c")],
                     }),
 
     # other noticeable options
@@ -402,10 +396,6 @@
     # if we have specified strange inconsistent settings.
     config.translation.gc = config.translation.gc
 
-    # disallow asmgcc on OS/X and on Win32
-    if config.translation.gcrootfinder == "asmgcc":
-        if sys.platform == "darwin" or sys.platform =="win32":
-            raise ConfigError("'asmgcc' not supported on this platform")
 
 # ----------------------------------------------------------------
 
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
@@ -438,51 +438,8 @@
 
     @staticmethod
     @rgc.no_collect
-    def _reacquire_gil_asmgcc(css, old_rpy_fastgil):
-        # Before doing an external call, 'rpy_fastgil' is initialized to
-        # be equal to css.  This function is called if we find out after
-        # 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
-            # 'rpy_fastgil' from 0 to 1, thus successfully reaquiring the
-            # GIL.
-            pass
-
-        elif old_rpy_fastgil == 1:
-            # 'rpy_fastgil' was (and still is) locked by someone else.
-            # We need to wait for the regular mutex.
-            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
-            # the 'old_rpy_fastgil' into the chained list.
-            from rpython.memory.gctransform import asmgcroot
-            oth = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, old_rpy_fastgil)
-            next = asmgcroot.gcrootanchor.next
-            oth.next = next
-            oth.prev = asmgcroot.gcrootanchor
-            asmgcroot.gcrootanchor.next = oth
-            next.prev = oth
-
-        # similar to trackgcroot.py:pypy_asm_stackwalk, second part:
-        # detach the 'css' from the chained list
-        from rpython.memory.gctransform import asmgcroot
-        old = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css)
-        prev = old.prev
-        next = old.next
-        prev.next = next
-        next.prev = prev
-
-    @staticmethod
-    @rgc.no_collect
     def _reacquire_gil_shadowstack():
-        # Simplified version of _reacquire_gil_asmgcc(): in shadowstack mode,
+        # This used to be more complex for asmgcc.  In shadowstack mode,
         # '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)
@@ -499,13 +456,10 @@
                                      self._reacquire_gil_shadowstack)
             self.reacqgil_addr = self.cpu.cast_ptr_to_int(reacqgil_func)
         else:
-            reacqgil_func = llhelper(self._REACQGIL2_FUNC,
-                                     self._reacquire_gil_asmgcc)
-            self.reacqgil_addr = self.cpu.cast_ptr_to_int(reacqgil_func)
+            raise AssertionError("!is_shadow_stack")
 
     def _is_asmgcc(self):
-        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
-        return bool(gcrootmap) and not gcrootmap.is_shadow_stack
+        return False        # legacy
 
 
 def debug_bridge(descr_number, rawstart, codeendpos):
diff --git a/rpython/jit/backend/llsupport/gc.py 
b/rpython/jit/backend/llsupport/gc.py
--- a/rpython/jit/backend/llsupport/gc.py
+++ b/rpython/jit/backend/llsupport/gc.py
@@ -21,7 +21,6 @@
 from rpython.jit.backend.llsupport.descr import get_call_descr
 from rpython.jit.backend.llsupport.descr import unpack_arraydescr
 from rpython.jit.backend.llsupport.rewrite import GcRewriterAssembler
-from rpython.memory.gctransform import asmgcroot
 from rpython.jit.codewriter.effectinfo import EffectInfo
 
 # ____________________________________________________________
@@ -117,7 +116,7 @@
         descrs = JitFrameDescrs()
         descrs.arraydescr = cpu.arraydescrof(jitframe.JITFRAME)
         for name in ['jf_descr', 'jf_guard_exc', 'jf_force_descr',
-                     'jf_frame_info', 'jf_gcmap', 'jf_extra_stack_depth',
+                     'jf_frame_info', 'jf_gcmap',
                      'jf_savedata', 'jf_forward']:
             setattr(descrs, name, cpu.fielddescrof(jitframe.JITFRAME, name))
         descrs.jfi_frame_size = cpu.fielddescrof(jitframe.JITFRAMEINFO,
@@ -244,15 +243,6 @@
 # ____________________________________________________________
 # All code below is for the hybrid or minimark GC
 
-class GcRootMap_asmgcc(object):
-    is_shadow_stack = False
-
-    def __init__(self, gcdescr):
-        pass
-
-    def register_asm_addr(self, start, mark):
-        pass
-
 class GcRootMap_shadowstack(object):
     is_shadow_stack = True
 
diff --git a/rpython/jit/backend/llsupport/jitframe.py 
b/rpython/jit/backend/llsupport/jitframe.py
--- a/rpython/jit/backend/llsupport/jitframe.py
+++ b/rpython/jit/backend/llsupport/jitframe.py
@@ -49,7 +49,6 @@
     rgc.register_custom_trace_hook(JITFRAME, lambda_jitframe_trace)
     frame = lltype.malloc(JITFRAME, frame_info.jfi_frame_depth)
     frame.jf_frame_info = frame_info
-    frame.jf_extra_stack_depth = 0
     return frame
 
 def jitframe_resolve(frame):
@@ -71,8 +70,6 @@
     ('jf_force_descr', llmemory.GCREF),
     # a map of GC pointers
     ('jf_gcmap', lltype.Ptr(GCMAP)),
-    # how much we decrease stack pointer. Used around calls and malloc slowpath
-    ('jf_extra_stack_depth', lltype.Signed),
     # For the front-end: a GCREF for the savedata
     ('jf_savedata', llmemory.GCREF),
     # For GUARD_(NO)_EXCEPTION and GUARD_NOT_FORCED: the exception we
@@ -103,7 +100,6 @@
 LENGTHOFS = llmemory.arraylengthoffset(JITFRAME.jf_frame)
 SIGN_SIZE = llmemory.sizeof(lltype.Signed)
 UNSIGN_SIZE = llmemory.sizeof(lltype.Unsigned)
-STACK_DEPTH_OFS = getofs('jf_extra_stack_depth')
 
 def jitframe_trace(gc, obj_addr, callback, arg):
     gc._trace_callback(callback, arg, obj_addr + getofs('jf_descr'))
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
@@ -584,8 +584,6 @@
 
             length = self.emit_getfield(ConstInt(frame_info),
                                         descr=descrs.jfi_frame_depth, raw=True)
-            self.emit_setfield(frame, self.c_zero,
-                               descr=descrs.jf_extra_stack_depth)
             self.emit_setfield(frame, self.c_null,
                                descr=descrs.jf_savedata)
             self.emit_setfield(frame, self.c_null,
diff --git a/rpython/jit/backend/llsupport/test/test_gc.py 
b/rpython/jit/backend/llsupport/test/test_gc.py
--- a/rpython/jit/backend/llsupport/test/test_gc.py
+++ b/rpython/jit/backend/llsupport/test/test_gc.py
@@ -110,7 +110,7 @@
         class config_(object):
             class translation(object):
                 gc = self.gc
-                gcrootfinder = 'asmgcc'
+                gcrootfinder = 'shadowstack'
                 gctransformer = 'framework'
                 gcremovetypeptr = False
         class FakeTranslator(object):
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
@@ -507,7 +507,6 @@
     ('jf_frame_info', lltype.Ptr(jitframe.JITFRAMEINFO)),
     ('jf_descr', llmemory.GCREF),
     ('jf_force_descr', llmemory.GCREF),
-    ('jf_extra_stack_depth', lltype.Signed),
     ('jf_guard_exc', llmemory.GCREF),
     ('jf_gcmap', lltype.Ptr(jitframe.GCMAP)),
     ('jf_gc_trace_state', lltype.Signed),
@@ -594,7 +593,7 @@
         descrs = JitFrameDescrs()
         descrs.arraydescr = cpu.arraydescrof(JITFRAME)
         for name in ['jf_descr', 'jf_guard_exc', 'jf_force_descr',
-                     'jf_frame_info', 'jf_gcmap', 'jf_extra_stack_depth']:
+                     'jf_frame_info', 'jf_gcmap']:
             setattr(descrs, name, cpu.fielddescrof(JITFRAME, name))
         descrs.jfi_frame_depth = cpu.fielddescrof(jitframe.JITFRAMEINFO,
                                                   'jfi_frame_depth')
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
@@ -170,7 +170,6 @@
         jf_descr = framedescrs.jf_descr
         jf_guard_exc = framedescrs.jf_guard_exc
         jf_forward = framedescrs.jf_forward
-        jf_extra_stack_depth = framedescrs.jf_extra_stack_depth
         signedframedescr = self.cpu.signedframedescr
         floatframedescr = self.cpu.floatframedescr
         casmdescr.compiled_loop_token = clt
@@ -386,7 +385,7 @@
         class config_(object):
             class translation(object):
                 gc = 'minimark'
-                gcrootfinder = 'asmgcc'
+                gcrootfinder = 'shadowstack'
                 gctransformer = 'framework'
                 gcremovetypeptr = False
         gcdescr = get_description(config_)
@@ -1102,7 +1101,6 @@
         p1 = call_malloc_nursery_varsize_frame(i1)
         gc_store(p1, 0,  0, %(tiddescr.field_size)s)
         i2 = gc_load_i(ConstClass(frame_info), %(jfi_frame_depth.offset)s, 
%(jfi_frame_depth.field_size)s)
-        %(setfield('p1', 0, jf_extra_stack_depth))s
         %(setfield('p1', 'NULL', jf_savedata))s
         %(setfield('p1', 'NULL', jf_force_descr))s
         %(setfield('p1', 'NULL', jf_descr))s
diff --git a/rpython/jit/backend/llsupport/test/zrpy_gc_test.py 
b/rpython/jit/backend/llsupport/test/zrpy_gc_test.py
--- a/rpython/jit/backend/llsupport/test/zrpy_gc_test.py
+++ b/rpython/jit/backend/llsupport/test/zrpy_gc_test.py
@@ -176,9 +176,6 @@
             cls.cbuilder = compile(get_entry(allfuncs), cls.gc,
                                    gcrootfinder=cls.gcrootfinder, jit=True,
                                    thread=True)
-        except ConfigError as e:        
-            assert str(e).startswith('invalid value asmgcc')
-            py.test.skip('asmgcc not supported')
         finally:
             GcLLDescr_framework.DEBUG = OLD_DEBUG
 
diff --git a/rpython/jit/backend/llsupport/test/ztranslation_test.py 
b/rpython/jit/backend/llsupport/test/ztranslation_test.py
--- a/rpython/jit/backend/llsupport/test/ztranslation_test.py
+++ b/rpython/jit/backend/llsupport/test/ztranslation_test.py
@@ -331,9 +331,6 @@
         try:
             res = self.meta_interp(main, [400])
             assert res == main(400)
-        except ConfigError as e:
-            assert str(e).startswith('invalid value asmgcc')
-            py.test.skip('asmgcc not supported')
         finally:
             del os.environ['PYPYLOG']
 
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
@@ -4725,6 +4725,7 @@
 
     def test_raw_load_int(self):
         from rpython.rlib import rawstorage
+        from rpython.rlib.rarithmetic import r_longlong
         for T in [rffi.UCHAR, rffi.SIGNEDCHAR,
                   rffi.USHORT, rffi.SHORT,
                   rffi.UINT, rffi.INT,
@@ -4738,7 +4739,7 @@
             p = rawstorage.alloc_raw_storage(31)
             for i in range(31):
                 p[i] = '\xDD'
-            value = rffi.cast(T, -0x4243444546474849)
+            value = rffi.cast(T, r_longlong(-0x4243444546474849))
             rawstorage.raw_storage_setitem(p, 16, value)
             got = self.cpu.bh_raw_load_i(rffi.cast(lltype.Signed, p), 16,
                                          arraydescr)
diff --git a/rpython/jit/backend/x86/arch.py b/rpython/jit/backend/x86/arch.py
--- a/rpython/jit/backend/x86/arch.py
+++ b/rpython/jit/backend/x86/arch.py
@@ -35,9 +35,7 @@
     PASS_ON_MY_FRAME = 15
     JITFRAME_FIXED_SIZE = 6 + 8 * 2 # 6 GPR + 8 XMM * 2 WORDS/float
     # 'threadlocal_addr' is passed as 2nd argument on the stack,
-    # and it can be left here for when it is needed.  As an additional hack,
-    # with asmgcc, it is made odd-valued to mean "already seen this frame
-    # during the previous minor collection".
+    # and it can be left here for when it is needed.
     THREADLOCAL_OFS = (FRAME_FIXED_SIZE + 2) * WORD
 else:
     # rbp + rbx + r12 + r13 + r14 + r15 + threadlocal + 12 extra words = 19
@@ -45,12 +43,10 @@
     PASS_ON_MY_FRAME = 12
     JITFRAME_FIXED_SIZE = 28 # 13 GPR + 15 XMM
     # 'threadlocal_addr' is passed as 2nd argument in %esi,
-    # and is moved into this frame location.  As an additional hack,
-    # with asmgcc, it is made odd-valued to mean "already seen this frame
-    # during the previous minor collection".
+    # and is moved into this frame location.
     THREADLOCAL_OFS = (FRAME_FIXED_SIZE - 1) * WORD
 
-assert PASS_ON_MY_FRAME >= 12       # asmgcc needs at least JIT_USE_WORDS + 3
+assert PASS_ON_MY_FRAME >= 12
 
 # return address, followed by FRAME_FIXED_SIZE words
 DEFAULT_FRAME_BYTES = (1 + FRAME_FIXED_SIZE) * WORD
diff --git a/rpython/jit/backend/x86/assembler.py 
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -137,11 +137,6 @@
         self.expand_byte_mask_addr = float_constants + 64
         self.element_ones = [float_constants + 80 + 16*i for i in range(4)]
 
-    def set_extra_stack_depth(self, mc, value):
-        if self._is_asmgcc():
-            extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth')
-            mc.MOV_bi(extra_ofs, value)
-
     def build_frame_realloc_slowpath(self):
         mc = codebuf.MachineCodeBlockWrapper()
         self._push_all_regs_to_frame(mc, [], self.cpu.supports_floats)
@@ -161,14 +156,20 @@
             mc.MOV_sr(0, ebp.value)
         # align
 
-        self.set_extra_stack_depth(mc, align * WORD)
+        #
+        # * Note: these commented-out pieces of code about 'extra_stack_depth'
+        # * are not necessary any more, but they are kept around in case we
+        # * need in the future again to track the exact stack depth.
+        #
+        #self.set_extra_stack_depth(mc, align * WORD)
+
         self._store_and_reset_exception(mc, None, ebx, ecx)
 
         mc.CALL(imm(self.cpu.realloc_frame))
         mc.MOV_rr(ebp.value, eax.value)
         self._restore_exception(mc, None, ebx, ecx)
         mc.ADD_ri(esp.value, (align - 1) * WORD)
-        self.set_extra_stack_depth(mc, 0)
+        #self.set_extra_stack_depth(mc, 0)
 
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         if gcrootmap and gcrootmap.is_shadow_stack:
@@ -196,12 +197,12 @@
         # the caller already did push_gcmap(store=True)
         if IS_X86_64:
             mc.SUB(esp, imm(WORD))     # alignment
-            self.set_extra_stack_depth(mc, 2 * WORD)
+            #self.set_extra_stack_depth(mc, 2 * WORD)
             # the arguments are already in the correct registers
         else:
             # we want space for 4 arguments + call + alignment
             mc.SUB(esp, imm(WORD * 7))
-            self.set_extra_stack_depth(mc, 8 * WORD)
+            #self.set_extra_stack_depth(mc, 8 * WORD)
             # store the arguments at the correct place in the stack
             for i in range(4):
                 mc.MOV_sr(i * WORD, cond_call_register_arguments[i].value)
@@ -211,7 +212,7 @@
             mc.ADD(esp, imm(WORD))
         else:
             mc.ADD(esp, imm(WORD * 7))
-        self.set_extra_stack_depth(mc, 0)
+        #self.set_extra_stack_depth(mc, 0)
         self.pop_gcmap(mc)   # cancel the push_gcmap(store=True) in the caller
         self._pop_all_regs_from_frame(mc, [eax], supports_floats, callee_only)
         mc.RET()
@@ -275,11 +276,11 @@
                 # (already in edx)              # length
                 mc.MOV_rr(esi.value, ecx.value) # tid
                 mc.MOV_rs(edi.value, WORD * 3)  # load the itemsize
-        self.set_extra_stack_depth(mc, 16)
+        #self.set_extra_stack_depth(mc, 16)
         mc.CALL(imm(follow_jump(addr)))
         self._reload_frame_if_necessary(mc)
         mc.ADD_ri(esp.value, 16 - WORD)
-        self.set_extra_stack_depth(mc, 0)
+        #self.set_extra_stack_depth(mc, 0)
         #
         mc.TEST_rr(eax.value, eax.value)
         # common case: not taken
@@ -1018,8 +1019,6 @@
         from rpython.rlib.rvmprof.rvmprof import cintf
         # edx = address of pypy_threadlocal_s
         self.mc.MOV_rs(edx.value, THREADLOCAL_OFS)
-        if self._is_asmgcc():
-            self.mc.AND_ri(edx.value, ~1)
         # eax = (our local vmprof_tl_stack).next
         self.mc.MOV_rs(eax.value, (FRAME_FIXED_SIZE - 4 + 0) * WORD)
         # save in vmprof_tl_stack the value eax
@@ -2236,25 +2235,6 @@
 
     def _call_assembler_emit_call(self, addr, argloc, _):
         threadlocal_loc = RawEspLoc(THREADLOCAL_OFS, INT)
-        if self._is_asmgcc():
-            # We need to remove the bit "already seen during the
-            # previous minor collection" instead of passing this
-            # value directly.
-            if IS_X86_64:
-                tmploc = esi    # already the correct place
-                if argloc is tmploc:
-                    # this case is theoretical only so far: in practice,
-                    # argloc is always eax, never esi
-                    self.mc.MOV_rr(edi.value, esi.value)
-                    argloc = edi
-            else:
-                tmploc = eax
-                if tmploc is argloc:
-                    tmploc = edx
-            self.mc.MOV(tmploc, threadlocal_loc)
-            self.mc.AND_ri(tmploc.value, ~1)
-            threadlocal_loc = tmploc
-        #
         self.simple_call(addr, [argloc, threadlocal_loc])
 
     def _call_assembler_emit_helper_call(self, addr, arglocs, result_loc):
@@ -2672,8 +2652,6 @@
         assert self.cpu.translate_support_code
         assert isinstance(resloc, RegLoc)
         self.mc.MOV_rs(resloc.value, THREADLOCAL_OFS)
-        if self._is_asmgcc():
-            self.mc.AND_ri(resloc.value, ~1)
         self.load_from_mem(resloc, addr_add_const(resloc, offset),
                            imm(size), imm(sign))
 
diff --git a/rpython/jit/backend/x86/callbuilder.py 
b/rpython/jit/backend/x86/callbuilder.py
--- a/rpython/jit/backend/x86/callbuilder.py
+++ b/rpython/jit/backend/x86/callbuilder.py
@@ -61,13 +61,6 @@
             self.arglocs = arglocs + [fnloc]
         self.start_frame_size = self.mc._frame_size
 
-    def select_call_release_gil_mode(self):
-        AbstractCallBuilder.select_call_release_gil_mode(self)
-        if self.asm._is_asmgcc():
-            from rpython.memory.gctransform import asmgcroot
-            self.stack_max = PASS_ON_MY_FRAME - asmgcroot.JIT_USE_WORDS
-            assert self.stack_max >= 3
-
     def subtract_esp_aligned(self, count):
         if count > 0:
             align = align_stack_words(count)
@@ -103,9 +96,14 @@
         # value eax, if necessary
         assert not self.is_call_release_gil
         current_esp = self.get_current_esp()
-        self.change_extra_stack_depth = (current_esp != 0)
-        if self.change_extra_stack_depth:
-            self.asm.set_extra_stack_depth(self.mc, -current_esp)
+        #
+        # * Note: these commented-out pieces of code about 'extra_stack_depth'
+        # * are not necessary any more, but they are kept around in case we
+        # * need in the future again to track the exact stack depth.
+        #
+        #self.change_extra_stack_depth = (current_esp != 0)
+        #if self.change_extra_stack_depth:
+        #    self.asm.set_extra_stack_depth(self.mc, -current_esp)
         noregs = self.asm.cpu.gc_ll_descr.is_shadow_stack()
         gcmap = self.asm._regalloc.get_gcmap([eax], noregs=noregs)
         self.asm.push_gcmap(self.mc, gcmap, store=True)
@@ -119,13 +117,14 @@
                 # top at this point, so reuse it instead of loading it again
                 ssreg = ebx
         self.asm._reload_frame_if_necessary(self.mc, shadowstack_reg=ssreg)
-        if self.change_extra_stack_depth:
-            self.asm.set_extra_stack_depth(self.mc, 0)
+        #if self.change_extra_stack_depth:
+        #    self.asm.set_extra_stack_depth(self.mc, 0)
         self.asm.pop_gcmap(self.mc)
 
     def call_releasegil_addr_and_move_real_arguments(self, fastgil):
         from rpython.jit.backend.x86.assembler import heap
         assert self.is_call_release_gil
+        assert not self.asm._is_asmgcc()
         #
         # Save this thread's shadowstack pointer into 'ebx',
         # for later comparison
@@ -135,38 +134,12 @@
                 rst = gcrootmap.get_root_stack_top_addr()
                 self.mc.MOV(ebx, heap(rst))
         #
-        if not self.asm._is_asmgcc():
-            # shadowstack: change 'rpy_fastgil' to 0 (it should be
-            # non-zero right now).
-            self.change_extra_stack_depth = False
-            # ^^ note that set_extra_stack_depth() in this case is a no-op
-            css_value = imm(0)
-        else:
-            from rpython.memory.gctransform import asmgcroot
-            # build a 'css' structure on the stack: 2 words for the linkage,
-            # and 5/7 words as described for asmgcroot.ASM_FRAMEDATA, for a
-            # total size of JIT_USE_WORDS.  This structure is found at
-            # [ESP+css].
-            css = -self.get_current_esp() + (
-                WORD * (PASS_ON_MY_FRAME - asmgcroot.JIT_USE_WORDS))
-            assert css >= 2 * WORD
-            # Save ebp
-            index_of_ebp = css + WORD * (2+asmgcroot.INDEX_OF_EBP)
-            self.mc.MOV_sr(index_of_ebp, ebp.value)  # MOV [css.ebp], EBP
-            # Save the "return address": we pretend that it's css
-            self.mc.LEA_rs(eax.value, css)           # LEA eax, [css]
-            frame_ptr = css + WORD * (2+asmgcroot.FRAME_PTR)
-            self.mc.MOV_sr(frame_ptr, eax.value)     # MOV [css.frame], eax
-            # Set up jf_extra_stack_depth to pretend that the return address
-            # was at css, and so our stack frame is supposedly shorter by
-            # (PASS_ON_MY_FRAME-JIT_USE_WORDS+1) words
-            delta = PASS_ON_MY_FRAME - asmgcroot.JIT_USE_WORDS + 1
-            self.change_extra_stack_depth = True
-            self.asm.set_extra_stack_depth(self.mc, -delta * WORD)
-            css_value = eax
+        # shadowstack: change 'rpy_fastgil' to 0 (it should be
+        # non-zero right now).
+        #self.change_extra_stack_depth = False
         #
         # <--here--> would come a memory fence, if the CPU needed one.
-        self.mc.MOV(heap(fastgil), css_value)
+        self.mc.MOV(heap(fastgil), imm(0))
         #
         if not we_are_translated():        # for testing: we should not access
             self.mc.ADD(ebp, imm(1))       # ebp any more
@@ -184,8 +157,6 @@
                 self.tlofs_reg = r12
             self.mc.MOV_rs(self.tlofs_reg.value,
                            THREADLOCAL_OFS - self.get_current_esp())
-            if self.asm._is_asmgcc():
-                self.mc.AND_ri(self.tlofs_reg.value, ~1)
         return self.tlofs_reg
 
     def save_stack_position(self):
@@ -318,13 +289,6 @@
             cb = self.callbuilder
             if not cb.result_value_saved_early:
                 cb.save_result_value(save_edx=False)
-            if assembler._is_asmgcc():
-                if IS_X86_32:
-                    css_value = edx
-                    old_value = ecx
-                    mc.MOV_sr(4, old_value.value)
-                    mc.MOV_sr(0, css_value.value)
-                # on X86_64, they are already in the right registers
             mc.CALL(imm(follow_jump(assembler.reacqgil_addr)))
             if not cb.result_value_saved_early:
                 cb.restore_result_value(save_edx=False)
@@ -333,29 +297,10 @@
         from rpython.jit.backend.x86 import rx86
         #
         # check if we need to call the reacqgil() function or not
-        # (to acquiring the GIL, remove the asmgcc head from
-        # the chained list, etc.)
+        # (to acquiring the GIL)
         mc = self.mc
         restore_edx = False
-        if not self.asm._is_asmgcc():
-            css = 0
-            css_value = imm(0)
-            old_value = ecx
-        else:
-            from rpython.memory.gctransform import asmgcroot
-            css = WORD * (PASS_ON_MY_FRAME - asmgcroot.JIT_USE_WORDS)
-            if IS_X86_32:
-                assert css >= 16
-                if self.restype == 'L':    # long long result: eax/edx
-                    if not self.result_value_saved_early:
-                        mc.MOV_sr(12, edx.value)
-                        restore_edx = True
-                css_value = edx    # note: duplicated in ReacqGilSlowPath
-                old_value = ecx    #
-            elif IS_X86_64:
-                css_value = edi
-                old_value = esi
-            mc.LEA_rs(css_value.value, css)
+        old_value = ecx
         #
         # Use XCHG as an atomic test-and-set-lock.  It also implicitly
         # does a memory barrier.
@@ -365,11 +310,12 @@
         else:
             mc.MOV_ri(X86_64_SCRATCH_REG.value, fastgil)
             mc.XCHG_rm(old_value.value, (X86_64_SCRATCH_REG.value, 0))
-        mc.CMP(old_value, css_value)
+        mc.CMP(old_value, imm(0))
         #
         gcrootmap = self.asm.cpu.gc_ll_descr.gcrootmap
-        if bool(gcrootmap) and gcrootmap.is_shadow_stack:
+        if bool(gcrootmap):
             from rpython.jit.backend.x86.assembler import heap
+            assert gcrootmap.is_shadow_stack
             #
             # When doing a call_release_gil with shadowstack, there
             # is the risk that the 'rpy_fastgil' was free but the
@@ -406,14 +352,8 @@
         if not we_are_translated():    # for testing: now we can accesss
             mc.SUB(ebp, imm(1))        # ebp again
         #
-        # Now that we required the GIL, we can reload a possibly modified ebp
-        if self.asm._is_asmgcc():
-            # special-case: reload ebp from the css
-            from rpython.memory.gctransform import asmgcroot
-            index_of_ebp = css + WORD * (2+asmgcroot.INDEX_OF_EBP)
-            mc.MOV_rs(ebp.value, index_of_ebp)  # MOV EBP, [css.ebp]
-        #else:
-        #   for shadowstack, done for us by _reload_frame_if_necessary()
+        # Now that we required the GIL, we will reload a possibly modified ebp:
+        # this done for us by _reload_frame_if_necessary()
 
     def save_result_value(self, save_edx):
         """Overridden in CallBuilder32 and CallBuilder64"""
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
@@ -829,10 +829,7 @@
         self.xrm.before_call(save_all_regs=save_all_regs)
         if gc_level == SAVE_GCREF_REGS:
             gcrootmap = self.assembler.cpu.gc_ll_descr.gcrootmap
-            # we save all the GCREF registers for shadowstack and asmgcc for 
now
-            # --- for asmgcc too: we can't say "register x is a gc ref"
-            # without distinguishing call sites, which we don't do any
-            # more for now.
+            # we save all the GCREF registers for shadowstack
             if gcrootmap: # and gcrootmap.is_shadow_stack:
                 save_all_regs = SAVE_GCREF_REGS
         self.rm.before_call(save_all_regs=save_all_regs)
@@ -940,15 +937,6 @@
     consider_cond_call_gc_wb_array = consider_cond_call_gc_wb
 
     def consider_cond_call(self, op):
-        # A 32-bit-only, asmgcc-only issue: 'cond_call_register_arguments'
-        # contains edi and esi, which are also in asmgcroot.py:ASM_FRAMEDATA.
-        # We must make sure that edi and esi do not contain GC pointers.
-        if IS_X86_32 and self.assembler._is_asmgcc():
-            for box, loc in self.rm.reg_bindings.items():
-                if (loc == edi or loc == esi) and box.type == REF:
-                    self.rm.force_spill_var(box)
-                    assert box not in self.rm.reg_bindings
-        #
         args = op.getarglist()
         assert 2 <= len(args) <= 4 + 2     # maximum 4 arguments
         v_func = args[1]
diff --git a/rpython/jit/backend/x86/test/test_runner.py 
b/rpython/jit/backend/x86/test/test_runner.py
--- a/rpython/jit/backend/x86/test/test_runner.py
+++ b/rpython/jit/backend/x86/test/test_runner.py
@@ -285,12 +285,15 @@
         cases = [8, 16, 24]
         if WORD == 8:
             cases.append(32)
+            bigvalue = 0xAAAAAAAAAAAA
+        else:
+            bigvalue = 0xAAAAAAA
         for i in cases:
-            box = InputArgInt(0xAAAAAAAAAAAA)
+            box = InputArgInt(bigvalue)
             res = self.execute_operation(rop.INT_AND,
                                          [box, ConstInt(2 ** i - 1)],
                                          'int')
-            assert res == 0xAAAAAAAAAAAA & (2 ** i - 1)
+            assert res == bigvalue & (2 ** i - 1)
 
     def test_nullity_with_guard(self):
         allops = [rop.INT_IS_TRUE]
diff --git a/rpython/jit/backend/x86/test/test_rx86.py 
b/rpython/jit/backend/x86/test/test_rx86.py
--- a/rpython/jit/backend/x86/test/test_rx86.py
+++ b/rpython/jit/backend/x86/test/test_rx86.py
@@ -1,4 +1,5 @@
 import py, struct
+from rpython.rlib.rarithmetic import r_longlong
 from rpython.jit.backend.x86.rx86 import *
 globals().update(R.__dict__)
 
@@ -210,8 +211,8 @@
     s.MOV_ri(ebx, -0x80000003)
     s.MOV_ri(r13, -0x80000002)
     s.MOV_ri(ecx, 42)
-    s.MOV_ri(r12, 0x80000042)
-    s.MOV_ri(r12, 0x100000007)
+    s.MOV_ri(r12, r_longlong(0x80000042))
+    s.MOV_ri(r12, r_longlong(0x100000007))
     assert s.getvalue() == ('\x48\xC7\xC1\xFE\xFF\xFF\xFF' +
                             '\x49\xC7\xC7\xFD\xFF\xFF\xFF' +
                             '\x48\xBB\xFD\xFF\xFF\x7F\xFF\xFF\xFF\xFF' +
diff --git a/rpython/jit/backend/x86/test/test_rx86_64_auto_encoding.py 
b/rpython/jit/backend/x86/test/test_rx86_64_auto_encoding.py
--- a/rpython/jit/backend/x86/test/test_rx86_64_auto_encoding.py
+++ b/rpython/jit/backend/x86/test/test_rx86_64_auto_encoding.py
@@ -1,7 +1,11 @@
+import sys, py
 import random
 from rpython.jit.backend.x86 import rx86
 from rpython.jit.backend.x86.test import test_rx86_32_auto_encoding
 
+if sys.maxint <= 2**32:
+    py.test.skip("skipping this test on x86-32")
+
 
 class TestRx86_64(test_rx86_32_auto_encoding.TestRx86_32):
     WORD = 8
diff --git a/rpython/jit/backend/x86/test/test_zrpy_gcasmgcc.py 
b/rpython/jit/backend/x86/test/test_zrpy_gcasmgcc.py
deleted file mode 100644
--- a/rpython/jit/backend/x86/test/test_zrpy_gcasmgcc.py
+++ /dev/null
@@ -1,9 +0,0 @@
-import py
-from rpython.jit.backend.llsupport.test.zrpy_gc_test import 
CompileFrameworkTests
-from rpython.translator.platform import platform as compiler
-
-if compiler.name == 'msvc':
-    py.test.skip('asmgcc buggy on msvc')
-
-class TestAsmGcc(CompileFrameworkTests):
-    gcrootfinder = "asmgcc"
diff --git a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py 
b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py
--- a/rpython/jit/backend/x86/test/test_zrpy_releasegil.py
+++ b/rpython/jit/backend/x86/test/test_zrpy_releasegil.py
@@ -1,11 +1,5 @@
 from rpython.jit.backend.llsupport.test.zrpy_releasegil_test import 
ReleaseGILTests
-from rpython.translator.platform import platform as compiler
 
 
 class TestShadowStack(ReleaseGILTests):
     gcrootfinder = "shadowstack"
-
-
-if compiler.name != 'msvc':
-    class TestAsmGcc(ReleaseGILTests):
-        gcrootfinder = "asmgcc"
diff --git 
a/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py 
b/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py
--- a/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py
+++ b/rpython/jit/backend/x86/test/test_ztranslation_external_exception.py
@@ -1,19 +1,12 @@
 from rpython.jit.backend.llsupport.test.ztranslation_test import 
TranslationRemoveTypePtrTest
 from rpython.translator.translator import TranslationContext
 from rpython.config.translationoption import DEFL_GC
-from rpython.translator.platform import platform as compiler
 
-if compiler.name == 'msvc':
-    _MSVC = True
-else:
-    _MSVC = False
 
 class TestTranslationRemoveTypePtrX86(TranslationRemoveTypePtrTest):
     def _get_TranslationContext(self):
         t = TranslationContext()
         t.config.translation.gc = DEFL_GC   # 'hybrid' or 'minimark'
-        if not _MSVC:
-            t.config.translation.gcrootfinder = 'asmgcc'
         t.config.translation.list_comprehension_operations = True
         t.config.translation.gcremovetypeptr = True
         return t
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
@@ -1156,8 +1156,7 @@
     'CALL_ASSEMBLER/*d/rfin',  # call already compiled assembler
     'CALL_MAY_FORCE/*d/rfin',
     'CALL_LOOPINVARIANT/*d/rfin',
-    'CALL_RELEASE_GIL/*d/fin',
-    # release the GIL and "close the stack" for asmgcc
+    'CALL_RELEASE_GIL/*d/fin',  # release the GIL around the call
     'CALL_PURE/*d/rfin',             # removed before it's passed to the 
backend
     'CHECK_MEMORY_ERROR/1/n',   # after a CALL: NULL => propagate MemoryError
     'CALL_MALLOC_NURSERY/1/r',  # nursery malloc, const number of bytes, zeroed
diff --git a/rpython/memory/gctransform/asmgcroot.py 
b/rpython/memory/gctransform/asmgcroot.py
deleted file mode 100644
--- a/rpython/memory/gctransform/asmgcroot.py
+++ /dev/null
@@ -1,870 +0,0 @@
-from rpython.flowspace.model import (Constant, Variable, Block, Link,
-     copygraph, SpaceOperation, checkgraph)
-from rpython.rlib.debug import ll_assert
-from rpython.rlib.nonconst import NonConstant
-from rpython.rlib import rgil
-from rpython.rtyper.annlowlevel import llhelper
-from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
-from rpython.rtyper.lltypesystem.lloperation import llop
-from rpython.memory.gctransform.framework import (
-     BaseFrameworkGCTransformer, BaseRootWalker)
-from rpython.rtyper.llannotation import SomeAddress
-from rpython.rtyper.rbuiltin import gen_cast
-from rpython.translator.unsimplify import varoftype
-from rpython.translator.tool.cbuild import ExternalCompilationInfo
-import sys
-
-
-#
-#  This transformer avoids the use of a shadow stack in a completely
-#  platform-specific way, by directing genc to insert asm() special
-#  instructions in the C source, which are recognized by GCC.
-#  The .s file produced by GCC is then parsed by trackgcroot.py.
-#
-
-IS_64_BITS = sys.maxint > 2147483647
-
-class AsmGcRootFrameworkGCTransformer(BaseFrameworkGCTransformer):
-    _asmgcc_save_restore_arguments = None
-
-    def push_roots(self, hop, keep_current_args=False):
-        livevars = self.get_livevars_for_roots(hop, keep_current_args)
-        self.num_pushs += len(livevars)
-        return livevars
-
-    def pop_roots(self, hop, livevars):
-        if not livevars:
-            return
-        # mark the values as gc roots
-        for var in livevars:
-            v_adr = gen_cast(hop.llops, llmemory.Address, var)
-            v_newaddr = hop.genop("direct_call", [c_asm_gcroot, v_adr],
-                                  resulttype=llmemory.Address)
-            hop.genop("gc_reload_possibly_moved", [v_newaddr, var])
-
-    def build_root_walker(self):
-        return AsmStackRootWalker(self)
-
-    def mark_call_cannotcollect(self, hop, name):
-        hop.genop("direct_call", [c_asm_nocollect, name])
-
-    def gct_direct_call(self, hop):
-        # just a sanity check: if we find a fnptr with the hint on the
-        # _callable, then we'd also find the hint by looking only at the
-        # graph.  We'll actually change this graph only later, in
-        # start_transforming_graph().
-        fnptr = hop.spaceop.args[0].value
-        try:
-            close_stack = fnptr._obj._callable._gctransformer_hint_close_stack_
-        except AttributeError:
-            pass
-        else:
-            assert fnptr._obj.graph.func is fnptr._obj._callable
-        BaseFrameworkGCTransformer.gct_direct_call(self, hop)
-
-    def start_transforming_graph(self, graph):
-        try:
-            close_stack = graph.func._gctransformer_hint_close_stack_
-        except AttributeError:
-            close_stack = False
-        if close_stack:
-            self._transform_hint_close_stack(graph)
-
-    def _transform_hint_close_stack(self, graph):
-        # We cannot easily pass variable amount of arguments of the call
-        # across the call to the pypy_asm_stackwalk helper.  So we store
-        # them away and restore them.  More precisely, we need to
-        # replace 'graph' with code that saves the arguments, and make
-        # a new graph that starts with restoring the arguments.
-        if self._asmgcc_save_restore_arguments is None:
-            self._asmgcc_save_restore_arguments = {}
-        sradict = self._asmgcc_save_restore_arguments
-        sra = []     # list of pointers to raw-malloced containers for args
-        seen = {}
-        ARGS = [v.concretetype for v in graph.getargs()]
-        for TYPE in ARGS:
-            if isinstance(TYPE, lltype.Ptr):
-                TYPE = llmemory.Address
-            num = seen.get(TYPE, 0)
-            seen[TYPE] = num + 1
-            key = (TYPE, num)
-            if key not in sradict:
-                CONTAINER = lltype.FixedSizeArray(TYPE, 1)
-                p = lltype.malloc(CONTAINER, flavor='raw', zero=True,
-                                  immortal=True)
-                sradict[key] = Constant(p, lltype.Ptr(CONTAINER))
-            sra.append(sradict[key])
-        #
-        # make a copy of the graph that will reload the values
-        graph2 = copygraph(graph)
-        del graph2.func   # otherwise, start_transforming_graph() will
-                          # again transform graph2, and we get an
-                          # infinite loop
-        #
-        # edit the original graph to only store the value of the arguments
-        block = Block(graph.startblock.inputargs)
-        c_item0 = Constant('item0', lltype.Void)
-        assert len(block.inputargs) == len(sra)
-        for v_arg, c_p in zip(block.inputargs, sra):
-            if isinstance(v_arg.concretetype, lltype.Ptr):
-                v_adr = varoftype(llmemory.Address)
-                block.operations.append(
-                    SpaceOperation("cast_ptr_to_adr", [v_arg], v_adr))
-                v_arg = v_adr
-            v_void = varoftype(lltype.Void)
-            block.operations.append(
-                SpaceOperation("bare_setfield", [c_p, c_item0, v_arg], v_void))
-        #
-        # call asm_stackwalk(graph2)
-        RESULT = graph.getreturnvar().concretetype
-        FUNC2 = lltype.FuncType([], RESULT)
-        fnptr2 = lltype.functionptr(FUNC2,
-                                    graph.name + '_reload',
-                                    graph=graph2)
-        c_fnptr2 = Constant(fnptr2, lltype.Ptr(FUNC2))
-        HELPERFUNC = lltype.FuncType([lltype.Ptr(FUNC2),
-                                      ASM_FRAMEDATA_HEAD_PTR], RESULT)
-        v_asm_stackwalk = varoftype(lltype.Ptr(HELPERFUNC), "asm_stackwalk")
-        block.operations.append(
-            SpaceOperation("cast_pointer", [c_asm_stackwalk], v_asm_stackwalk))
-        v_result = varoftype(RESULT)
-        block.operations.append(
-            SpaceOperation("indirect_call", [v_asm_stackwalk, c_fnptr2,
-                                             c_gcrootanchor,
-                                             Constant(None, lltype.Void)],
-                           v_result))
-        block.closeblock(Link([v_result], graph.returnblock))
-        graph.startblock = block
-        #
-        # edit the copy of the graph to reload the values
-        block2 = graph2.startblock
-        block1 = Block([])
-        reloadedvars = []
-        for v, c_p in zip(block2.inputargs, sra):
-            v = v.copy()
-            if isinstance(v.concretetype, lltype.Ptr):
-                w = varoftype(llmemory.Address)
-            else:
-                w = v
-            block1.operations.append(SpaceOperation('getfield',
-                                                    [c_p, c_item0], w))
-            if w is not v:
-                block1.operations.append(SpaceOperation('cast_adr_to_ptr',
-                                                        [w], v))
-            reloadedvars.append(v)
-        block1.closeblock(Link(reloadedvars, block2))
-        graph2.startblock = block1
-        #
-        checkgraph(graph)
-        checkgraph(graph2)
-
-
-class AsmStackRootWalker(BaseRootWalker):
-
-    def __init__(self, gctransformer):
-        BaseRootWalker.__init__(self, gctransformer)
-
-        def _asm_callback():
-            self.walk_stack_from()
-        self._asm_callback = _asm_callback
-        self._shape_decompressor = ShapeDecompressor()
-        self._with_jit = hasattr(gctransformer.translator, '_jit2gc')
-        if self._with_jit:
-            jit2gc = gctransformer.translator._jit2gc
-            self.frame_tid = jit2gc['frame_tid']
-        self.gctransformer = gctransformer
-        #
-        # unless overridden in need_thread_support():
-        self.belongs_to_current_thread = lambda framedata: True
-
-    def need_stacklet_support(self, gctransformer, getfn):
-        from rpython.annotator import model as annmodel
-        from rpython.rlib import _stacklet_asmgcc
-        # stacklet support: BIG HACK for rlib.rstacklet
-        _stacklet_asmgcc._asmstackrootwalker = self     # as a global! argh
-        _stacklet_asmgcc.complete_destrptr(gctransformer)
-        #
-        def gc_detach_callback_pieces():
-            anchor = llmemory.cast_ptr_to_adr(gcrootanchor)
-            result = llmemory.NULL
-            framedata = anchor.address[1]
-            while framedata != anchor:
-                next = framedata.address[1]
-                if self.belongs_to_current_thread(framedata):
-                    # detach it
-                    prev = framedata.address[0]
-                    prev.address[1] = next
-                    next.address[0] = prev
-                    # update the global stack counter
-                    rffi.stackcounter.stacks_counter -= 1
-                    # reattach framedata into the singly-linked list 'result'
-                    framedata.address[0] = rffi.cast(llmemory.Address, -1)
-                    framedata.address[1] = result
-                    result = framedata
-                framedata = next
-            return result
-        #
-        def gc_reattach_callback_pieces(pieces):
-            anchor = llmemory.cast_ptr_to_adr(gcrootanchor)
-            while pieces != llmemory.NULL:
-                framedata = pieces
-                pieces = pieces.address[1]
-                # attach 'framedata' into the normal doubly-linked list
-                following = anchor.address[1]
-                following.address[0] = framedata
-                framedata.address[1] = following
-                anchor.address[1] = framedata
-                framedata.address[0] = anchor
-                # update the global stack counter
-                rffi.stackcounter.stacks_counter += 1
-        #
-        s_addr = SomeAddress()
-        s_None = annmodel.s_None
-        self.gc_detach_callback_pieces_ptr = getfn(gc_detach_callback_pieces,
-                                                   [], s_addr)
-        self.gc_reattach_callback_pieces_ptr=getfn(gc_reattach_callback_pieces,
-                                                   [s_addr], s_None)
-
-    def need_thread_support(self, gctransformer, getfn):
-        # Threads supported "out of the box" by the rest of the code.
-        # The whole code in this function is only there to support
-        # fork()ing in a multithreaded process :-(
-        # For this, we need to handle gc_thread_start and gc_thread_die
-        # to record the mapping {thread_id: stack_start}, and
-        # gc_thread_before_fork and gc_thread_after_fork to get rid of
-        # all ASM_FRAMEDATA structures that do no belong to the current
-        # thread after a fork().
-        from rpython.rlib import rthread
-        from rpython.memory.support import AddressDict
-        from rpython.memory.support import copy_without_null_values
-        from rpython.annotator import model as annmodel
-        gcdata = self.gcdata
-
-        def get_aid():
-            """Return the thread identifier, cast to an (opaque) address."""
-            return llmemory.cast_int_to_adr(rthread.get_ident())
-
-        def thread_start():
-            value = llmemory.cast_int_to_adr(llop.stack_current(lltype.Signed))
-            gcdata.aid2stack.setitem(get_aid(), value)
-        thread_start._always_inline_ = True
-
-        def thread_setup():
-            gcdata.aid2stack = AddressDict()
-            gcdata.dead_threads_count = 0
-            # to also register the main thread's stack
-            thread_start()
-        thread_setup._always_inline_ = True
-
-        def thread_die():
-            gcdata.aid2stack.setitem(get_aid(), llmemory.NULL)
-            # from time to time, rehash the dictionary to remove
-            # old NULL entries
-            gcdata.dead_threads_count += 1
-            if (gcdata.dead_threads_count & 511) == 0:
-                copy = copy_without_null_values(gcdata.aid2stack)
-                gcdata.aid2stack.delete()
-                gcdata.aid2stack = copy
-
-        def belongs_to_current_thread(framedata):
-            # xxx obscure: the answer is Yes if, as a pointer, framedata
-            # lies between the start of the current stack and the top of it.
-            stack_start = gcdata.aid2stack.get(get_aid(), llmemory.NULL)
-            ll_assert(stack_start != llmemory.NULL,
-                      "current thread not found in gcdata.aid2stack!")
-            stack_stop = llmemory.cast_int_to_adr(
-                             llop.stack_current(lltype.Signed))
-            return (stack_start <= framedata <= stack_stop or
-                    stack_start >= framedata >= stack_stop)
-        self.belongs_to_current_thread = belongs_to_current_thread
-
-        def thread_before_fork():
-            # before fork(): collect all ASM_FRAMEDATA structures that do
-            # not belong to the current thread, and move them out of the
-            # way, i.e. out of the main circular doubly linked list.
-            detached_pieces = llmemory.NULL
-            anchor = llmemory.cast_ptr_to_adr(gcrootanchor)
-            initialframedata = anchor.address[1]
-            while initialframedata != anchor:   # while we have not looped back
-                if not belongs_to_current_thread(initialframedata):
-                    # Unlink it
-                    prev = initialframedata.address[0]
-                    next = initialframedata.address[1]
-                    prev.address[1] = next
-                    next.address[0] = prev
-                    # Link it to the singly linked list 'detached_pieces'
-                    initialframedata.address[0] = detached_pieces
-                    detached_pieces = initialframedata
-                    rffi.stackcounter.stacks_counter -= 1
-                # Then proceed to the next piece of stack
-                initialframedata = initialframedata.address[1]
-            return detached_pieces
-
-        def thread_after_fork(result_of_fork, detached_pieces):
-            if result_of_fork == 0:
-                # We are in the child process.  Assumes that only the
-                # current thread survived.  All the detached_pieces
-                # are pointers in other stacks, so have likely been
-                # freed already by the multithreaded library.
-                # Nothing more for us to do.
-                pass
-            else:
-                # We are still in the parent process.  The fork() may
-                # have succeeded or not, but that's irrelevant here.
-                # We need to reattach the detached_pieces now, to the
-                # circular doubly linked list at 'gcrootanchor'.  The
-                # order is not important.
-                anchor = llmemory.cast_ptr_to_adr(gcrootanchor)
-                while detached_pieces != llmemory.NULL:
-                    reattach = detached_pieces
-                    detached_pieces = detached_pieces.address[0]
-                    a_next = anchor.address[1]
-                    reattach.address[0] = anchor
-                    reattach.address[1] = a_next
-                    anchor.address[1] = reattach
-                    a_next.address[0] = reattach
-                    rffi.stackcounter.stacks_counter += 1
-
-        self.thread_setup = thread_setup
-        self.thread_start_ptr = getfn(thread_start, [], annmodel.s_None,
-                                      inline=True)
-        self.thread_die_ptr = getfn(thread_die, [], annmodel.s_None)
-        self.thread_before_fork_ptr = getfn(thread_before_fork, [],
-                                            SomeAddress())
-        self.thread_after_fork_ptr = getfn(thread_after_fork,
-                                           [annmodel.SomeInteger(),
-                                            SomeAddress()],
-                                           annmodel.s_None)
-        #
-        # check that the order of the need_*() is correct for us: if we
-        # need both threads and stacklets, need_thread_support() must be
-        # called first, to initialize self.belongs_to_current_thread.
-        assert not hasattr(self, 'gc_detach_callback_pieces_ptr')
-
-    def postprocess_graph(self, gct, graph, any_inlining):
-        pass
-
-    def walk_stack_roots(self, collect_stack_root, is_minor=False):
-        gcdata = self.gcdata
-        gcdata._gc_collect_stack_root = collect_stack_root
-        gcdata._gc_collect_is_minor = is_minor
-        pypy_asm_stackwalk(llhelper(ASM_CALLBACK_PTR, self._asm_callback),
-                           gcrootanchor)
-
-    def walk_stack_from(self):
-        curframe = lltype.malloc(WALKFRAME, flavor='raw')
-        otherframe = lltype.malloc(WALKFRAME, flavor='raw')
-
-        # Walk over all the pieces of stack.  They are in a circular linked
-        # list of structures of 7 words, the 2 first words being prev/next.
-        # The anchor of this linked list is:
-        anchor = llmemory.cast_ptr_to_adr(gcrootanchor)
-        initialframedata = anchor.address[1]
-        stackscount = 0
-        while initialframedata != anchor:     # while we have not looped back
-            self.walk_frames(curframe, otherframe, initialframedata)
-            # Then proceed to the next piece of stack
-            initialframedata = initialframedata.address[1]
-            stackscount += 1
-        #
-        # for the JIT: rpy_fastgil may contain an extra framedata
-        rpy_fastgil = rgil.gil_fetch_fastgil().signed[0]
-        if rpy_fastgil != 1:
-            ll_assert(rpy_fastgil != 0, "walk_stack_from doesn't have the GIL")
-            initialframedata = rffi.cast(llmemory.Address, rpy_fastgil)
-            #
-            # very rare issue: initialframedata.address[0] is uninitialized
-            # in this case, but "retaddr = callee.frame_address.address[0]"
-            # reads it.  If it happens to be exactly a valid return address
-            # inside the C code, then bad things occur.
-            initialframedata.address[0] = llmemory.NULL
-            #
-            self.walk_frames(curframe, otherframe, initialframedata)
-            stackscount += 1
-        #
-        expected = rffi.stackcounter.stacks_counter
-        if NonConstant(0):
-            rffi.stackcounter.stacks_counter += 42    # hack to force it
-        ll_assert(not (stackscount < expected), "non-closed stacks around")
-        ll_assert(not (stackscount > expected), "stacks counter corruption?")
-        lltype.free(otherframe, flavor='raw')
-        lltype.free(curframe, flavor='raw')
-
-    def walk_frames(self, curframe, otherframe, initialframedata):
-        self.fill_initial_frame(curframe, initialframedata)
-        # Loop over all the frames in the stack
-        while self.walk_to_parent_frame(curframe, otherframe):
-            swap = curframe
-            curframe = otherframe    # caller becomes callee
-            otherframe = swap
-
-    def fill_initial_frame(self, curframe, initialframedata):
-        # Read the information provided by initialframedata
-        initialframedata += 2*sizeofaddr #skip the prev/next words at the start
-        reg = 0
-        while reg < CALLEE_SAVED_REGS:
-            # NB. 'initialframedata' stores the actual values of the
-            # registers %ebx etc., and if these values are modified
-            # they are reloaded by pypy_asm_stackwalk().  By contrast,
-            # 'regs_stored_at' merely points to the actual values
-            # from the 'initialframedata'.
-            curframe.regs_stored_at[reg] = initialframedata + reg*sizeofaddr
-            reg += 1
-        curframe.frame_address = initialframedata.address[CALLEE_SAVED_REGS]
-
-    def walk_to_parent_frame(self, callee, caller):
-        """Starting from 'callee', walk the next older frame on the stack
-        and fill 'caller' accordingly.  Also invokes the collect_stack_root()
-        callback from the GC code for each GC root found in 'caller'.
-        """
-        #
-        # The gcmap table is a list of entries, two machine words each:
-        #     void *SafePointAddress;
-        #     int Shape;
-        #
-        # A "safe point" is the return address of a call.
-        # The "shape" of a safe point is a list of integers
-        # that represent "locations".  A "location" can be
-        # either in the stack or in a register.  See
-        # getlocation() for the decoding of this integer.
-        # The locations stored in a "shape" are as follows:
-        #
-        #   * The "location" of the return address.  This is just
-        #     after the end of the frame of 'callee'; it is the
-        #     first word of the frame of 'caller' (see picture
-        #     below).
-        #
-        #   * Four "locations" that specify where the function saves
-        #     each of the four callee-saved registers (%ebx, %esi,
-        #     %edi, %ebp).
-        #
-        #   * The number of live GC roots around the call.
-        #
-        #   * For each GC root, an integer that specify where the
-        #     GC pointer is stored.  This is a "location" too.
-        #
-        # XXX the details are completely specific to X86!!!
-        # a picture of the stack may help:
-        #                                           ^ ^ ^
-        #     |     ...      |                 to older frames
-        #     +--------------+
-        #     |   ret addr   |  <------ caller_frame (addr of retaddr)
-        #     |     ...      |
-        #     | caller frame |
-        #     |     ...      |
-        #     +--------------+
-        #     |   ret addr   |  <------ callee_frame (addr of retaddr)
-        #     |     ...      |
-        #     | callee frame |
-        #     |     ...      |                 lower addresses
-        #     +--------------+                      v v v
-        #
-
-        retaddr = callee.frame_address.address[0]
-        #
-        # try to locate the caller function based on retaddr.
-        # set up self._shape_decompressor.
-        #
-        ebp_in_caller = callee.regs_stored_at[INDEX_OF_EBP].address[0]
-        self.locate_caller_based_on_retaddr(retaddr, ebp_in_caller)
-        #
-        # found!  Enumerate the GC roots in the caller frame
-        #
-        collect_stack_root = self.gcdata._gc_collect_stack_root
-        gc = self.gc
-        while True:
-            location = self._shape_decompressor.next()
-            if location == 0:
-                break
-            addr = self.getlocation(callee, ebp_in_caller, location)
-            if gc.points_to_valid_gc_object(addr):
-                collect_stack_root(gc, addr)
-        #
-        # small hack: the JIT reserves THREADLOCAL_OFS's last bit for
-        # us.  We use it to store an "already traced past this frame"
-        # flag.
-        if self._with_jit and self.gcdata._gc_collect_is_minor:
-            if self.mark_jit_frame_can_stop(callee):
-                return False
-        #
-        # track where the caller_frame saved the registers from its own
-        # caller
-        #
-        reg = CALLEE_SAVED_REGS - 1
-        while reg >= 0:
-            location = self._shape_decompressor.next()
-            addr = self.getlocation(callee, ebp_in_caller, location)
-            caller.regs_stored_at[reg] = addr
-            reg -= 1
-
-        location = self._shape_decompressor.next()
-        caller.frame_address = self.getlocation(callee, ebp_in_caller,
-                                                location)
-        # we get a NULL marker to mean "I'm the frame
-        # of the entry point, stop walking"
-        return caller.frame_address != llmemory.NULL
-
-    def locate_caller_based_on_retaddr(self, retaddr, ebp_in_caller):
-        gcmapstart = llop.gc_asmgcroot_static(llmemory.Address, 0)
-        gcmapend   = llop.gc_asmgcroot_static(llmemory.Address, 1)
-        item = search_in_gcmap(gcmapstart, gcmapend, retaddr)
-        if item:
-            self._shape_decompressor.setpos(item.signed[1])
-            return
-
-        if not self._shape_decompressor.sorted:
-            # the item may have been not found because the main array was
-            # not sorted.  Sort it and try again.
-            win32_follow_gcmap_jmp(gcmapstart, gcmapend)
-            sort_gcmap(gcmapstart, gcmapend)
-            self._shape_decompressor.sorted = True
-            item = search_in_gcmap(gcmapstart, gcmapend, retaddr)
-            if item:
-                self._shape_decompressor.setpos(item.signed[1])
-                return
-
-        if self._with_jit:
-            # item not found.  We assume that it's a JIT-generated
-            # location -- but we check for consistency that ebp points
-            # to a JITFRAME object.
-            from rpython.jit.backend.llsupport.jitframe import STACK_DEPTH_OFS
-
-            tid = self.gc.get_possibly_forwarded_type_id(ebp_in_caller)
-            if (rffi.cast(lltype.Signed, tid) ==
-                    rffi.cast(lltype.Signed, self.frame_tid)):
-                # fish the depth
-                extra_stack_depth = (ebp_in_caller + STACK_DEPTH_OFS).signed[0]
-                ll_assert((extra_stack_depth & (rffi.sizeof(lltype.Signed) - 
1))
-                           == 0, "asmgcc: misaligned extra_stack_depth")
-                extra_stack_depth //= rffi.sizeof(lltype.Signed)
-                self._shape_decompressor.setjitframe(extra_stack_depth)
-                return
-        llop.debug_fatalerror(lltype.Void, "cannot find gc roots!")
-
-    def getlocation(self, callee, ebp_in_caller, location):
-        """Get the location in the 'caller' frame of a variable, based
-        on the integer 'location' that describes it.  All locations are
-        computed based on information saved by the 'callee'.
-        """
-        ll_assert(location >= 0, "negative location")
-        kind = location & LOC_MASK
-        offset = location & ~ LOC_MASK
-        if IS_64_BITS:
-            offset <<= 1
-        if kind == LOC_REG:   # register
-            if location == LOC_NOWHERE:
-                return llmemory.NULL
-            reg = (location >> 2) - 1
-            ll_assert(reg < CALLEE_SAVED_REGS, "bad register location")
-            return callee.regs_stored_at[reg]
-        elif kind == LOC_ESP_PLUS:    # in the caller stack frame at N(%esp)
-            esp_in_caller = callee.frame_address + sizeofaddr
-            return esp_in_caller + offset
-        elif kind == LOC_EBP_PLUS:    # in the caller stack frame at N(%ebp)
-            return ebp_in_caller + offset
-        else:  # kind == LOC_EBP_MINUS:   at -N(%ebp)
-            return ebp_in_caller - offset
-
-    def mark_jit_frame_can_stop(self, callee):
-        location = self._shape_decompressor.get_threadlocal_loc()
-        if location == LOC_NOWHERE:
-            return False
-        addr = self.getlocation(callee, llmemory.NULL, location)
-        #
-        x = addr.signed[0]
-        if x & 1:
-            return True            # this JIT stack frame is already marked!
-        else:
-            addr.signed[0] = x | 1    # otherwise, mark it but don't stop
-            return False
-
-
-LOC_REG       = 0
-LOC_ESP_PLUS  = 1
-LOC_EBP_PLUS  = 2
-LOC_EBP_MINUS = 3
-LOC_MASK      = 0x03
-LOC_NOWHERE   = LOC_REG | 0
-
-# ____________________________________________________________
-
-sizeofaddr = llmemory.sizeof(llmemory.Address)
-arrayitemsize = 2 * sizeofaddr
-
-
-def binary_search(start, end, addr1):
-    """Search for an element in a sorted array.
-
-    The interval from the start address (included) to the end address
-    (excluded) is assumed to be a sorted arrays of pairs (addr1, addr2).
-    This searches for the item with a given addr1 and returns its
-    address.  If not found exactly, it tries to return the address
-    of the item left of addr1 (i.e. such that result.address[0] < addr1).
-    """
-    count = (end - start) // arrayitemsize
-    while count > 1:
-        middleindex = count // 2
-        middle = start + middleindex * arrayitemsize
-        if addr1 < middle.address[0]:
-            count = middleindex
-        else:
-            start = middle
-            count -= middleindex
-    return start
-
-def search_in_gcmap(gcmapstart, gcmapend, retaddr):
-    item = binary_search(gcmapstart, gcmapend, retaddr)
-    if item.address[0] == retaddr:
-        return item     # found
-    # 'retaddr' not exactly found.  Check that 'item' is the start of a
-    # compressed range that includes 'retaddr'.
-    if retaddr > item.address[0] and item.signed[1] < 0:
-        return item     # ok
-    else:
-        return llmemory.NULL    # failed
-
-def search_in_gcmap2(gcmapstart, gcmapend, retaddr):
-    # same as 'search_in_gcmap', but without range checking support
-    # (item.signed[1] is an address in this case, not a signed at all!)
-    item = binary_search(gcmapstart, gcmapend, retaddr)
-    if item.address[0] == retaddr:
-        return item.address[1]     # found
-    else:
-        return llmemory.NULL    # failed
-
-def sort_gcmap(gcmapstart, gcmapend):
-    count = (gcmapend - gcmapstart) // arrayitemsize
-    qsort(gcmapstart,
-          rffi.cast(rffi.SIZE_T, count),
-          rffi.cast(rffi.SIZE_T, arrayitemsize),
-          c_compare_gcmap_entries)
-
-def replace_dead_entries_with_nulls(start, end):
-    # replace the dead entries (null value) with a null key.
-    count = (end - start) // arrayitemsize - 1
-    while count >= 0:
-        item = start + count * arrayitemsize
-        if item.address[1] == llmemory.NULL:
-            item.address[0] = llmemory.NULL
-        count -= 1
-
-if sys.platform == 'win32':
-    def win32_follow_gcmap_jmp(start, end):
-        # The initial gcmap table contains addresses to a JMP
-        # instruction that jumps indirectly to the real code.
-        # Replace them with the target addresses.
-        assert rffi.SIGNEDP is rffi.LONGP, "win64 support missing"
-        while start < end:
-            code = rffi.cast(rffi.CCHARP, start.address[0])[0]
-            if code == '\xe9': # jmp
-                rel32 = rffi.cast(rffi.SIGNEDP, start.address[0]+1)[0]
-                target = start.address[0] + (rel32 + 5)
-                start.address[0] = target
-            start += arrayitemsize
-else:
-    def win32_follow_gcmap_jmp(start, end):
-        pass
-
-# ____________________________________________________________
-
-class ShapeDecompressor:
-    _alloc_flavor_ = "raw"
-
-    sorted = False
-
-    def setpos(self, pos):
-        if pos < 0:
-            pos = ~ pos     # can ignore this "range" marker here
-        gccallshapes = llop.gc_asmgcroot_static(llmemory.Address, 2)
-        self.addr = gccallshapes + pos
-        self.jit_index = -1
-
-    def setjitframe(self, extra_stack_depth):
-        self.jit_index = 0
-        self.extra_stack_depth = extra_stack_depth
-
-    def next(self):
-        index = self.jit_index
-        if index < 0:
-            # case "outside the jit"
-            addr = self.addr
-            value = 0
-            while True:
-                b = ord(addr.char[0])
-                addr += 1
-                value += b
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to