Author: Ronan Lamy <[email protected]>
Branch: py3k-update
Changeset: r83994:4363df660a6b
Date: 2016-04-27 18:52 +0100
http://bitbucket.org/pypy/pypy/changeset/4363df660a6b/

Log:    hg merge 73a49ec9edc3

diff --git a/lib_pypy/_collections.py b/lib_pypy/_collections.py
--- a/lib_pypy/_collections.py
+++ b/lib_pypy/_collections.py
@@ -320,8 +320,7 @@
     def __reduce_ex__(self, proto):
         return type(self), (list(self), self.maxlen)
 
-    def __hash__(self):
-        raise TypeError("deque objects are unhashable")
+    __hash__ = None
 
     def __copy__(self):
         return self.__class__(self, self.maxlen)
diff --git a/lib_pypy/_pypy_wait.py b/lib_pypy/_pypy_wait.py
--- a/lib_pypy/_pypy_wait.py
+++ b/lib_pypy/_pypy_wait.py
@@ -1,51 +1,22 @@
-from resource import _struct_rusage, struct_rusage
-from ctypes import CDLL, c_int, POINTER, byref
-from ctypes.util import find_library
+from resource import ffi, lib, _make_struct_rusage
 
 __all__ = ["wait3", "wait4"]
 
-libc = CDLL(find_library("c"))
-c_wait3 = libc.wait3
-c_wait3.argtypes = [POINTER(c_int), c_int, POINTER(_struct_rusage)]
-c_wait3.restype = c_int
-
-c_wait4 = libc.wait4
-c_wait4.argtypes = [c_int, POINTER(c_int), c_int, POINTER(_struct_rusage)]
-c_wait4.restype = c_int
-
-def create_struct_rusage(c_struct):
-    return struct_rusage((
-        float(c_struct.ru_utime),
-        float(c_struct.ru_stime),
-        c_struct.ru_maxrss,
-        c_struct.ru_ixrss,
-        c_struct.ru_idrss,
-        c_struct.ru_isrss,
-        c_struct.ru_minflt,
-        c_struct.ru_majflt,
-        c_struct.ru_nswap,
-        c_struct.ru_inblock,
-        c_struct.ru_oublock,
-        c_struct.ru_msgsnd,
-        c_struct.ru_msgrcv,
-        c_struct.ru_nsignals,
-        c_struct.ru_nvcsw,
-        c_struct.ru_nivcsw))
 
 def wait3(options):
-    status = c_int()
-    _rusage = _struct_rusage()
-    pid = c_wait3(byref(status), c_int(options), byref(_rusage))
+    status = ffi.new("int *")
+    ru = ffi.new("struct rusage *")
+    pid = lib.wait3(status, options, ru)
 
-    rusage = create_struct_rusage(_rusage)
+    rusage = _make_struct_rusage(ru)
 
-    return pid, status.value, rusage
+    return pid, status[0], rusage
 
 def wait4(pid, options):
-    status = c_int()
-    _rusage = _struct_rusage()
-    pid = c_wait4(c_int(pid), byref(status), c_int(options), byref(_rusage))
+    status = ffi.new("int *")
+    ru = ffi.new("struct rusage *")
+    pid = lib.wait4(pid, status, options, ru)
 
-    rusage = create_struct_rusage(_rusage)
+    rusage = _make_struct_rusage(ru)
 
-    return pid, status.value, rusage
+    return pid, status[0], rusage
diff --git a/lib_pypy/_resource_build.py b/lib_pypy/_resource_build.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_resource_build.py
@@ -0,0 +1,118 @@
+from cffi import FFI
+
+ffi = FFI()
+
+# Note: we don't directly expose 'struct timeval' or 'struct rlimit'
+
+
+rlimit_consts = '''
+RLIMIT_CPU
+RLIMIT_FSIZE
+RLIMIT_DATA
+RLIMIT_STACK
+RLIMIT_CORE
+RLIMIT_NOFILE
+RLIMIT_OFILE
+RLIMIT_VMEM
+RLIMIT_AS
+RLIMIT_RSS
+RLIMIT_NPROC
+RLIMIT_MEMLOCK
+RLIMIT_SBSIZE
+RLIM_INFINITY
+RUSAGE_SELF
+RUSAGE_CHILDREN
+RUSAGE_BOTH
+'''.split()
+
+rlimit_consts = ['#ifdef %s\n\t{"%s", %s},\n#endif\n' % (s, s, s)
+                 for s in rlimit_consts]
+
+
+ffi.set_source("_resource_cffi", """
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+
+static const struct my_rlimit_def {
+    const char *name;
+    long long value;
+} my_rlimit_consts[] = {
+$RLIMIT_CONSTS
+    { NULL, 0 }
+};
+
+#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
+
+static double my_utime(struct rusage *input)
+{
+    return doubletime(input->ru_utime);
+}
+
+static double my_stime(struct rusage *input)
+{
+    return doubletime(input->ru_stime);
+}
+
+static int my_getrlimit(int resource, long long result[2])
+{
+    struct rlimit rl;
+    if (getrlimit(resource, &rl) == -1)
+        return -1;
+    result[0] = rl.rlim_cur;
+    result[1] = rl.rlim_max;
+    return 0;
+}
+
+static int my_setrlimit(int resource, long long cur, long long max)
+{
+    struct rlimit rl;
+    rl.rlim_cur = cur & RLIM_INFINITY;
+    rl.rlim_max = max & RLIM_INFINITY;
+    return setrlimit(resource, &rl);
+}
+
+""".replace('$RLIMIT_CONSTS', ''.join(rlimit_consts)))
+
+
+ffi.cdef("""
+
+#define RLIM_NLIMITS ...
+
+const struct my_rlimit_def {
+    const char *name;
+    long long value;
+} my_rlimit_consts[];
+
+struct rusage {
+    long ru_maxrss;
+    long ru_ixrss;
+    long ru_idrss;
+    long ru_isrss;
+    long ru_minflt;
+    long ru_majflt;
+    long ru_nswap;
+    long ru_inblock;
+    long ru_oublock;
+    long ru_msgsnd;
+    long ru_msgrcv;
+    long ru_nsignals;
+    long ru_nvcsw;
+    long ru_nivcsw;
+    ...;
+};
+
+static double my_utime(struct rusage *);
+static double my_stime(struct rusage *);
+void getrusage(int who, struct rusage *result);
+int my_getrlimit(int resource, long long result[2]);
+int my_setrlimit(int resource, long long cur, long long max);
+
+int wait3(int *status, int options, struct rusage *rusage);
+int wait4(int pid, int *status, int options, struct rusage *rusage);
+""")
+
+
+if __name__ == "__main__":
+    ffi.compile()
diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py
--- a/lib_pypy/cffi/cparser.py
+++ b/lib_pypy/cffi/cparser.py
@@ -29,7 +29,8 @@
 _r_stdcall1 = re.compile(r"\b(__stdcall|WINAPI)\b")
 _r_stdcall2 = re.compile(r"[(]\s*(__stdcall|WINAPI)\b")
 _r_cdecl = re.compile(r"\b__cdecl\b")
-_r_extern_python = re.compile(r'\bextern\s*"Python"\s*.')
+_r_extern_python = re.compile(r'\bextern\s*"'
+                              r'(Python|Python\s*\+\s*C|C\s*\+\s*Python)"\s*.')
 _r_star_const_space = re.compile(       # matches "* const "
     r"[*]\s*((const|volatile|restrict)\b\s*)+")
 
@@ -88,6 +89,12 @@
     #     void __cffi_extern_python_start;
     #     int foo(int);
     #     void __cffi_extern_python_stop;
+    #
+    # input: `extern "Python+C" int foo(int);`
+    # output:
+    #     void __cffi_extern_python_plus_c_start;
+    #     int foo(int);
+    #     void __cffi_extern_python_stop;
     parts = []
     while True:
         match = _r_extern_python.search(csource)
@@ -98,7 +105,10 @@
         #print ''.join(parts)+csource
         #print '=>'
         parts.append(csource[:match.start()])
-        parts.append('void __cffi_extern_python_start; ')
+        if 'C' in match.group(1):
+            parts.append('void __cffi_extern_python_plus_c_start; ')
+        else:
+            parts.append('void __cffi_extern_python_start; ')
         if csource[endpos] == '{':
             # grouping variant
             closing = csource.find('}', endpos)
@@ -302,7 +312,7 @@
                 break
         #
         try:
-            self._inside_extern_python = False
+            self._inside_extern_python = '__cffi_extern_python_stop'
             for decl in iterator:
                 if isinstance(decl, pycparser.c_ast.Decl):
                     self._parse_decl(decl)
@@ -376,8 +386,10 @@
         tp = self._get_type_pointer(tp, quals)
         if self._options.get('dllexport'):
             tag = 'dllexport_python '
-        elif self._inside_extern_python:
+        elif self._inside_extern_python == '__cffi_extern_python_start':
             tag = 'extern_python '
+        elif self._inside_extern_python == '__cffi_extern_python_plus_c_start':
+            tag = 'extern_python_plus_c '
         else:
             tag = 'function '
         self._declare(tag + decl.name, tp)
@@ -421,11 +433,9 @@
                     # hack: `extern "Python"` in the C source is replaced
                     # with "void __cffi_extern_python_start;" and
                     # "void __cffi_extern_python_stop;"
-                    self._inside_extern_python = not self._inside_extern_python
-                    assert self._inside_extern_python == (
-                        decl.name == '__cffi_extern_python_start')
+                    self._inside_extern_python = decl.name
                 else:
-                    if self._inside_extern_python:
+                    if self._inside_extern_python 
!='__cffi_extern_python_stop':
                         raise api.CDefError(
                             "cannot declare constants or "
                             "variables with 'extern \"Python\"'")
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
--- a/lib_pypy/cffi/recompiler.py
+++ b/lib_pypy/cffi/recompiler.py
@@ -1145,11 +1145,11 @@
     def _generate_cpy_extern_python_collecttype(self, tp, name):
         assert isinstance(tp, model.FunctionPtrType)
         self._do_collect_type(tp)
+    _generate_cpy_dllexport_python_collecttype = \
+      _generate_cpy_extern_python_plus_c_collecttype = \
+      _generate_cpy_extern_python_collecttype
 
-    def _generate_cpy_dllexport_python_collecttype(self, tp, name):
-        self._generate_cpy_extern_python_collecttype(tp, name)
-
-    def _generate_cpy_extern_python_decl(self, tp, name, dllexport=False):
+    def _extern_python_decl(self, tp, name, tag_and_space):
         prnt = self._prnt
         if isinstance(tp.result, model.VoidType):
             size_of_result = '0'
@@ -1184,11 +1184,7 @@
             size_of_a = 'sizeof(%s) > %d ? sizeof(%s) : %d' % (
                 tp.result.get_c_name(''), size_of_a,
                 tp.result.get_c_name(''), size_of_a)
-        if dllexport:
-            tag = 'CFFI_DLLEXPORT'
-        else:
-            tag = 'static'
-        prnt('%s %s' % (tag, tp.result.get_c_name(name_and_arguments)))
+        prnt('%s%s' % (tag_and_space, 
tp.result.get_c_name(name_and_arguments)))
         prnt('{')
         prnt('  char a[%s];' % size_of_a)
         prnt('  char *p = a;')
@@ -1206,8 +1202,14 @@
         prnt()
         self._num_externpy += 1
 
+    def _generate_cpy_extern_python_decl(self, tp, name):
+        self._extern_python_decl(tp, name, 'static ')
+
     def _generate_cpy_dllexport_python_decl(self, tp, name):
-        self._generate_cpy_extern_python_decl(tp, name, dllexport=True)
+        self._extern_python_decl(tp, name, 'CFFI_DLLEXPORT ')
+
+    def _generate_cpy_extern_python_plus_c_decl(self, tp, name):
+        self._extern_python_decl(tp, name, '')
 
     def _generate_cpy_extern_python_ctx(self, tp, name):
         if self.target_is_python:
@@ -1220,8 +1222,9 @@
         self._lsts["global"].append(
             GlobalExpr(name, '&_cffi_externpy__%s' % name, type_op, name))
 
-    def _generate_cpy_dllexport_python_ctx(self, tp, name):
-        self._generate_cpy_extern_python_ctx(tp, name)
+    _generate_cpy_dllexport_python_ctx = \
+      _generate_cpy_extern_python_plus_c_ctx = \
+      _generate_cpy_extern_python_ctx
 
     def _string_literal(self, s):
         def _char_repr(c):
diff --git a/lib_pypy/ctypes_config_cache/.empty 
b/lib_pypy/ctypes_config_cache/.empty
new file mode 100644
--- /dev/null
+++ b/lib_pypy/ctypes_config_cache/.empty
@@ -0,0 +1,1 @@
+dummy file to allow old buildbot configuration to run
diff --git a/lib_pypy/ctypes_config_cache/__init__.py 
b/lib_pypy/ctypes_config_cache/__init__.py
deleted file mode 100644
diff --git a/lib_pypy/ctypes_config_cache/dumpcache.py 
b/lib_pypy/ctypes_config_cache/dumpcache.py
deleted file mode 100644
--- a/lib_pypy/ctypes_config_cache/dumpcache.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import sys, os
-from ctypes_configure import dumpcache
-
-def dumpcache2(basename, config):
-    size = 32 if sys.maxint <= 2**32 else 64
-    filename = '_%s_%s_.py' % (basename, size)
-    dumpcache.dumpcache(__file__, filename, config)
-    #
-    filename = os.path.join(os.path.dirname(__file__),
-                            '_%s_cache.py' % (basename,))
-    g = open(filename, 'w')
-    print >> g, '''\
-import sys
-_size = 32 if sys.maxsize <= 2**32 else 64
-# XXX relative import, should be removed together with
-# XXX the relative imports done e.g. by lib_pypy/pypy_test/test_hashlib
-_mod = __import__("_%s_%%s_" %% (_size,),
-                  globals(), locals(), ["*"], level=1)
-globals().update(_mod.__dict__)\
-''' % (basename,)
-    g.close()
diff --git a/lib_pypy/ctypes_config_cache/locale.ctc.py 
b/lib_pypy/ctypes_config_cache/locale.ctc.py
deleted file mode 100644
--- a/lib_pypy/ctypes_config_cache/locale.ctc.py
+++ /dev/null
@@ -1,73 +0,0 @@
-"""
-'ctypes_configure' source for _locale.py.
-Run this to rebuild _locale_cache.py.
-"""
-
-from ctypes_configure.configure import (configure, ExternalCompilationInfo,
-    ConstantInteger, DefinedConstantInteger, SimpleType, check_eci)
-import dumpcache
-
-# ____________________________________________________________
-
-_CONSTANTS = [
-    'LC_CTYPE',
-    'LC_TIME',
-    'LC_COLLATE',
-    'LC_MONETARY',
-    'LC_MESSAGES',
-    'LC_NUMERIC',
-    'LC_ALL',
-    'CHAR_MAX',
-]
-
-class LocaleConfigure:
-    _compilation_info_ = ExternalCompilationInfo(includes=['limits.h',
-                                                           'locale.h'])
-for key in _CONSTANTS:
-    setattr(LocaleConfigure, key, DefinedConstantInteger(key))
-
-config = configure(LocaleConfigure, noerr=True)
-for key, value in config.items():
-    if value is None:
-        del config[key]
-        _CONSTANTS.remove(key)
-
-# ____________________________________________________________
-
-eci = ExternalCompilationInfo(includes=['locale.h', 'langinfo.h'])
-HAS_LANGINFO = check_eci(eci)
-
-if HAS_LANGINFO:
-    # list of all possible names
-    langinfo_names = [
-        "RADIXCHAR", "THOUSEP", "CRNCYSTR",
-        "D_T_FMT", "D_FMT", "T_FMT", "AM_STR", "PM_STR",
-        "CODESET", "T_FMT_AMPM", "ERA", "ERA_D_FMT", "ERA_D_T_FMT",
-        "ERA_T_FMT", "ALT_DIGITS", "YESEXPR", "NOEXPR", "_DATE_FMT",
-        ]
-    for i in range(1, 8):
-        langinfo_names.append("DAY_%d" % i)
-        langinfo_names.append("ABDAY_%d" % i)
-    for i in range(1, 13):
-        langinfo_names.append("MON_%d" % i)
-        langinfo_names.append("ABMON_%d" % i)
-    
-    class LanginfoConfigure:
-        _compilation_info_ = eci
-        nl_item = SimpleType('nl_item')
-    for key in langinfo_names:
-        setattr(LanginfoConfigure, key, DefinedConstantInteger(key))
-
-    langinfo_config = configure(LanginfoConfigure)
-    for key, value in langinfo_config.items():
-        if value is None:
-            del langinfo_config[key]
-            langinfo_names.remove(key)
-    config.update(langinfo_config)
-    _CONSTANTS += langinfo_names
-
-# ____________________________________________________________
-
-config['ALL_CONSTANTS'] = tuple(_CONSTANTS)
-config['HAS_LANGINFO'] = HAS_LANGINFO
-dumpcache.dumpcache2('locale', config)
diff --git a/lib_pypy/ctypes_config_cache/rebuild.py 
b/lib_pypy/ctypes_config_cache/rebuild.py
deleted file mode 100755
--- a/lib_pypy/ctypes_config_cache/rebuild.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#! /usr/bin/env python
-# Run this script to rebuild all caches from the *.ctc.py files.
-
-import os, sys
-
-sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), 
'..', '..')))
-
-import py
-
-_dirpath = os.path.dirname(__file__) or os.curdir
-
-from rpython.tool.ansi_print import AnsiLogger
-log = AnsiLogger("ctypes_config_cache")
-
-
-def rebuild_one(name):
-    filename = os.path.join(_dirpath, name)
-    d = {'__file__': filename}
-    path = sys.path[:]
-    try:
-        sys.path.insert(0, _dirpath)
-        execfile(filename, d)
-    finally:
-        sys.path[:] = path
-
-def try_rebuild():
-    size = 32 if sys.maxint <= 2**32 else 64
-    # remove the files '_*_size_.py'
-    left = {}
-    for p in os.listdir(_dirpath):
-        if p.startswith('_') and (p.endswith('_%s_.py' % size) or
-                                  p.endswith('_%s_.pyc' % size)):
-            os.unlink(os.path.join(_dirpath, p))
-        elif p.startswith('_') and (p.endswith('_.py') or
-                                    p.endswith('_.pyc')):
-            for i in range(2, len(p)-4):
-                left[p[:i]] = True
-    # remove the files '_*_cache.py' if there is no '_*_*_.py' left around
-    for p in os.listdir(_dirpath):
-        if p.startswith('_') and (p.endswith('_cache.py') or
-                                  p.endswith('_cache.pyc')):
-            if p[:-9] not in left:
-                os.unlink(os.path.join(_dirpath, p))
-    #
-    for p in os.listdir(_dirpath):
-        if p.endswith('.ctc.py'):
-            try:
-                rebuild_one(p)
-            except Exception, e:
-                log.ERROR("Running %s:\n  %s: %s" % (
-                    os.path.join(_dirpath, p),
-                    e.__class__.__name__, e))
-
-
-if __name__ == '__main__':
-    try_rebuild()
diff --git a/lib_pypy/ctypes_config_cache/resource.ctc.py 
b/lib_pypy/ctypes_config_cache/resource.ctc.py
deleted file mode 100644
--- a/lib_pypy/ctypes_config_cache/resource.ctc.py
+++ /dev/null
@@ -1,62 +0,0 @@
-"""
-'ctypes_configure' source for resource.py.
-Run this to rebuild _resource_cache.py.
-"""
-
-
-from ctypes import sizeof
-import dumpcache
-from ctypes_configure.configure import (configure,
-    ExternalCompilationInfo, ConstantInteger, DefinedConstantInteger,
-    SimpleType)
-
-
-_CONSTANTS = (
-    'RLIM_INFINITY',
-    'RLIM_NLIMITS',
-)
-_OPTIONAL_CONSTANTS = (
-    'RLIMIT_CPU',
-    'RLIMIT_FSIZE',
-    'RLIMIT_DATA',
-    'RLIMIT_STACK',
-    'RLIMIT_CORE',
-    'RLIMIT_RSS',
-    'RLIMIT_NPROC',
-    'RLIMIT_NOFILE',
-    'RLIMIT_OFILE',
-    'RLIMIT_MEMLOCK',
-    'RLIMIT_AS',
-    'RLIMIT_LOCKS',
-    'RLIMIT_SIGPENDING',
-    'RLIMIT_MSGQUEUE',
-    'RLIMIT_NICE',
-    'RLIMIT_RTPRIO',
-    'RLIMIT_VMEM',
-
-    'RUSAGE_BOTH',
-    'RUSAGE_SELF',
-    'RUSAGE_CHILDREN',
-)
-
-# Setup our configure
-class ResourceConfigure:
-    _compilation_info_ = ExternalCompilationInfo(includes=['sys/resource.h'])
-    rlim_t = SimpleType('rlim_t')
-for key in _CONSTANTS:
-    setattr(ResourceConfigure, key, ConstantInteger(key))
-for key in _OPTIONAL_CONSTANTS:
-    setattr(ResourceConfigure, key, DefinedConstantInteger(key))
-
-# Configure constants and types
-config = configure(ResourceConfigure)
-config['rlim_t_max'] = (1<<(sizeof(config['rlim_t']) * 8)) - 1
-optional_constants = []
-for key in _OPTIONAL_CONSTANTS:
-    if config[key] is not None:
-        optional_constants.append(key)
-    else:
-        del config[key]
-
-config['ALL_CONSTANTS'] = _CONSTANTS + tuple(optional_constants)
-dumpcache.dumpcache2('resource', config)
diff --git a/lib_pypy/pwd.py b/lib_pypy/pwd.py
--- a/lib_pypy/pwd.py
+++ b/lib_pypy/pwd.py
@@ -1,4 +1,4 @@
-# ctypes implementation: Victor Stinner, 2008-05-08
+# indirectly based on ctypes implementation: Victor Stinner, 2008-05-08
 """
 This module provides access to the Unix password database.
 It is available on all Unix versions.
diff --git a/lib_pypy/resource.py b/lib_pypy/resource.py
--- a/lib_pypy/resource.py
+++ b/lib_pypy/resource.py
@@ -1,15 +1,8 @@
-import sys
-if sys.platform == 'win32':
-    raise ImportError('resource module not available for win32')
+"""http://docs.python.org/library/resource""";
 
-# load the platform-specific cache made by running resource.ctc.py
-from ctypes_config_cache._resource_cache import *
-
-from ctypes_support import standard_c_lib as libc
-from ctypes_support import get_errno
-from ctypes import Structure, c_int, c_long, byref, POINTER
+from _resource_cffi import ffi, lib
 from errno import EINVAL, EPERM
-import _structseq
+import _structseq, os
 
 try: from __pypy__ import builtinify
 except ImportError: builtinify = lambda f: f
@@ -18,104 +11,37 @@
 class error(Exception):
     pass
 
+class struct_rusage(metaclass=_structseq.structseqtype):
+    """struct_rusage: Result from getrusage.
 
-# Read required libc functions
-_getrusage = libc.getrusage
-_getrlimit = libc.getrlimit
-_setrlimit = libc.setrlimit
-try:
-    _getpagesize = libc.getpagesize
-    _getpagesize.argtypes = ()
-    _getpagesize.restype = c_int
-except AttributeError:
-    from os import sysconf
-    _getpagesize = None
+This object may be accessed either as a tuple of
+    (utime,stime,maxrss,ixrss,idrss,isrss,minflt,majflt,
+    nswap,inblock,oublock,msgsnd,msgrcv,nsignals,nvcsw,nivcsw)
+or via the attributes ru_utime, ru_stime, ru_maxrss, and so on."""
 
+    __metaclass__ = _structseq.structseqtype
 
-class timeval(Structure):
-    _fields_ = (
-        ("tv_sec", c_long),
-        ("tv_usec", c_long),
-    )
-    def __str__(self):
-        return "(%s, %s)" % (self.tv_sec, self.tv_usec)
+    ru_utime = _structseq.structseqfield(0,    "user time used")
+    ru_stime = _structseq.structseqfield(1,    "system time used")
+    ru_maxrss = _structseq.structseqfield(2,   "max. resident set size")
+    ru_ixrss = _structseq.structseqfield(3,    "shared memory size")
+    ru_idrss = _structseq.structseqfield(4,    "unshared data size")
+    ru_isrss = _structseq.structseqfield(5,    "unshared stack size")
+    ru_minflt = _structseq.structseqfield(6,   "page faults not requiring I/O")
+    ru_majflt = _structseq.structseqfield(7,   "page faults requiring I/O")
+    ru_nswap = _structseq.structseqfield(8,    "number of swap outs")
+    ru_inblock = _structseq.structseqfield(9,  "block input operations")
+    ru_oublock = _structseq.structseqfield(10, "block output operations")
+    ru_msgsnd = _structseq.structseqfield(11,  "IPC messages sent")
+    ru_msgrcv = _structseq.structseqfield(12,  "IPC messages received")
+    ru_nsignals = _structseq.structseqfield(13,"signals received")
+    ru_nvcsw = _structseq.structseqfield(14,   "voluntary context switches")
+    ru_nivcsw = _structseq.structseqfield(15,  "involuntary context switches")
 
-    def __float__(self):
-        return self.tv_sec + self.tv_usec/1000000.0
-
-class _struct_rusage(Structure):
-    _fields_ = (
-        ("ru_utime", timeval),
-        ("ru_stime", timeval),
-        ("ru_maxrss", c_long),
-        ("ru_ixrss", c_long),
-        ("ru_idrss", c_long),
-        ("ru_isrss", c_long),
-        ("ru_minflt", c_long),
-        ("ru_majflt", c_long),
-        ("ru_nswap", c_long),
-        ("ru_inblock", c_long),
-        ("ru_oublock", c_long),
-        ("ru_msgsnd", c_long),
-        ("ru_msgrcv", c_long),
-        ("ru_nsignals", c_long),
-        ("ru_nvcsw", c_long),
-        ("ru_nivcsw", c_long),
-    )
-
-_getrusage.argtypes = (c_int, POINTER(_struct_rusage))
-_getrusage.restype = c_int
-
-
-class struct_rusage(metaclass=_structseq.structseqtype):
-    ru_utime = _structseq.structseqfield(0)
-    ru_stime = _structseq.structseqfield(1)
-    ru_maxrss = _structseq.structseqfield(2)
-    ru_ixrss = _structseq.structseqfield(3)
-    ru_idrss = _structseq.structseqfield(4)
-    ru_isrss = _structseq.structseqfield(5)
-    ru_minflt = _structseq.structseqfield(6)
-    ru_majflt = _structseq.structseqfield(7)
-    ru_nswap = _structseq.structseqfield(8)
-    ru_inblock = _structseq.structseqfield(9)
-    ru_oublock = _structseq.structseqfield(10)
-    ru_msgsnd = _structseq.structseqfield(11)
-    ru_msgrcv = _structseq.structseqfield(12)
-    ru_nsignals = _structseq.structseqfield(13)
-    ru_nvcsw = _structseq.structseqfield(14)
-    ru_nivcsw = _structseq.structseqfield(15)
-
-@builtinify
-def rlimit_check_bounds(rlim_cur, rlim_max):
-    if rlim_cur > rlim_t_max:
-        raise ValueError("%d does not fit into rlim_t" % rlim_cur)
-    if rlim_max > rlim_t_max:
-        raise ValueError("%d does not fit into rlim_t" % rlim_max)
-
-class rlimit(Structure):
-    _fields_ = (
-        ("rlim_cur", rlim_t),
-        ("rlim_max", rlim_t),
-    )
-
-_getrlimit.argtypes = (c_int, POINTER(rlimit))
-_getrlimit.restype = c_int
-_setrlimit.argtypes = (c_int, POINTER(rlimit))
-_setrlimit.restype = c_int
-
-
-@builtinify
-def getrusage(who):
-    ru = _struct_rusage()
-    ret = _getrusage(who, byref(ru))
-    if ret == -1:
-        errno = get_errno()
-        if errno == EINVAL:
-            raise ValueError("invalid who parameter")
-        raise error(errno)
+def _make_struct_rusage(ru):
     return struct_rusage((
-        float(ru.ru_utime),
-        float(ru.ru_stime),
+        lib.my_utime(ru),
+        lib.my_stime(ru),
         ru.ru_maxrss,
         ru.ru_ixrss,
         ru.ru_idrss,
@@ -133,48 +59,59 @@
         ))
 
 @builtinify
+def getrusage(who):
+    ru = ffi.new("struct rusage *")
+    if lib.getrusage(who, ru) == -1:
+        if ffi.errno == EINVAL:
+            raise ValueError("invalid who parameter")
+        raise error(ffi.errno)
+    return _make_struct_rusage(ru)
+
+@builtinify
 def getrlimit(resource):
-    if not(0 <= resource < RLIM_NLIMITS):
+    if not (0 <= resource < lib.RLIM_NLIMITS):
         return ValueError("invalid resource specified")
 
-    rlim = rlimit()
-    ret = _getrlimit(resource, byref(rlim))
-    if ret == -1:
-        errno = get_errno()
-        raise error(errno)
-    return (rlim.rlim_cur, rlim.rlim_max)
+    result = ffi.new("long long[2]")
+    if lib.my_getrlimit(resource, result) == -1:
+        raise error(ffi.errno)
+    return (result[0], result[1])
 
 @builtinify
-def setrlimit(resource, rlim):
-    if not(0 <= resource < RLIM_NLIMITS):
+def setrlimit(resource, limits):
+    if not (0 <= resource < lib.RLIM_NLIMITS):
         return ValueError("invalid resource specified")
-    rlimit_check_bounds(*rlim)
-    rlim = rlimit(rlim[0], rlim[1])
 
-    ret = _setrlimit(resource, byref(rlim))
-    if ret == -1:
-        errno = get_errno()
-        if errno == EINVAL:
-            return ValueError("current limit exceeds maximum limit")
-        elif errno == EPERM:
-            return ValueError("not allowed to raise maximum limit")
+    limits = tuple(limits)
+    if len(limits) != 2:
+        raise ValueError("expected a tuple of 2 integers")
+
+    if lib.my_setrlimit(resource, limits[0], limits[1]) == -1:
+        if ffi.errno == EINVAL:
+            raise ValueError("current limit exceeds maximum limit")
+        elif ffi.errno == EPERM:
+            raise ValueError("not allowed to raise maximum limit")
         else:
-            raise error(errno)
+            raise error(ffi.errno)
+
 
 @builtinify
 def getpagesize():
-    if _getpagesize:
-        return _getpagesize()
-    else:
-        try:
-            return sysconf("SC_PAGE_SIZE")
-        except ValueError:
-            # Irix 5.3 has _SC_PAGESIZE, but not _SC_PAGE_SIZE
-            return sysconf("SC_PAGESIZE")
+    return os.sysconf("SC_PAGESIZE")
 
-__all__ = ALL_CONSTANTS + (
-    'error', 'timeval', 'struct_rusage', 'rlimit',
-    'getrusage', 'getrlimit', 'setrlimit', 'getpagesize',
+
+def _setup():
+    all_constants = []
+    p = lib.my_rlimit_consts
+    while p.name:
+        name = ffi.string(p.name)
+        globals()[name] = int(p.value)
+        all_constants.append(name)
+        p += 1
+    return all_constants
+
+__all__ = tuple(_setup()) + (
+    'error', 'getpagesize', 'struct_rusage',
+    'getrusage', 'getrlimit', 'setrlimit',
 )
-
-del ALL_CONSTANTS
+del _setup
diff --git a/pypy/goal/targetpypystandalone.py 
b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -344,10 +344,6 @@
         return PyPyJitPolicy(pypy_hooks)
 
     def get_entry_point(self, config):
-        from pypy.tool.lib_pypy import import_from_lib_pypy
-        rebuild = import_from_lib_pypy('ctypes_config_cache/rebuild')
-        rebuild.try_rebuild()
-
         space = make_objspace(config)
 
         # manually imports app_main.py
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
@@ -1353,8 +1353,8 @@
         ffi = FFI(backend=self.Backend())
         ffi.cdef("enum foo;")
         from cffi import __version_info__
-        if __version_info__ < (1, 6):
-            py.test.skip("re-enable me in version 1.6")
+        if __version_info__ < (1, 7):
+            py.test.skip("re-enable me in version 1.7")
         e = py.test.raises(CDefError, ffi.cast, "enum foo", -1)
         assert str(e.value) == (
             "'enum foo' has no values explicitly defined: refusing to guess "
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
@@ -1511,7 +1511,9 @@
             void boz(void);
         }
     """)
-    lib = verify(ffi, 'test_extern_python_1', "")
+    lib = verify(ffi, 'test_extern_python_1', """
+        static void baz(int, int);   /* forward */
+    """)
     assert ffi.typeof(lib.bar) == ffi.typeof("int(*)(int, int)")
     with FdWriteCapture() as f:
         res = lib.bar(4, 5)
@@ -1745,6 +1747,35 @@
     assert lib.mycb1(200) == 242
     assert lib.indirect_call(300) == 342
 
+def test_extern_python_plus_c():
+    ffi = FFI()
+    ffi.cdef("""
+        extern "Python+C" int foo(int);
+        extern "C +\tPython" int bar(int);
+        int call_me(int);
+    """)
+    lib = verify(ffi, 'test_extern_python_plus_c', """
+        int foo(int);
+        #ifdef __GNUC__
+        __attribute__((visibility("hidden")))
+        #endif
+        int bar(int);
+
+        static int call_me(int x) {
+            return foo(x) - bar(x);
+        }
+    """)
+    #
+    @ffi.def_extern()
+    def foo(x):
+        return x * 42
+    @ffi.def_extern()
+    def bar(x):
+        return x * 63
+    assert lib.foo(100) == 4200
+    assert lib.bar(100) == 6300
+    assert lib.call_me(100) == -2100
+
 def test_introspect_function():
     ffi = FFI()
     ffi.cdef("float f1(double);")
diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/empty.py 
b/pypy/module/test_lib_pypy/cffi_tests/embedding/empty.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/test_lib_pypy/cffi_tests/embedding/empty.py
@@ -0,0 +1,11 @@
+# Generated by pypy/tool/import_cffi.py
+import cffi
+
+ffi = cffi.FFI()
+
+ffi.embedding_api("")
+
+ffi.set_source("_empty_cffi", "")
+
+fn = ffi.compile(verbose=True)
+print('FILENAME: %s' % (fn,))
diff --git a/pypy/module/test_lib_pypy/test_collections.py 
b/pypy/module/test_lib_pypy/test_collections.py
--- a/pypy/module/test_lib_pypy/test_collections.py
+++ b/pypy/module/test_lib_pypy/test_collections.py
@@ -62,6 +62,12 @@
             raises(IndexError, d.remove, 'c')
             assert len(d) == 0
 
+    def test_deque_unhashable(self):
+        from collections import Hashable
+        d = self.get_deque()
+        raises(TypeError, hash, d)
+        assert not isinstance(d, Hashable)
+
 class AppTestDequeExtra:
 
     spaceconfig = dict(usemodules=('binascii', 'struct',))
diff --git a/pypy/module/test_lib_pypy/test_ctypes_config_cache.py 
b/pypy/module/test_lib_pypy/test_ctypes_config_cache.py
deleted file mode 100644
--- a/pypy/module/test_lib_pypy/test_ctypes_config_cache.py
+++ /dev/null
@@ -1,44 +0,0 @@
-import py
-import sys, os
-from rpython.tool.udir import udir
-
-dirpath = py.path.local(__file__).dirpath().dirpath().dirpath().dirpath()
-dirpath = dirpath.join('lib_pypy').join('ctypes_config_cache')
-
-
-def run(filename, outputname):
-    filepath = dirpath.join(filename)
-    tmpdir = udir.ensure('testcache-' + os.path.splitext(filename)[0],
-                         dir=True)
-    tmpdir.join('dumpcache.py').write(dirpath.join('dumpcache.py').read())
-    path = sys.path[:]
-    sys.modules.pop('dumpcache', None)
-    try:
-        sys.path.insert(0, str(tmpdir))
-        execfile(str(filepath), {})
-    finally:
-        sys.path[:] = path
-        sys.modules.pop('dumpcache', None)
-    #
-    outputpath = tmpdir.join(outputname)
-    assert outputpath.check(exists=1)
-    modname = os.path.splitext(outputname)[0]
-    try:
-        sys.path.insert(0, str(tmpdir))
-        d = {}
-        execfile(str(outputpath), d)
-    finally:
-        sys.path[:] = path
-    return d
-
-
-def test_resource():
-    if sys.platform == 'win32':
-        py.test.skip('no resource module on this platform')
-    d = run('resource.ctc.py', '_resource_cache.py')
-    assert 'RLIM_NLIMITS' in d
-
-def test_locale():
-    d = run('locale.ctc.py', '_locale_cache.py')
-    assert 'LC_ALL' in d
-    assert 'CHAR_MAX' in d
diff --git a/pypy/module/test_lib_pypy/test_os_wait.py 
b/pypy/module/test_lib_pypy/test_os_wait.py
--- a/pypy/module/test_lib_pypy/test_os_wait.py
+++ b/pypy/module/test_lib_pypy/test_os_wait.py
@@ -1,52 +1,36 @@
-# Generates the resource cache (it might be there already, but maybe not)
+# Assumes that _resource_cffi is there already
 from __future__ import absolute_import
 import os
+import py
+from pypy.module.test_lib_pypy import test_resource   # side-effect: skip()
 
-import py
 
-from lib_pypy.ctypes_config_cache import rebuild
-from pypy.module.test_lib_pypy.support import import_lib_pypy
+from lib_pypy import _pypy_wait
 
+def test_os_wait3():
+    wait3 = _pypy_wait.wait3
+    exit_status = 0x33
+    child = os.fork()
+    if child == 0: # in child
+        os._exit(exit_status)
+    else:
+        pid, status, rusage = wait3(0)
+        assert child == pid
+        assert os.WIFEXITED(status)
+        assert os.WEXITSTATUS(status) == exit_status
+        assert isinstance(rusage.ru_utime, float)
+        assert isinstance(rusage.ru_maxrss, int)
 
-class AppTestOsWait:
-
-    spaceconfig = dict(usemodules=('_rawffi', 'fcntl', 'itertools', 'select',
-                                   'signal', '_posixsubprocess'))
-
-    def setup_class(cls):
-        if not hasattr(os, "fork"):
-            py.test.skip("Need fork() to test wait3/wait4()")
-        rebuild.rebuild_one('resource.ctc.py')
-        cls.space.appexec([], "(): import ctypes")
-        cls.w__pypy_wait = import_lib_pypy(
-            cls.space, '_pypy_wait')
-
-    def test_os_wait3(self):
-        import os
-        wait3 = self._pypy_wait.wait3
-        exit_status = 0x33
-        child = os.fork()
-        if child == 0: # in child
-            os._exit(exit_status)
-        else:
-            pid, status, rusage = wait3(0)
-            assert child == pid
-            assert os.WIFEXITED(status)
-            assert os.WEXITSTATUS(status) == exit_status
-            assert isinstance(rusage.ru_utime, float)
-            assert isinstance(rusage.ru_maxrss, int)
-
-    def test_os_wait4(self):
-        import os
-        wait4 = self._pypy_wait.wait4
-        exit_status = 0x33
-        child = os.fork()
-        if child == 0: # in child
-            os._exit(exit_status)
-        else:
-            pid, status, rusage = wait4(child, 0)
-            assert child == pid
-            assert os.WIFEXITED(status)
-            assert os.WEXITSTATUS(status) == exit_status
-            assert isinstance(rusage.ru_utime, float)
-            assert isinstance(rusage.ru_maxrss, int)
+def test_os_wait4():
+    wait4 = _pypy_wait.wait4
+    exit_status = 0x33
+    child = os.fork()
+    if child == 0: # in child
+        os._exit(exit_status)
+    else:
+        pid, status, rusage = wait4(child, 0)
+        assert child == pid
+        assert os.WIFEXITED(status)
+        assert os.WEXITSTATUS(status) == exit_status
+        assert isinstance(rusage.ru_utime, float)
+        assert isinstance(rusage.ru_maxrss, int)
diff --git a/pypy/module/test_lib_pypy/test_resource.py 
b/pypy/module/test_lib_pypy/test_resource.py
--- a/pypy/module/test_lib_pypy/test_resource.py
+++ b/pypy/module/test_lib_pypy/test_resource.py
@@ -1,45 +1,49 @@
 from __future__ import absolute_import
 
-from lib_pypy.ctypes_config_cache import rebuild
-from pypy.module.test_lib_pypy.support import import_lib_pypy
-
 import os
 if os.name != 'posix':
     skip('resource.h only available on unix')
 
-class AppTestResource:
+try:
+    from lib_pypy import resource
+except ImportError as e:
+    skip(str(e))
 
-    spaceconfig = dict(usemodules=('_rawffi', 'fcntl', 'itertools', 'select',
-                                   'signal'))
 
-    def setup_class(cls):
-        rebuild.rebuild_one('resource.ctc.py')
-        cls.w_resource = import_lib_pypy(cls.space, 'resource',
-                                         'No resource module available')
+def test_getrusage():
+    x = resource.getrusage(resource.RUSAGE_SELF)
+    assert len(x) == 16
+    assert x[0] == x[-16] == x.ru_utime
+    assert x[1] == x[-15] == x.ru_stime
+    assert x[2] == x[-14] == x.ru_maxrss
+    assert x[3] == x[-13] == x.ru_ixrss
+    assert x[4] == x[-12] == x.ru_idrss
+    assert x[5] == x[-11] == x.ru_isrss
+    assert x[6] == x[-10] == x.ru_minflt
+    assert x[7] == x[-9] == x.ru_majflt
+    assert x[8] == x[-8] == x.ru_nswap
+    assert x[9] == x[-7] == x.ru_inblock
+    assert x[10] == x[-6] == x.ru_oublock
+    assert x[11] == x[-5] == x.ru_msgsnd
+    assert x[12] == x[-4] == x.ru_msgrcv
+    assert x[13] == x[-3] == x.ru_nsignals
+    assert x[14] == x[-2] == x.ru_nvcsw
+    assert x[15] == x[-1] == x.ru_nivcsw
+    for i in range(16):
+        if i < 2:
+            expected_type = float
+        else:
+            expected_type = int
+        assert isinstance(x[i], expected_type)
 
-    def test_resource(self):
-        resource = self.resource
-        x = resource.getrusage(resource.RUSAGE_SELF)
-        assert len(x) == 16
-        assert x[0] == x[-16] == x.ru_utime
-        assert x[1] == x[-15] == x.ru_stime
-        assert x[2] == x[-14] == x.ru_maxrss
-        assert x[3] == x[-13] == x.ru_ixrss
-        assert x[4] == x[-12] == x.ru_idrss
-        assert x[5] == x[-11] == x.ru_isrss
-        assert x[6] == x[-10] == x.ru_minflt
-        assert x[7] == x[-9] == x.ru_majflt
-        assert x[8] == x[-8] == x.ru_nswap
-        assert x[9] == x[-7] == x.ru_inblock
-        assert x[10] == x[-6] == x.ru_oublock
-        assert x[11] == x[-5] == x.ru_msgsnd
-        assert x[12] == x[-4] == x.ru_msgrcv
-        assert x[13] == x[-3] == x.ru_nsignals
-        assert x[14] == x[-2] == x.ru_nvcsw
-        assert x[15] == x[-1] == x.ru_nivcsw
-        for i in range(16):
-            if i < 2:
-                expected_type = float
-            else:
-                expected_type = int
-            assert isinstance(x[i], expected_type)
+def test_getrlimit():
+    x = resource.getrlimit(resource.RLIMIT_CPU)
+    assert isinstance(x, tuple)
+    assert len(x) == 2
+    assert isinstance(x[0], int)
+    assert isinstance(x[1], int)
+
+def test_setrlimit():
+    # minimal "does not crash" test
+    x = resource.getrlimit(resource.RLIMIT_CPU)
+    resource.setrlimit(resource.RLIMIT_CPU, x)
diff --git a/pypy/tool/build_cffi_imports.py b/pypy/tool/build_cffi_imports.py
--- a/pypy/tool/build_cffi_imports.py
+++ b/pypy/tool/build_cffi_imports.py
@@ -13,6 +13,7 @@
     "syslog": "_syslog_build.py" if sys.platform != "win32" else None,
     "_gdbm": "_gdbm_build.py"  if sys.platform != "win32" else None,
     "pwdgrp": "_pwdgrp_build.py" if sys.platform != "win32" else None,
+    "resource": "_resource_build.py" if sys.platform != "win32" else None,
     "lzma": "_lzma_build.py",
     "_decimal": "_decimal_build.py",
     "xx": None,    # for testing: 'None' should be completely ignored
diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py
--- a/pypy/tool/release/package.py
+++ b/pypy/tool/release/package.py
@@ -172,6 +172,7 @@
 
     # Careful: to copy lib_pypy, copying just the hg-tracked files
     # would not be enough: there are also ctypes_config_cache/_*_cache.py.
+    # XXX ^^^ this is no longer true!
     shutil.copytree(str(basedir.join('lib-python').join(STDLIB_VER)),
                     str(pypydir.join('lib-python').join(STDLIB_VER)),
                     ignore=ignore_patterns('.svn', 'py', '*.pyc', '*~'))
diff --git a/rpython/jit/backend/zarch/regalloc.py 
b/rpython/jit/backend/zarch/regalloc.py
--- a/rpython/jit/backend/zarch/regalloc.py
+++ b/rpython/jit/backend/zarch/regalloc.py
@@ -182,9 +182,9 @@
         """
         self._check_type(origvar)
         prev_loc = self.loc(origvar, must_exist=must_exist)
-        var2 = TempVar()
+        var2 = TempInt()
         if bindvar is None:
-            bindvar = TempVar()
+            bindvar = TempInt()
         if bind_first:
             loc, loc2 = self.force_allocate_reg_pair(bindvar, var2, 
self.temp_boxes)
         else:
@@ -310,20 +310,22 @@
             # uff! in this case, we need to move a forbidden var to another 
register
             assert len(forbidden_vars) <= 8 # otherwise it is NOT possible to 
complete
             even, odd = r.r2, r.r3
-            even_var = reverse_mapping.get(even, None)
-            odd_var = reverse_mapping.get(odd, None)
-            if even_var:
-                if even_var in forbidden_vars:
-                    self._relocate_forbidden_variable(even, even_var, 
reverse_mapping,
+            old_even_var = reverse_mapping.get(even, None)
+            old_odd_var = reverse_mapping.get(odd, None)
+            if old_even_var:
+                if old_even_var in forbidden_vars:
+                    self._relocate_forbidden_variable(even, old_even_var, 
reverse_mapping,
                                                       forbidden_vars, odd)
                 else:
-                    self._sync_var(even_var)
-            if odd_var:
-                if odd_var in forbidden_vars:
-                    self._relocate_forbidden_variable(odd, odd_var, 
reverse_mapping,
+                    self._sync_var(old_even_var)
+                    del self.reg_bindings[old_even_var]
+            if old_odd_var:
+                if old_odd_var in forbidden_vars:
+                    self._relocate_forbidden_variable(odd, old_odd_var, 
reverse_mapping,
                                                       forbidden_vars, even)
                 else:
-                    self._sync_var(odd_var)
+                    self._sync_var(old_odd_var)
+                    del self.reg_bindings[old_odd_var]
 
             self.free_regs = [fr for fr in self.free_regs \
                               if fr is not even and \
@@ -335,6 +337,12 @@
         return even, odd
 
     def _relocate_forbidden_variable(self, reg, var, reverse_mapping, 
forbidden_vars, forbidden_reg):
+        if len(self.free_regs) > 0:
+            candidate = self.free_regs.pop()
+            self.assembler.regalloc_mov(reg, candidate)
+            self.reg_bindings[var] = candidate
+            reverse_mapping[candidate] = var
+
         for candidate in r.MANAGED_REGS:
             # move register of var to another register
             # thus it is not allowed to bei either reg or forbidden_reg
@@ -345,9 +353,11 @@
             if not candidate_var or candidate_var not in forbidden_vars:
                 if candidate_var is not None:
                     self._sync_var(candidate_var)
+                    del self.reg_bindings[candidate_var]
                 self.assembler.regalloc_mov(reg, candidate)
+                assert var is not None
                 self.reg_bindings[var] = candidate
-                reverse_mapping[reg] = var
+                reverse_mapping[candidate] = var
                 self.free_regs.append(reg)
                 break
         else:
diff --git a/rpython/rlib/rposix_stat.py b/rpython/rlib/rposix_stat.py
--- a/rpython/rlib/rposix_stat.py
+++ b/rpython/rlib/rposix_stat.py
@@ -94,7 +94,8 @@
         return self.__class__,
 
     def getattr(self, s_attr):
-        assert s_attr.is_constant(), "non-constant attr name in getattr()"
+        if not s_attr.is_constant():
+            raise annmodel.AnnotatorError("non-constant attr name in 
getattr()")
         attrname = s_attr.const
         TYPE = STAT_FIELD_TYPES[attrname]
         return lltype_to_annotation(TYPE)
diff --git a/rpython/rlib/test/test_rthread.py 
b/rpython/rlib/test/test_rthread.py
--- a/rpython/rlib/test/test_rthread.py
+++ b/rpython/rlib/test/test_rthread.py
@@ -287,7 +287,12 @@
             wr_from_thread.seen = False
             start_new_thread(thread_entry_point, ())
             wr1 = f()
-            time.sleep(0.5)
+            count = 0
+            while True:
+                time.sleep(0.5)
+                if wr_from_thread.seen or count >= 50:
+                    break
+                count += 1
             assert wr_from_thread.seen is True
             wr2 = wr_from_thread.wr
             import gc; gc.collect()      # wr2() should be collected here
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to