Author: Ronan Lamy <[email protected]>
Branch: PEP393
Changeset: r89920:791a64ac3ea2
Date: 2017-02-04 17:56 +0000
http://bitbucket.org/pypy/pypy/changeset/791a64ac3ea2/

Log:    hg merge py3.5

diff too long, truncating to 2000 out of 5539 lines

diff --git a/lib-python/3/datetime.py b/lib-python/3/datetime.py
--- a/lib-python/3/datetime.py
+++ b/lib-python/3/datetime.py
@@ -706,7 +706,7 @@
 
     @classmethod
     def fromordinal(cls, n):
-        """Contruct a date from a proleptic Gregorian ordinal.
+        """Construct a date from a proleptic Gregorian ordinal.
 
         January 1 of year 1 is day 1.  Only the year, month and day are
         non-zero in the result.
@@ -1145,18 +1145,17 @@
     def __hash__(self):
         """Hash."""
         if self._hashcode == -1:
+            # PyPy: uses the same algo as _datetimemodule.c, which
+            # unlike the pure Python version always relies on the
+            # nondeterministic hash on strings
+            temp1 = timedelta(hours=self._hour,
+                              minutes=self._minute,
+                              seconds=self._second,
+                              microseconds=self._microsecond)
             tzoff = self.utcoffset()
-            if not tzoff:  # zero or None
-                self._hashcode = hash(self._getstate()[0])
-            else:
-                h, m = divmod(timedelta(hours=self.hour, minutes=self.minute) 
- tzoff,
-                              timedelta(hours=1))
-                assert not m % timedelta(minutes=1), "whole minute"
-                m //= timedelta(minutes=1)
-                if 0 <= h < 24:
-                    self._hashcode = hash(time(h, m, self.second, 
self.microsecond))
-                else:
-                    self._hashcode = hash((h, m, self.second, 
self.microsecond))
+            if tzoff:  # not zero, not None
+                temp1 -= tzoff
+            self._hashcode = hash(temp1)
         return self._hashcode
 
     # Conversion to string
diff --git a/lib-python/3/importlib/_bootstrap_external.py 
b/lib-python/3/importlib/_bootstrap_external.py
--- a/lib-python/3/importlib/_bootstrap_external.py
+++ b/lib-python/3/importlib/_bootstrap_external.py
@@ -238,6 +238,12 @@
 # different than CPython's, always < 3000.  We get the 4-bytes string
 # here via a hack: MAGIC_NUMBER is set in the module from
 # module/_frozen_importlib/__init__.py before the module is executed.
+# FOR TESTS ONLY, we make it default to imp.get_magic().
+try:
+    MAGIC_NUMBER
+except NameError:
+    import imp
+    MAGIC_NUMBER = imp.get_magic()
 
 _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little')  # For import.c
 
diff --git a/lib-python/3/test/_test_multiprocessing.py 
b/lib-python/3/test/_test_multiprocessing.py
--- a/lib-python/3/test/_test_multiprocessing.py
+++ b/lib-python/3/test/_test_multiprocessing.py
@@ -2795,6 +2795,7 @@
             self.assertTrue((arena != narena and nstart == 0) or
                             (stop == nstart))
 
+    @test.support.cpython_only
     def test_free_from_gc(self):
         # Check that freeing of blocks by the garbage collector doesn't 
deadlock
         # (issue #12352).
@@ -2893,12 +2894,14 @@
         a = Foo()
         util.Finalize(a, conn.send, args=('a',))
         del a           # triggers callback for a
+        import gc; gc.collect()
 
         b = Foo()
         close_b = util.Finalize(b, conn.send, args=('b',))
         close_b()       # triggers callback for b
         close_b()       # does nothing because callback has already been called
         del b           # does nothing because callback has already been called
+        import gc; gc.collect()
 
         c = Foo()
         util.Finalize(c, conn.send, args=('c',))
diff --git a/lib-python/3/test/test_hash.py b/lib-python/3/test/test_hash.py
--- a/lib-python/3/test/test_hash.py
+++ b/lib-python/3/test/test_hash.py
@@ -43,7 +43,7 @@
 
 def skip_unless_internalhash(test):
     """Skip decorator for tests that depend on SipHash24 or FNV"""
-    ok = sys.hash_info.algorithm in {"fnv", "siphash24", "rpython"}
+    ok = sys.hash_info.algorithm in {"fnv", "siphash24"}
     msg = "Requires SipHash24 or FNV"
     return test if ok else unittest.skip(msg)(test)
 
@@ -189,7 +189,6 @@
         stdout = out[1].strip()
         return int(stdout)
 
-    @impl_detail("PyPy does not support hash randomization", pypy=False)
     def test_randomized_hash(self):
         # two runs should return different hashes
         run1 = self.get_hash(self.repr_, seed='random')
@@ -197,10 +196,6 @@
         self.assertNotEqual(run1, run2)
 
 class StringlikeHashRandomizationTests(HashRandomizationTests):
-    if check_impl_detail(pypy=True):
-        EMPTY_STRING_HASH = -2
-    else:
-        EMPTY_STRING_HASH = 0
     repr_ = None
     repr_long = None
 
@@ -242,9 +237,9 @@
             [-283066365, -4576729883824601543, -271871407,
              -3927695501187247084],
         ],
-        'rpython': [
-            # This is for PyPy.  NOTE: PyPy does not support hash
-            # randomization for now, so the results don't depend on the seed.
+        'fnv-pypy': [
+            # This is for PyPy, whose fnv algorithm does not support hash
+            # randomization, so the results don't depend on the seed.
             # seed 0, 'abc'
             [-1600925533, 1453079729188098211, -1600925533,
              1453079729188098211],
@@ -273,6 +268,8 @@
         else:
             assert(sys.byteorder == 'big')
             platform = 3 if IS_64BIT else 2
+        if algorithm == 'fnv' and check_impl_detail(pypy=True):
+            algorithm = 'fnv-pypy'
         return self.known_hashes[algorithm][position][platform]
 
     def test_null_hash(self):
@@ -280,8 +277,7 @@
         known_hash_of_obj = self.get_expected_hash(0, 3)
 
         # Randomization is enabled by default:
-        if check_impl_detail(pypy=False):
-            self.assertNotEqual(self.get_hash(self.repr_), known_hash_of_obj)
+        self.assertNotEqual(self.get_hash(self.repr_), known_hash_of_obj)
 
         # It can also be disabled by setting the seed to 0:
         self.assertEqual(self.get_hash(self.repr_, seed=0), known_hash_of_obj)
@@ -307,11 +303,12 @@
     repr_long = repr('abcdefghijk')
     repr_ucs2 = repr('&#228;&#250;&#8721;&#8455;')
 
-    @impl_detail("hash('') == -2 on PyPy", pypy=False)
+    @impl_detail("hash('') != 0 on PyPy", pypy=False)
     @skip_unless_internalhash
     def test_empty_string(self):
         self.assertEqual(hash(""), 0)
 
+    @impl_detail("hash(ucs2) differs on PyPy if unichar is 4 bytes", 
pypy=False)
     @skip_unless_internalhash
     def test_ucs2_string(self):
         h = self.get_expected_hash(3, 6)
@@ -324,18 +321,20 @@
     repr_ = repr(b'abc')
     repr_long = repr(b'abcdefghijk')
 
+    @impl_detail("hash('') != 0 on PyPy", pypy=False)
     @skip_unless_internalhash
     def test_empty_string(self):
-        self.assertEqual(hash(b""), self.EMPTY_STRING_HASH)
+        self.assertEqual(hash(b""), 0)
 
 class MemoryviewHashRandomizationTests(StringlikeHashRandomizationTests,
                                        unittest.TestCase):
     repr_ = "memoryview(b'abc')"
     repr_long = "memoryview(b'abcdefghijk')"
 
+    @impl_detail("hash('') != 0 on PyPy", pypy=False)
     @skip_unless_internalhash
     def test_empty_string(self):
-        self.assertEqual(hash(memoryview(b"")), self.EMPTY_STRING_HASH)
+        self.assertEqual(hash(memoryview(b"")), 0)
 
 class DatetimeTests(HashRandomizationTests):
     def get_hash_command(self, repr_):
diff --git a/lib-python/3/test/test_signal.py b/lib-python/3/test/test_signal.py
--- a/lib-python/3/test/test_signal.py
+++ b/lib-python/3/test/test_signal.py
@@ -358,6 +358,8 @@
 
         assert_python_ok('-c', code)
 
+    @support.impl_detail("pypy writes the message to fd 2, not to sys.stderr",
+                         pypy=False)
     @unittest.skipIf(_testcapi is None, 'need _testcapi')
     def test_wakeup_write_error(self):
         # Issue #16105: write() errors in the C signal handler should not
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -261,7 +261,7 @@
     RegrTest('test_imaplib.py'),
     RegrTest('test_imghdr.py'),
     RegrTest('test_import'),
-    RegrTest('test_importlib', skip='XXX segfaults'),
+    RegrTest('test_importlib'),
     RegrTest('test_imp.py', core=True, usemodules='thread'),
     RegrTest('test_index.py'),
     RegrTest('test_inspect.py', usemodules="struct unicodedata"),
@@ -304,10 +304,10 @@
     RegrTest('test_modulefinder.py'),
     RegrTest('test_msilib.py'),
     RegrTest('test_multibytecodec.py', usemodules='_multibytecodec'),
-    RegrTest('test_multiprocessing_fork.py', skip="XXX: deadlocks?"),
-    RegrTest('test_multiprocessing_forkserver.py', skip="XXX: deadlocks?"),
-    RegrTest('test_multiprocessing_main_handling.py', skip="XXX: deadlocks?"),
-    RegrTest('test_multiprocessing_spawn.py', skip="XXX: deadlocks?"),
+    RegrTest('test_multiprocessing_fork.py'),
+    RegrTest('test_multiprocessing_forkserver.py'),
+    RegrTest('test_multiprocessing_main_handling.py'),
+    RegrTest('test_multiprocessing_spawn.py'),
     RegrTest('test_netrc.py'),
     RegrTest('test_nis.py'),
     RegrTest('test_nntplib.py'),
diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py
--- a/lib_pypy/_ctypes/basics.py
+++ b/lib_pypy/_ctypes/basics.py
@@ -92,7 +92,11 @@
                 % (buf.nbytes, offset + size))
         raw_addr = buf._pypy_raw_address() + offset
         result = self.from_address(raw_addr)
-        result._ensure_objects()['ffffffff'] = obj
+        objects = result._ensure_objects()
+        if objects is not None:
+            objects['ffffffff'] = obj
+        else:   # case e.g. of a primitive type like c_int
+            result._objects = obj
         return result
 
     def from_buffer_copy(self, obj, offset=0):
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -201,6 +201,13 @@
                "issue, you can disable them here",
                default=True),
 
+    ChoiceOption("hash",
+                 "The hash function to use for strings: fnv from CPython 2.7"
+                 " or siphash24 from CPython >= 3.4",
+                 ["fnv", "siphash24"],
+                 default="siphash24",
+                 cmdline="--hash"),
+
     OptionDescription("std", "Standard Object Space Options", [
         BoolOption("withtproxy", "support transparent proxies",
                    default=True),
diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst
--- a/pypy/doc/build.rst
+++ b/pypy/doc/build.rst
@@ -56,6 +56,9 @@
 .. _`arm document`: http://rpython.readthedocs.org/en/latest/arm.html
 .. _`RPython documentation`: http://rpython.readthedocs.org
 
+The host Python needs to have CFFI installed. If translating on PyPy, CFFI is
+already installed. If translating on CPython, you need to install it, e.g. 
+using ``pip install cffi``.
 
 To build PyPy on Unix using the C translation backend, you need at least a C
 compiler and ``make`` installed. Further, some optional modules have additional
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
@@ -134,3 +134,12 @@
 rffi structures in cpyext can now be created by parsing simple C headers.
 Additionally, the cts object that holds the parsed information can act like
 cffi's ffi objects, with the methods cts.cast() and cts.gettype().
+
+.. branch: rpython-hash
+
+Don't freeze hashes in the translated pypy.  In practice, that means
+that we can now translate PyPy with the option --hash=siphash24 and get
+the same hashes as CPython 3.5, which can be randomized (in a
+crypographically good way).  It is the default in PyPy3.  The default of
+PyPy2 remains unchanged: there are user programs out there that depend
+on constant hashes (or even sometimes on specific hash results).
diff --git a/pypy/goal/targetpypystandalone.py 
b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -36,6 +36,7 @@
         w_run_toplevel = space.getitem(w_dict, space.wrap('run_toplevel'))
         w_initstdio = space.getitem(w_dict, space.wrap('initstdio'))
         withjit = space.config.objspace.usemodules.pypyjit
+        hashfunc = space.config.objspace.hash
     else:
         w_initstdio = space.appexec([], """():
             return lambda unbuffered: None
@@ -46,6 +47,10 @@
             from rpython.jit.backend.hlinfo import highleveljitinfo
             highleveljitinfo.sys_executable = argv[0]
 
+        if hashfunc == "siphash24":
+            from rpython.rlib import rsiphash
+            rsiphash.enable_siphash24()
+
         #debug("entry point starting")
         #for arg in argv:
         #    debug(" argv -> " + arg)
diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py
--- a/pypy/interpreter/app_main.py
+++ b/pypy/interpreter/app_main.py
@@ -728,8 +728,26 @@
             if IS_WINDOWS:
                 filename = filename.lower()
             if filename.endswith('.pyc') or filename.endswith('.pyo'):
+                # We don't actually load via SourcelessFileLoader
+                # because '__main__' must not be listed inside
+                # 'importlib._bootstrap._module_locks' (it deadlocks
+                # test_multiprocessing_main_handling.test_script_compiled)
+                from importlib._bootstrap_external import MAGIC_NUMBER
+                import marshal
                 loader = SourcelessFileLoader('__main__', filename)
-                args = (loader.load_module, loader.name)
+                mainmodule.__loader__ = loader
+                @hidden_applevel
+                def execfile(filename, namespace):
+                    with open(filename, 'rb') as f:
+                        if f.read(4) != MAGIC_NUMBER:
+                            raise RuntimeError("Bad magic number in .pyc file")
+                        if len(f.read(8)) != 8:
+                            raise RuntimeError("Truncated .pyc file")
+                        co = marshal.load(f)
+                    if type(co) is not type((lambda:0).__code__):
+                        raise RuntimeError("Bad code object in .pyc file")
+                    exec_(co, namespace)
+                args = (execfile, filename, mainmodule.__dict__)
             else:
                 filename = sys.argv[0]
                 for hook in sys.path_hooks:
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -225,14 +225,14 @@
     def buffer_w(self, space, flags):
         if _does_override_buffer_w_ex(self.__class__):
             return self.buffer_w_ex(space, flags)[0]
-        return self._buffer(space, flags).buffer_w(space, flags)
+        return self.__buffer_w(space, flags).buffer_w(space, flags)
 
     def buffer_w_ex(self, space, flags):
         if _does_override_buffer_w(self.__class__):
             return self.buffer_w(space, flags), 'B', 1
-        return self._buffer(space, flags).buffer_w_ex(space, flags)
+        return self.__buffer_w(space, flags).buffer_w_ex(space, flags)
 
-    def _buffer(self, space, flags):
+    def __buffer_w(self, space, flags):
         if flags & space.BUF_WRITABLE:
             w_impl = space.lookup(self, '__wbuffer__')
         else:
diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -7,7 +7,7 @@
 
 from rpython.rlib import jit
 from rpython.rlib.objectmodel import we_are_translated, specialize
-from rpython.rlib import rstackovf
+from rpython.rlib import rstack, rstackovf
 
 from pypy.interpreter import debug
 
@@ -60,6 +60,7 @@
         "Check if this is an exception that should better not be caught."
         return (self.match(space, space.w_SystemExit) or
                 self.match(space, space.w_KeyboardInterrupt))
+        # note: an extra case is added in OpErrFmtNoArgs
 
     def __str__(self):
         "NOT_RPYTHON: Convenience for tracebacks."
@@ -512,6 +513,16 @@
     def _compute_value(self, space):
         return self._value.decode('utf-8')
 
+    def async(self, space):
+        # also matches a RuntimeError("maximum rec.") if the stack is
+        # still almost full, because in this case it might be a better
+        # idea to propagate the exception than eat it
+        if (self.w_type is space.w_RecursionError and
+            self._value == "maximum recursion depth exceeded" and
+            rstack.stack_almost_full()):
+            return True
+        return OperationError.async(self, space)
+
 @specialize.memo()
 def get_operr_class(valuefmt):
     try:
diff --git a/pypy/interpreter/test/test_function.py 
b/pypy/interpreter/test/test_function.py
--- a/pypy/interpreter/test/test_function.py
+++ b/pypy/interpreter/test/test_function.py
@@ -160,10 +160,8 @@
     def test_write_code_builtin_forbidden(self):
         def f(*args):
             return 42
-        if hasattr('dir', '__code__'):
-            # only on PyPy, CPython does not expose these attrs
-            raises(TypeError, "dir.__code__ = f.__code__")
-            raises(TypeError, "list().append.__func__.__code__ = f.__code__")
+        raises(TypeError, "dir.__code__ = f.__code__")
+        raises(TypeError, "list.append.__code__ = f.__code__")
 
     def test_set_module_to_name_eagerly(self):
         skip("fails on PyPy but works on CPython.  Unsure we want to care")
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -88,6 +88,7 @@
         '_promote'                   : 'interp_magic._promote',
         'normalize_exc'             : 'interp_magic.normalize_exc',
         'StdErrPrinter'             : 'interp_stderrprinter.W_StdErrPrinter',
+        'stack_almost_full'         : 'interp_magic.stack_almost_full',
     }
 
     submodules = {
diff --git a/pypy/module/__pypy__/interp_magic.py 
b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -9,7 +9,7 @@
 from pypy.objspace.std.setobject import W_BaseSetObject
 from pypy.objspace.std.typeobject import MethodCache
 from pypy.objspace.std.mapdict import MapAttrCache
-from rpython.rlib import rposix, rgc
+from rpython.rlib import rposix, rgc, rstack
 
 
 def internal_repr(space, w_object):
@@ -176,3 +176,7 @@
     operr = OperationError(w_type, w_value, w_tb)
     operr.normalize_exception(space)
     return operr.get_w_value(space)
+
+def stack_almost_full(space):
+    """Return True if the stack is more than 15/16th full."""
+    return space.wrap(rstack.stack_almost_full())
diff --git a/pypy/module/_cffi_backend/newtype.py 
b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -23,13 +23,34 @@
 # ____________________________________________________________
 
 class UniqueCache:
+    for_testing = False    # set to True on the class level in test_c.py
+
     def __init__(self, space):
         self.ctvoid = None      # Cache for the 'void' type
         self.ctvoidp = None     # Cache for the 'void *' type
         self.ctchara = None     # Cache for the 'char[]' type
         self.primitives = {}    # Cache for {name: primitive_type}
         self.functions = []     # see _new_function_type()
-        self.for_testing = False
+        self.functions_packed = None     # only across translation
+
+    def _cleanup_(self):
+        import gc
+        assert self.functions_packed is None
+        # Note: a full PyPy translation may still have
+        # 'self.functions == []' at this point, possibly depending
+        # on details.  Code tested directly in test_ffi_obj
+        gc.collect()
+        funcs = []
+        for weakdict in self.functions:
+            funcs += weakdict._dict.values()
+        del self.functions[:]
+        self.functions_packed = funcs if len(funcs) > 0 else None
+
+    def unpack_functions(self):
+        for fct in self.functions_packed:
+            _record_function_type(self, fct)
+        self.functions_packed = None
+
 
 def _clean_cache(space):
     "NOT_RPYTHON"
@@ -622,7 +643,7 @@
     for w_arg in fargs:
         y = compute_identity_hash(w_arg)
         x = intmask((1000003 * x) ^ y)
-    x ^= (ellipsis - abi)
+    x ^= ellipsis + 2 * abi
     if unique_cache.for_testing:    # constant-folded to False in translation;
         x &= 3                      # but for test, keep only 2 bits of hash
     return x
@@ -646,6 +667,8 @@
     # one such dict, but in case of hash collision, there might be
     # more.
     unique_cache = space.fromcache(UniqueCache)
+    if unique_cache.functions_packed is not None:
+        unique_cache.unpack_functions()
     func_hash = _func_key_hash(unique_cache, fargs, fresult, ellipsis, abi)
     for weakdict in unique_cache.functions:
         ctype = weakdict.get(func_hash)
@@ -674,13 +697,18 @@
     #
     fct = ctypefunc.W_CTypeFunc(space, fargs, fresult, ellipsis, abi)
     unique_cache = space.fromcache(UniqueCache)
-    func_hash = _func_key_hash(unique_cache, fargs, fresult, ellipsis, abi)
+    _record_function_type(unique_cache, fct)
+    return fct
+
+def _record_function_type(unique_cache, fct):
+    from pypy.module._cffi_backend import ctypefunc
+    #
+    func_hash = _func_key_hash(unique_cache, fct.fargs, fct.ctitem,
+                               fct.ellipsis, fct.abi)
     for weakdict in unique_cache.functions:
         if weakdict.get(func_hash) is None:
-            weakdict.set(func_hash, fct)
             break
     else:
         weakdict = rweakref.RWeakValueDictionary(int, ctypefunc.W_CTypeFunc)
         unique_cache.functions.append(weakdict)
-        weakdict.set(func_hash, fct)
-    return fct
+    weakdict.set(func_hash, fct)
diff --git a/pypy/module/_cffi_backend/test/test_c.py 
b/pypy/module/_cffi_backend/test/test_c.py
--- a/pypy/module/_cffi_backend/test/test_c.py
+++ b/pypy/module/_cffi_backend/test/test_c.py
@@ -37,6 +37,7 @@
     def setup_class(cls):
         testfuncs_w = []
         keepalive_funcs = []
+        UniqueCache.for_testing = True
 
         test_lib_c = tmpdir.join('_test_lib.c')
         src_test_lib_c = py.path.local(__file__).dirpath().join('_test_lib.c')
@@ -100,11 +101,12 @@
             _all_test_c.find_and_load_library = func
             _all_test_c._testfunc = testfunc
         """)
-        UniqueCache.for_testing = True
 
     def teardown_method(self, method):
+        _clean_cache(self.space)
+
+    def teardown_class(cls):
         UniqueCache.for_testing = False
-        _clean_cache(self.space)
 
 
 all_names = ', '.join(Module.interpleveldefs.keys())
diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py 
b/pypy/module/_cffi_backend/test/test_ffi_obj.py
--- a/pypy/module/_cffi_backend/test/test_ffi_obj.py
+++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py
@@ -1,5 +1,23 @@
+from pypy.module._cffi_backend import newtype
 from pypy.module._cffi_backend.newtype import _clean_cache
 
+
+class TestFFIObj:
+    spaceconfig = dict(usemodules=('_cffi_backend', 'array'))
+
+    def teardown_method(self, meth):
+        _clean_cache(self.space)
+
+    def test_new_function_type_during_translation(self):
+        space = self.space
+        BInt = newtype.new_primitive_type(space, "int")
+        BFunc = newtype.new_function_type(space, space.wrap([BInt]), BInt)
+        assert BFunc is 
newtype.new_function_type(space,space.wrap([BInt]),BInt)
+        unique_cache = space.fromcache(newtype.UniqueCache)
+        unique_cache._cleanup_()
+        assert BFunc is 
newtype.new_function_type(space,space.wrap([BInt]),BInt)
+
+
 class AppTestFFIObj:
     spaceconfig = dict(usemodules=('_cffi_backend', 'array'))
 
diff --git a/pypy/module/_multiprocessing/__init__.py 
b/pypy/module/_multiprocessing/__init__.py
--- a/pypy/module/_multiprocessing/__init__.py
+++ b/pypy/module/_multiprocessing/__init__.py
@@ -5,7 +5,6 @@
 class Module(MixedModule):
 
     interpleveldefs = {
-        'Connection'      : 'interp_connection.W_FileConnection',
         'SemLock'         : 'interp_semaphore.W_SemLock',
         'sem_unlink'      : 'interp_semaphore.semaphore_unlink',
         'address_of_buffer' : 'interp_memory.address_of_buffer',
@@ -15,12 +14,5 @@
     }
 
     if sys.platform == 'win32':
-        interpleveldefs['PipeConnection'] = \
-            'interp_connection.W_PipeConnection'
         interpleveldefs['win32'] = 'interp_win32.win32_namespace(space)'
         del interpleveldefs['sem_unlink']
-
-    def init(self, space):
-        MixedModule.init(self, space)
-        from pypy.module._multiprocessing.interp_connection import State
-        space.fromcache(State).init(space)
diff --git a/pypy/module/_multiprocessing/interp_connection.py 
b/pypy/module/_multiprocessing/interp_connection.py
deleted file mode 100644
--- a/pypy/module/_multiprocessing/interp_connection.py
+++ /dev/null
@@ -1,547 +0,0 @@
-import sys
-from errno import EINTR
-
-from rpython.rlib import rpoll, rsocket
-from rpython.rlib.objectmodel import we_are_translated
-from rpython.rlib.rarithmetic import intmask
-from rpython.rtyper.lltypesystem import lltype, rffi
-
-from pypy.interpreter.baseobjspace import W_Root
-from pypy.interpreter.error import OperationError, oefmt, wrap_oserror
-from pypy.interpreter.gateway import (
-    WrappedDefault, interp2app, interpindirect2app, unwrap_spec)
-from pypy.interpreter.typedef import GetSetProperty, TypeDef
-
-READABLE, WRITABLE = range(1, 3)
-PY_SSIZE_T_MAX = sys.maxint
-PY_SSIZE_T_MIN = -sys.maxint - 1
-
-class State(object):
-    def __init__(self, space):
-        pass
-
-    def init(self, space):
-        w_builtins = space.getbuiltinmodule('builtins')
-        w_module = space.call_method(
-            w_builtins, '__import__', space.wrap("multiprocessing"))
-        self.w_BufferTooShort = space.getattr(w_module, 
space.wrap("BufferTooShort"))
-
-        self.w_picklemodule = space.call_method(
-            w_builtins, '__import__', space.wrap("pickle"))
-
-def BufferTooShort(space, w_data):
-    state = space.fromcache(State)
-    if not we_are_translated() and not hasattr(state, 'w_BufferTooShort'):
-        state.init(space)   # xxx for test/test_connection.py
-    w_BufferTooShort = state.w_BufferTooShort
-    return OperationError(w_BufferTooShort, w_data)
-
-def w_handle(space, handle):
-    return space.wrap(rffi.cast(rffi.INTPTR_T, handle))
-
-
-class W_BaseConnection(W_Root):
-    BUFFER_SIZE = 1024
-    buffer = lltype.nullptr(rffi.CCHARP.TO)
-
-    def __init__(self, space, flags):
-        self.flags = flags
-        self.buffer = lltype.malloc(rffi.CCHARP.TO, self.BUFFER_SIZE,
-                                    flavor='raw')
-        self.register_finalizer(space)
-
-    def _finalize_(self):
-        buf = self.buffer
-        if buf:
-            self.buffer = lltype.nullptr(rffi.CCHARP.TO)
-            lltype.free(buf, flavor='raw')
-        try:
-            self.do_close()
-        except OSError:
-            pass
-
-    # Abstract methods
-    def do_close(self):
-        raise NotImplementedError
-    def is_valid(self):
-        return False
-    def do_send_string(self, space, buf, offset, size):
-        raise NotImplementedError
-    def do_recv_string(self, space, buflength, maxlength):
-        raise NotImplementedError
-    def do_poll(self, space, timeout):
-        raise NotImplementedError
-
-    def close(self):
-        self.do_close()
-
-    def closed_get(self, space):
-        return space.newbool(not self.is_valid())
-    def readable_get(self, space):
-        return space.newbool(bool(self.flags & READABLE))
-    def writable_get(self, space):
-        return space.newbool(bool(self.flags & WRITABLE))
-
-    def _repr(self, space, handle):
-        index = self.flags - 1
-        conn_type = [u"read-only", u"write-only", u"read-write"][index]
-        return space.wrap(u"<%s %s, handle %d>" % (
-                conn_type, space.type(self).getname(space), handle))
-
-    def descr_repr(self, space):
-        raise NotImplementedError
-
-    def _check_readable(self, space):
-        if not self.flags & READABLE:
-            raise oefmt(space.w_IOError, "connection is write-only")
-    def _check_writable(self, space):
-        if not self.flags & WRITABLE:
-            raise oefmt(space.w_IOError, "connection is read-only")
-
-    @unwrap_spec(offset='index', size='index')
-    def send_bytes(self, space, w_buf, offset=0, size=PY_SSIZE_T_MIN):
-        buf = space.getarg_w('s*', w_buf).as_str()
-        length = len(buf)
-        self._check_writable(space)
-        if offset < 0:
-            raise oefmt(space.w_ValueError, "offset is negative")
-        if length < offset:
-            raise oefmt(space.w_ValueError, "buffer length < offset")
-
-        if size == PY_SSIZE_T_MIN:
-            size = length - offset
-        elif size < 0:
-            raise oefmt(space.w_ValueError, "size is negative")
-        elif offset + size > length:
-            raise oefmt(space.w_ValueError, "buffer length > offset + size")
-
-        self.do_send_string(space, buf, offset, size)
-
-    @unwrap_spec(maxlength='index')
-    def recv_bytes(self, space, maxlength=PY_SSIZE_T_MAX):
-        self._check_readable(space)
-        if maxlength < 0:
-            raise oefmt(space.w_ValueError, "maxlength < 0")
-
-        res, newbuf = self.do_recv_string(
-            space, self.BUFFER_SIZE, maxlength)
-        try:
-            if newbuf:
-                return space.newbytes(rffi.charpsize2str(newbuf, res))
-            else:
-                return space.newbytes(rffi.charpsize2str(self.buffer, res))
-        finally:
-            if newbuf:
-                rffi.free_charp(newbuf)
-
-    @unwrap_spec(offset='index')
-    def recv_bytes_into(self, space, w_buffer, offset=0):
-        rwbuffer = space.writebuf_w(w_buffer)
-        length = rwbuffer.getlength()
-
-        res, newbuf = self.do_recv_string(
-            space, length - offset, PY_SSIZE_T_MAX)
-        try:
-            if newbuf:
-                raise BufferTooShort(space, space.newbytes(
-                    rffi.charpsize2str(newbuf, res)))
-            rwbuffer.setslice(offset, rffi.charpsize2str(self.buffer, res))
-        finally:
-            if newbuf:
-                rffi.free_charp(newbuf)
-
-        return space.wrap(res)
-
-    def send(self, space, w_obj):
-        self._check_writable(space)
-
-        w_picklemodule = space.fromcache(State).w_picklemodule
-        w_protocol = space.getattr(
-            w_picklemodule, space.wrap("HIGHEST_PROTOCOL"))
-        w_pickled = space.call_method(
-            w_picklemodule, "dumps", w_obj, w_protocol)
-
-        buf = space.str_w(w_pickled)
-        self.do_send_string(space, buf, 0, len(buf))
-
-    def recv(self, space):
-        self._check_readable(space)
-
-        res, newbuf = self.do_recv_string(
-            space, self.BUFFER_SIZE, PY_SSIZE_T_MAX)
-        try:
-            if newbuf:
-                w_received = space.newbytes(rffi.charpsize2str(newbuf, res))
-            else:
-                w_received = space.newbytes(rffi.charpsize2str(self.buffer, 
res))
-        finally:
-            if newbuf:
-                rffi.free_charp(newbuf)
-
-        w_builtins = space.getbuiltinmodule('builtins')
-        w_picklemodule = space.fromcache(State).w_picklemodule
-        w_unpickled = space.call_method(
-            w_picklemodule, "loads", w_received)
-
-        return w_unpickled
-
-    @unwrap_spec(w_timeout=WrappedDefault(0.0))
-    def poll(self, space, w_timeout):
-        self._check_readable(space)
-        if space.is_w(w_timeout, space.w_None):
-            timeout = -1.0 # block forever
-        else:
-            timeout = space.float_w(w_timeout)
-            if timeout < 0.0:
-                timeout = 0.0
-        return space.newbool(self.do_poll(space, timeout))
-
-W_BaseConnection.typedef = TypeDef(
-    'BaseConnection',
-    __repr__ = interpindirect2app(W_BaseConnection.descr_repr),
-    closed = GetSetProperty(W_BaseConnection.closed_get),
-    readable = GetSetProperty(W_BaseConnection.readable_get),
-    writable = GetSetProperty(W_BaseConnection.writable_get),
-
-    send_bytes = interp2app(W_BaseConnection.send_bytes),
-    recv_bytes = interp2app(W_BaseConnection.recv_bytes),
-    recv_bytes_into = interp2app(W_BaseConnection.recv_bytes_into),
-    send = interp2app(W_BaseConnection.send),
-    recv = interp2app(W_BaseConnection.recv),
-    poll = interp2app(W_BaseConnection.poll),
-    close = interp2app(W_BaseConnection.close),
-    )
-
-class W_FileConnection(W_BaseConnection):
-    INVALID_HANDLE_VALUE = -1
-    fd = INVALID_HANDLE_VALUE
-
-    if sys.platform == 'win32':
-        def WRITE(self, data):
-            from rpython.rlib._rsocket_rffi import send, geterrno
-            length = send(self.fd, data, len(data), 0)
-            if length < 0:
-                raise WindowsError(geterrno(), "send")
-            return length
-        def READ(self, size):
-            from rpython.rlib._rsocket_rffi import socketrecv, geterrno
-            with rffi.scoped_alloc_buffer(size) as buf:
-                length = socketrecv(self.fd, buf.raw, buf.size, 0)
-                if length < 0:
-                    raise WindowsError(geterrno(), "recv")
-                return buf.str(length)
-        def CLOSE(self):
-            from rpython.rlib._rsocket_rffi import socketclose
-            socketclose(self.fd)
-    else:
-        def WRITE(self, data):
-            import os
-            return os.write(self.fd, data)
-        def READ(self, length):
-            import os
-            return os.read(self.fd, length)
-        def CLOSE(self):
-            import os
-            try:
-                os.close(self.fd)
-            except OSError:
-                pass
-
-    def __init__(self, space, fd, flags):
-        if fd == self.INVALID_HANDLE_VALUE or fd < 0:
-            raise oefmt(space.w_IOError, "invalid handle %d", fd)
-        W_BaseConnection.__init__(self, space, flags)
-        self.fd = fd
-
-    @unwrap_spec(fd=int, readable=bool, writable=bool)
-    def descr_new_file(space, w_subtype, fd, readable=True, writable=True):
-        flags = (readable and READABLE) | (writable and WRITABLE)
-
-        self = space.allocate_instance(W_FileConnection, w_subtype)
-        W_FileConnection.__init__(self, space, fd, flags)
-        return space.wrap(self)
-
-    def descr_repr(self, space):
-        return self._repr(space, self.fd)
-
-    def fileno(self, space):
-        return space.wrap(self.fd)
-
-    def is_valid(self):
-        return self.fd != self.INVALID_HANDLE_VALUE
-
-    def do_close(self):
-        if self.is_valid():
-            self.CLOSE()
-            self.fd = self.INVALID_HANDLE_VALUE
-
-    def do_send_string(self, space, buf, offset, size):
-        # Since str2charp copies the buf anyway, always combine the
-        # "header" and the "body" of the message and send them at once.
-        message = lltype.malloc(rffi.CCHARP.TO, size + 4, flavor='raw')
-        try:
-            length = rffi.r_uint(rsocket.htonl(
-                    rffi.cast(lltype.Unsigned, size)))
-            rffi.cast(rffi.UINTP, message)[0] = length
-            i = size - 1
-            while i >= 0:
-                message[4 + i] = buf[offset + i]
-                i -= 1
-            self._sendall(space, message, size + 4)
-        finally:
-            lltype.free(message, flavor='raw')
-
-    def do_recv_string(self, space, buflength, maxlength):
-        with lltype.scoped_alloc(rffi.CArrayPtr(rffi.UINT).TO, 1) as 
length_ptr:
-            self._recvall(space, rffi.cast(rffi.CCHARP, length_ptr), 4)
-            length = intmask(rsocket.ntohl(
-                    rffi.cast(lltype.Unsigned, length_ptr[0])))
-        if length > maxlength: # bad message, close connection
-            self.flags &= ~READABLE
-            if self.flags == 0:
-                self.close()
-            raise oefmt(space.w_IOError, "bad message length")
-
-        if length <= buflength:
-            self._recvall(space, self.buffer, length)
-            return length, lltype.nullptr(rffi.CCHARP.TO)
-        else:
-            newbuf = lltype.malloc(rffi.CCHARP.TO, length, flavor='raw')
-            self._recvall(space, newbuf, length)
-            return length, newbuf
-
-    def _sendall(self, space, message, size):
-        while size > 0:
-            # XXX inefficient
-            data = rffi.charpsize2str(message, size)
-            try:
-                count = self.WRITE(data)
-            except OSError as e:
-                if e.errno == EINTR:
-                    space.getexecutioncontext().checksignals()
-                    continue
-                raise wrap_oserror(space, e)
-            size -= count
-            message = rffi.ptradd(message, count)
-
-    def _recvall(self, space, buf, length):
-        length = intmask(length)
-        remaining = length
-        while remaining > 0:
-            try:
-                data = self.READ(remaining)
-            except OSError as e:
-                if e.errno == EINTR:
-                    space.getexecutioncontext().checksignals()
-                    continue
-                raise wrap_oserror(space, e)
-            count = len(data)
-            if count == 0:
-                if remaining == length:
-                    raise OperationError(space.w_EOFError, space.w_None)
-                else:
-                    raise oefmt(space.w_IOError,
-                                "got end of file during message")
-            # XXX inefficient
-            for i in range(count):
-                buf[i] = data[i]
-            remaining -= count
-            buf = rffi.ptradd(buf, count)
-
-    if sys.platform == 'win32':
-        def _check_fd(self):
-            return self.fd >= 0
-    else:
-        def _check_fd(self):
-            return self.fd >= 0 and self.fd < rpoll.FD_SETSIZE
-
-    def do_poll(self, space, timeout):
-        if not self._check_fd():
-            raise oefmt(space.w_IOError, "handle out of range in select()")
-        r, w, e = rpoll.select([self.fd], [], [], timeout, handle_eintr=True)
-        return bool(r)
-
-W_FileConnection.typedef = TypeDef(
-    '_multiprocessing.Connection', W_BaseConnection.typedef,
-    __new__ = interp2app(W_FileConnection.descr_new_file.im_func),
-    fileno = interp2app(W_FileConnection.fileno),
-)
-
-class W_PipeConnection(W_BaseConnection):
-    if sys.platform == 'win32':
-        from rpython.rlib.rwin32 import INVALID_HANDLE_VALUE
-
-    def __init__(self, space, handle, flags):
-        W_BaseConnection.__init__(self, space, flags)
-        self.handle = handle
-
-    @unwrap_spec(readable=bool, writable=bool)
-    def descr_new_pipe(space, w_subtype, w_handle, readable=True,
-                       writable=True):
-        from pypy.module._multiprocessing.interp_win32 import handle_w
-        handle = handle_w(space, w_handle)
-        flags = (readable and READABLE) | (writable and WRITABLE)
-
-        self = space.allocate_instance(W_PipeConnection, w_subtype)
-        W_PipeConnection.__init__(self, space, handle, flags)
-        return space.wrap(self)
-
-    def descr_repr(self, space):
-        return self._repr(space, rffi.cast(rffi.INTPTR_T, self.handle))
-
-    def is_valid(self):
-        return self.handle != self.INVALID_HANDLE_VALUE
-
-    def fileno(self, space):
-        return w_handle(space, self.handle)
-
-    def do_close(self):
-        from rpython.rlib.rwin32 import CloseHandle
-        if self.is_valid():
-            CloseHandle(self.handle)
-            self.handle = self.INVALID_HANDLE_VALUE
-
-    def do_send_string(self, space, buf, offset, size):
-        from pypy.module._multiprocessing.interp_win32 import (
-            _WriteFile, ERROR_NO_SYSTEM_RESOURCES)
-        from rpython.rlib import rwin32
-
-        with rffi.scoped_view_charp(buf) as charp:
-            written_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1,
-                                        flavor='raw')
-            try:
-                result = _WriteFile(
-                    self.handle, rffi.ptradd(charp, offset),
-                    size, written_ptr, rffi.NULL)
-
-                if (result == 0 and
-                    rwin32.GetLastError_saved() == ERROR_NO_SYSTEM_RESOURCES):
-                    raise oefmt(space.w_ValueError,
-                                "Cannot send %d bytes over connection", size)
-            finally:
-                lltype.free(written_ptr, flavor='raw')
-
-    def do_recv_string(self, space, buflength, maxlength):
-        from pypy.module._multiprocessing.interp_win32 import (
-            _ReadFile, _PeekNamedPipe, ERROR_BROKEN_PIPE, ERROR_MORE_DATA)
-        from rpython.rlib import rwin32
-        from pypy.interpreter.error import wrap_windowserror
-
-        read_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1,
-                                 flavor='raw')
-        left_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1,
-                                 flavor='raw')
-        try:
-            result = _ReadFile(self.handle,
-                               self.buffer, min(self.BUFFER_SIZE, buflength),
-                               read_ptr, rffi.NULL)
-            if result:
-                return intmask(read_ptr[0]), lltype.nullptr(rffi.CCHARP.TO)
-
-            err = rwin32.GetLastError_saved()
-            if err == ERROR_BROKEN_PIPE:
-                raise OperationError(space.w_EOFError, space.w_None)
-            elif err != ERROR_MORE_DATA:
-                raise wrap_windowserror(space, WindowsError(err, "_ReadFile"))
-
-            # More data...
-            if not _PeekNamedPipe(self.handle, rffi.NULL, 0,
-                                  lltype.nullptr(rwin32.LPDWORD.TO),
-                                  lltype.nullptr(rwin32.LPDWORD.TO),
-                                  left_ptr):
-                raise wrap_windowserror(space, rwin32.lastSavedWindowsError())
-
-            length = intmask(read_ptr[0] + left_ptr[0])
-            if length > maxlength: # bad message, close connection
-                self.flags &= ~READABLE
-                if self.flags == 0:
-                    self.close()
-                raise oefmt(space.w_IOError, "bad message length")
-
-            newbuf = lltype.malloc(rffi.CCHARP.TO, length + 1, flavor='raw')
-            for i in range(read_ptr[0]):
-                newbuf[i] = self.buffer[i]
-
-            result = _ReadFile(self.handle,
-                               rffi.ptradd(newbuf, read_ptr[0]), left_ptr[0],
-                               read_ptr, rffi.NULL)
-            if not result:
-                rffi.free_charp(newbuf)
-                raise wrap_windowserror(space, rwin32.lastSavedWindowsError())
-
-            assert read_ptr[0] == left_ptr[0]
-            return length, newbuf
-        finally:
-            lltype.free(read_ptr, flavor='raw')
-            lltype.free(left_ptr, flavor='raw')
-
-    def do_poll(self, space, timeout):
-        from pypy.module._multiprocessing.interp_win32 import (
-            _PeekNamedPipe, _GetTickCount, _Sleep)
-        from rpython.rlib import rwin32
-        from pypy.interpreter.error import wrap_windowserror
-        bytes_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1,
-                                 flavor='raw')
-        try:
-            if not _PeekNamedPipe(self.handle, rffi.NULL, 0,
-                                  lltype.nullptr(rwin32.LPDWORD.TO),
-                                  bytes_ptr,
-                                  lltype.nullptr(rwin32.LPDWORD.TO)):
-                raise wrap_windowserror(space, rwin32.lastSavedWindowsError())
-            bytes = bytes_ptr[0]
-        finally:
-            lltype.free(bytes_ptr, flavor='raw')
-
-        if timeout == 0.0:
-            return bytes > 0
-
-        block = timeout < 0
-        if not block:
-            # XXX does not check for overflow
-            deadline = intmask(_GetTickCount()) + int(1000 * timeout + 0.5)
-        else:
-            deadline = 0
-
-        _Sleep(0)
-
-        delay = 1
-        while True:
-            bytes_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1,
-                                     flavor='raw')
-            try:
-                if not _PeekNamedPipe(self.handle, rffi.NULL, 0,
-                                      lltype.nullptr(rwin32.LPDWORD.TO),
-                                      bytes_ptr,
-                                      lltype.nullptr(rwin32.LPDWORD.TO)):
-                    raise wrap_windowserror(space,
-                                            rwin32.lastSavedWindowsError())
-                bytes = bytes_ptr[0]
-            finally:
-                lltype.free(bytes_ptr, flavor='raw')
-
-            if bytes > 0:
-                return True
-
-            if not block:
-                now = intmask(_GetTickCount())
-                if now > deadline:
-                    return False
-                diff = deadline - now
-                if delay > diff:
-                    delay = diff
-            else:
-                delay += 1
-
-            if delay >= 20:
-                delay = 20
-            _Sleep(delay)
-
-            # check for signals
-            # PyErr_CheckSignals()
-
-if sys.platform == 'win32':
-    W_PipeConnection.typedef = TypeDef(
-        '_multiprocessing.PipeConnection', W_BaseConnection.typedef,
-        __new__ = interp2app(W_PipeConnection.descr_new_pipe.im_func),
-        fileno = interp2app(W_PipeConnection.fileno),
-    )
diff --git a/pypy/module/_multiprocessing/interp_semaphore.py 
b/pypy/module/_multiprocessing/interp_semaphore.py
--- a/pypy/module/_multiprocessing/interp_semaphore.py
+++ b/pypy/module/_multiprocessing/interp_semaphore.py
@@ -13,9 +13,9 @@
 from pypy.interpreter.error import oefmt, wrap_oserror
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import GetSetProperty, TypeDef
-from pypy.module._multiprocessing.interp_connection import w_handle
 
 RECURSIVE_MUTEX, SEMAPHORE = range(2)
+sys_platform = sys.platform
 
 if sys.platform == 'win32':
     from rpython.rlib import rwin32
@@ -216,9 +216,10 @@
 
     def semaphore_unlink(space, w_name):
         name = space.str_w(w_name)
-        res = _sem_unlink(name)
-        if res < 0:
-            raise oefmt(space.w_OSError, "sem unlink failed with errno: %d", 
rposix.get_saved_errno())
+        try:
+            sem_unlink(name)
+        except OSError as e:
+            raise wrap_oserror(space, e)
 
 class CounterState:
     def __init__(self, space):
@@ -331,6 +332,11 @@
         rgc.add_memory_pressure(SEM_T_SIZE)
         return sem
 
+    def reopen_semaphore(name):
+        sem = sem_open(name, 0, 0600, 0)
+        rgc.add_memory_pressure(SEM_T_SIZE)
+        return sem
+
     def delete_semaphore(handle):
         _sem_close_no_errno(handle)
 
@@ -454,7 +460,8 @@
         return space.newint(self.maxvalue)
 
     def handle_get(self, space):
-        return w_handle(space, self.handle)
+        h = rffi.cast(rffi.INTPTR_T, self.handle)
+        return space.wrap(h)
 
     def get_count(self, space):
         return space.wrap(self.count)
@@ -521,8 +528,18 @@
     @unwrap_spec(kind=int, maxvalue=int)
     def rebuild(space, w_cls, w_handle, kind, maxvalue, w_name):
         name = space.str_or_None_w(w_name)
+        #
+        if sys_platform != 'win32' and name is not None:
+            # like CPython, in this case ignore 'w_handle'
+            try:
+                handle = reopen_semaphore(name)
+            except OSError as e:
+                raise wrap_oserror(space, e)
+        else:
+            handle = handle_w(space, w_handle)
+        #
         self = space.allocate_instance(W_SemLock, w_cls)
-        self.__init__(space, handle_w(space, w_handle), kind, maxvalue, name)
+        self.__init__(space, handle, kind, maxvalue, name)
         return space.wrap(self)
 
     def enter(self, space):
diff --git a/pypy/module/_multiprocessing/test/test_connection.py 
b/pypy/module/_multiprocessing/test/test_connection.py
deleted file mode 100644
--- a/pypy/module/_multiprocessing/test/test_connection.py
+++ /dev/null
@@ -1,200 +0,0 @@
-import py
-import sys
-from pypy.interpreter.gateway import interp2app, W_Root
-
-class TestImport:
-    def test_simple(self):
-        from pypy.module._multiprocessing import interp_connection
-        from pypy.module._multiprocessing import interp_semaphore
-
-class AppTestBufferTooShort:
-    spaceconfig = {'usemodules': ['_multiprocessing', 'thread', 'signal',
-                                  'select', 'struct', 'binascii',
-                                  '_posixsubprocess']}
-    if sys.platform == 'win32':
-        spaceconfig['usemodules'].append('_rawffi')
-    else:
-        spaceconfig['usemodules'].append('fcntl')
-
-
-    def setup_class(cls):
-        if cls.runappdirect:
-            def raiseBufferTooShort(self, data):
-                import multiprocessing
-                raise multiprocessing.BufferTooShort(data)
-            cls.w_raiseBufferTooShort = raiseBufferTooShort
-        else:
-            from pypy.module._multiprocessing import interp_connection
-            def raiseBufferTooShort(space, w_data):
-                raise interp_connection.BufferTooShort(space, w_data)
-            cls.w_raiseBufferTooShort = cls.space.wrap(
-                interp2app(raiseBufferTooShort))
-
-    def test_exception(self):
-        import multiprocessing
-        try:
-            self.raiseBufferTooShort("data")
-        except multiprocessing.BufferTooShort as e:
-            assert isinstance(e, multiprocessing.ProcessError)
-            assert e.args == ("data",)
-
-class BaseConnectionTest(object):
-    def test_connection(self):
-        rhandle, whandle = self.make_pair()
-
-        whandle.send_bytes(b"abc")
-        assert rhandle.recv_bytes(100) == b"abc"
-
-        obj = [1, 2.0, "hello"]
-        whandle.send(obj)
-        obj2 = rhandle.recv()
-        assert obj == obj2
-
-    def test_poll(self):
-        rhandle, whandle = self.make_pair()
-
-        assert rhandle.poll() == False
-        assert rhandle.poll(1) == False
-        whandle.send(1)
-        import time; time.sleep(0.1)  # give it time to arrive :-)
-        assert rhandle.poll() == True
-        assert rhandle.poll(None) == True
-        assert rhandle.recv() == 1
-        assert rhandle.poll() == False
-        raises(IOError, whandle.poll)
-
-    def test_read_into(self):
-        import array, multiprocessing
-        rhandle, whandle = self.make_pair()
-
-        obj = [1, 2.0, "hello"]
-        whandle.send(obj)
-        buffer = array.array('b', [0]*10)
-        raises(multiprocessing.BufferTooShort, rhandle.recv_bytes_into, buffer)
-        assert rhandle.readable
-
-class AppTestWinpipeConnection(BaseConnectionTest):
-    spaceconfig = {
-        "usemodules": [
-            '_multiprocessing', 'thread', 'signal', 'struct', 'array',
-            'itertools', '_socket', 'binascii',
-        ]
-    }
-    if sys.platform == 'win32':
-        spaceconfig['usemodules'].append('_rawffi')
-
-    def setup_class(cls):
-        if sys.platform != "win32":
-            py.test.skip("win32 only")
-
-        if not cls.runappdirect:
-            space = cls.space
-            # stubs for some modules,
-            # just for multiprocessing to import correctly on Windows
-            w_modules = space.sys.get('modules')
-            space.setitem(w_modules, space.wrap('msvcrt'), space.sys)
-        else:
-            import _multiprocessing
-
-    def w_make_pair(self):
-        import multiprocessing
-
-        return multiprocessing.Pipe(duplex=False)
-
-
-class AppTestSocketConnection(BaseConnectionTest):
-    spaceconfig = {
-        "usemodules": [
-            '_multiprocessing', 'thread', 'signal', 'struct', 'array',
-            '_socket', 'binascii', 'select', '_posixsubprocess']
-    }
-    if sys.platform == 'win32':
-        spaceconfig['usemodules'].append('_rawffi')
-    else:
-        spaceconfig['usemodules'].append('fcntl')
-
-    def setup_class(cls):
-        cls.w_connections = cls.space.newlist([])
-
-    def w_socketpair(self):
-        "A socket.socketpair() that works on Windows"
-        import errno
-        import socket
-
-        serverSocket = socket.socket()
-        serverSocket.bind(('127.0.0.1', 0))
-        serverSocket.listen(1)
-
-        client = socket.socket()
-        client.setblocking(False)
-        try:
-            client.connect(('127.0.0.1', serverSocket.getsockname()[1]))
-        except socket.error as e:
-            assert e.args[0] in (errno.EINPROGRESS, errno.EWOULDBLOCK)
-        server, addr = serverSocket.accept()
-
-        # keep sockets alive during the test
-        self.connections.append(server)
-        self.connections.append(client)
-
-        return server.fileno(), client.fileno()
-
-    def w_make_pair(self):
-        import _multiprocessing
-
-        fd1, fd2 = self.socketpair()
-        rhandle = _multiprocessing.Connection(fd1, writable=False)
-        whandle = _multiprocessing.Connection(fd2, readable=False)
-        self.connections.append(rhandle)
-        self.connections.append(whandle)
-        return rhandle, whandle
-
-    def teardown_method(self, func):
-        # Work hard to close all sockets and connections now!
-        # since the fd is probably already closed, another unrelated
-        # part of the program will probably reuse it;
-        # And any object forgotten here will close it on destruction...
-        try:
-            w_connections = self.w_connections
-        except AttributeError:
-            return
-        space = self.space
-        for c in space.unpackiterable(w_connections):
-            if isinstance(c, W_Root):
-                space.call_method(c, "close")
-            else:
-                c.close()
-        space.delslice(w_connections, space.wrap(0), space.wrap(100))
-
-    def test_bad_fd(self):
-        import _multiprocessing
-
-        raises(IOError, _multiprocessing.Connection, -1)
-        raises(IOError, _multiprocessing.Connection, -15)
-
-    def test_byte_order(self):
-        import socket
-        if not 'fromfd' in dir(socket):
-            skip('No fromfd in socket')
-        # The exact format of net strings (length in network byte
-        # order) is important for interoperation with others
-        # implementations.
-        rhandle, whandle = self.make_pair()
-        whandle.send_bytes(b"abc")
-        whandle.send_bytes(b"defg")
-        sock = socket.fromfd(rhandle.fileno(),
-                             socket.AF_INET, socket.SOCK_STREAM)
-        data1 = sock.recv(7)
-        assert data1 == b'\x00\x00\x00\x03abc'
-        data2 = sock.recv(8)
-        assert data2 == b'\x00\x00\x00\x04defg'
-
-    def test_repr(self):
-        import _multiprocessing, os
-        fd = os.dup(1)     # closed by Connection.__del__
-        c = _multiprocessing.Connection(fd)
-        assert repr(c) == '<read-write Connection, handle %d>' % fd
-        if hasattr(_multiprocessing, 'PipeConnection'):
-            fd = os.dup(1)     # closed by PipeConnection.__del__
-            c = _multiprocessing.PipeConnection(fd)
-            assert repr(c) == '<read-write PipeConnection, handle %d>' % fd
diff --git a/pypy/module/_multiprocessing/test/test_semaphore.py 
b/pypy/module/_multiprocessing/test/test_semaphore.py
--- a/pypy/module/_multiprocessing/test/test_semaphore.py
+++ b/pypy/module/_multiprocessing/test/test_semaphore.py
@@ -22,10 +22,13 @@
     @py.test.mark.skipif("sys.platform == 'win32'")
     def test_sem_unlink(self):
         from _multiprocessing import sem_unlink
+        import errno
         try:
             sem_unlink("non-existent")
-        except OSError:
-            pass
+        except OSError as e:
+            assert e.errno in (errno.ENOENT, errno.EINVAL)
+        else:
+            assert 0, "should have raised"
 
     def test_semaphore(self):
         from _multiprocessing import SemLock
@@ -99,14 +102,20 @@
         assert res == False
 
     def test_semaphore_rebuild(self):
-        from _multiprocessing import SemLock
+        from _multiprocessing import SemLock, sem_unlink
         kind = self.SEMAPHORE
         value = 1
         maxvalue = 1
-        sem = SemLock(kind, value, maxvalue, "4", unlink=True)
-
-        sem2 = SemLock._rebuild(sem.handle, kind, value, "10")
-        assert sem.handle == sem2.handle
+        sem = SemLock(kind, value, maxvalue, "4.2", unlink=False)
+        try:
+            sem2 = SemLock._rebuild(-1, kind, value, "4.2")
+            #assert sem.handle != sem2.handle---even though they come
+            # from different calls to sem_open(), on Linux at least,
+            # they are the same pointer
+            sem2 = SemLock._rebuild(sem.handle, kind, value, None)
+            assert sem.handle == sem2.handle
+        finally:
+            sem_unlink("4.2")
 
     def test_semaphore_contextmanager(self):
         from _multiprocessing import SemLock
diff --git a/pypy/module/_weakref/interp__weakref.py 
b/pypy/module/_weakref/interp__weakref.py
--- a/pypy/module/_weakref/interp__weakref.py
+++ b/pypy/module/_weakref/interp__weakref.py
@@ -194,6 +194,15 @@
         W_WeakrefBase.__init__(self, space, w_obj, w_callable)
         self.w_hash = None
 
+    def _cleanup_(self):
+        # When a prebuilt weakref is frozen inside a translation, if
+        # this weakref has got an already-cached w_hash, then throw it
+        # away.  That's because the hash value will change after
+        # translation.  It will be recomputed the first time we ask for
+        # it.  Note that such a frozen weakref, if not dead, will point
+        # to a frozen object, so it will never die.
+        self.w_hash = None
+
     def descr__init__weakref(self, space, w_obj, w_callable=None,
                              __args__=None):
         if __args__.arguments_w:
diff --git a/pypy/module/array/interp_array.py 
b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -141,12 +141,120 @@
                                         hints={'nolength': True}))
 
 class W_ArrayBase(W_Root):
-    _attrs_ = ('space', 'len', 'allocated', '_lifeline_') # no buffer
+    _attrs_ = ('space', 'len', 'allocated', '_lifeline_', '_buffer')
 
     def __init__(self, space):
         self.space = space
         self.len = 0
         self.allocated = 0
+        self._buffer = lltype.nullptr(rffi.CCHARP.TO)
+
+    @rgc.must_be_light_finalizer
+    def __del__(self):
+        if self._buffer:
+            lltype.free(self._buffer, flavor='raw')
+
+    def setlen(self, size, zero=False, overallocate=True):
+        if size > 0:
+            if size > self.allocated or size < self.allocated / 2:
+                if overallocate:
+                    if size < 9:
+                        some = 3
+                    else:
+                        some = 6
+                    some += size >> 3
+                else:
+                    some = 0
+                self.allocated = size + some
+                byte_size = self.allocated * self.itemsize
+                if zero:
+                    new_buffer = lltype.malloc(
+                        rffi.CCHARP.TO, byte_size, flavor='raw',
+                        add_memory_pressure=True, zero=True)
+                else:
+                    new_buffer = lltype.malloc(
+                        rffi.CCHARP.TO, byte_size, flavor='raw',
+                        add_memory_pressure=True)
+                    copy_bytes = min(size, self.len) * self.itemsize
+                    rffi.c_memcpy(rffi.cast(rffi.VOIDP, new_buffer),
+                                  rffi.cast(rffi.VOIDP, self._buffer),
+                                  copy_bytes)
+            else:
+                self.len = size
+                return
+        else:
+            assert size == 0
+            self.allocated = 0
+            new_buffer = lltype.nullptr(rffi.CCHARP.TO)
+
+        if self._buffer:
+            lltype.free(self._buffer, flavor='raw')
+        self._buffer = new_buffer
+        self.len = size
+
+    def _fromiterable(self, w_seq):
+        # used by fromsequence().
+        # a more careful case if w_seq happens to be a very large
+        # iterable: don't copy the items into some intermediate list
+        w_iterator = self.space.iter(w_seq)
+        tp = self.space.type(w_iterator)
+        while True:
+            unpack_driver.jit_merge_point(selfclass=self.__class__,
+                                          tp=tp, self=self,
+                                          w_iterator=w_iterator)
+            space = self.space
+            try:
+                w_item = space.next(w_iterator)
+            except OperationError as e:
+                if not e.match(space, space.w_StopIteration):
+                    raise
+                break  # done
+            self.descr_append(space, w_item)
+
+    def _charbuf_start(self):
+        return self._buffer
+
+    def _buffer_as_unsigned(self):
+        return rffi.cast(lltype.Unsigned, self._buffer)
+
+    def _charbuf_stop(self):
+        keepalive_until_here(self)
+
+    def delitem(self, space, i, j):
+        if i < 0:
+            i += self.len
+        if i < 0:
+            i = 0
+        if j < 0:
+            j += self.len
+        if j < 0:
+            j = 0
+        if j > self.len:
+            j = self.len
+        if i >= j:
+            return None
+        oldbuffer = self._buffer
+        self._buffer = lltype.malloc(rffi.CCHARP.TO,
+            (self.len - (j - i)) * self.itemsize, flavor='raw',
+            add_memory_pressure=True)
+        if i:
+            rffi.c_memcpy(
+                rffi.cast(rffi.VOIDP, self._buffer),
+                rffi.cast(rffi.VOIDP, oldbuffer),
+                i * self.itemsize
+            )
+        if j < self.len:
+            rffi.c_memcpy(
+                rffi.cast(rffi.VOIDP, rffi.ptradd(self._buffer,
+                                                  i * self.itemsize)),
+                rffi.cast(rffi.VOIDP, rffi.ptradd(oldbuffer,
+                                                  j * self.itemsize)),
+                (self.len - j) * self.itemsize
+            )
+        self.len -= j - i
+        self.allocated = self.len
+        if oldbuffer:
+            lltype.free(oldbuffer, flavor='raw')
 
     def buffer_w_ex(self, space, flags):
         return ArrayBuffer(self, False), self.typecode, self.itemsize
@@ -170,14 +278,24 @@
 
         Return number of occurrences of x in the array.
         """
-        raise NotImplementedError
+        cnt = 0
+        for i in range(self.len):
+            # XXX jitdriver
+            w_item = self.w_getitem(space, i)
+            if space.is_true(space.eq(w_item, w_val)):
+                cnt += 1
+        return space.wrap(cnt)
 
     def descr_index(self, space, w_x):
         """ index(x)
 
         Return index of first occurrence of x in the array.
         """
-        raise NotImplementedError
+        for i in range(self.len):
+            w_item = self.w_getitem(space, i)
+            if space.is_true(space.eq(w_item, w_x)):
+                return space.wrap(i)
+        raise oefmt(space.w_ValueError, "array.index(x): x not in list")
 
     def descr_reverse(self, space):
         """ reverse()
@@ -191,7 +309,8 @@
 
         Remove the first occurrence of x in the array.
         """
-        raise NotImplementedError
+        w_idx = self.descr_index(space, w_val)
+        self.descr_pop(space, space.int_w(w_idx))
 
     @unwrap_spec(i=int)
     def descr_pop(self, space, i=-1):
@@ -507,16 +626,102 @@
         return space.newseqiter(self)
 
     def descr_add(self, space, w_other):
-        raise NotImplementedError
+        if (not isinstance(w_other, W_ArrayBase)
+                or w_other.typecode != self.typecode):
+            return space.w_NotImplemented
+        a = self.constructor(space)
+        a.setlen(self.len + w_other.len, overallocate=False)
+        if self.len:
+            rffi.c_memcpy(
+                rffi.cast(rffi.VOIDP, a._buffer),
+                rffi.cast(rffi.VOIDP, self._buffer),
+                self.len * self.itemsize
+            )
+        if w_other.len:
+            rffi.c_memcpy(
+                rffi.cast(rffi.VOIDP, rffi.ptradd(a._buffer,
+                                             self.len * self.itemsize)),
+                rffi.cast(rffi.VOIDP, w_other._buffer),
+                w_other.len * self.itemsize
+            )
+        keepalive_until_here(self)
+        keepalive_until_here(a)
+        return a
 
     def descr_inplace_add(self, space, w_other):
-        raise NotImplementedError
+        if (not isinstance(w_other, W_ArrayBase)
+                or w_other.typecode != self.typecode):
+            return space.w_NotImplemented
+        oldlen = self.len
+        otherlen = w_other.len
+        self.setlen(oldlen + otherlen)
+        if otherlen:
+            rffi.c_memcpy(
+                rffi.cast(rffi.VOIDP, rffi.ptradd(self._buffer,
+                                             oldlen * self.itemsize)),
+                rffi.cast(rffi.VOIDP, w_other._buffer),
+                otherlen * self.itemsize
+            )
+        keepalive_until_here(self)
+        keepalive_until_here(w_other)
+        return self
+
+    def _mul_helper(self, space, w_repeat, is_inplace):
+        try:
+            repeat = space.getindex_w(w_repeat, space.w_OverflowError)
+        except OperationError as e:
+            if e.match(space, space.w_TypeError):
+                return space.w_NotImplemented
+            raise
+        if is_inplace:
+            a = self
+            start = 1
+        else:
+            a = self.constructor(space)
+            start = 0
+        if repeat <= start:
+            if repeat <= 0:
+                a.setlen(0, overallocate=False)
+            return a
+        oldlen = self.len
+        try:
+            newlen = ovfcheck(oldlen * repeat)
+        except OverflowError:
+            raise MemoryError
+        #
+        srcbuf = self._buffer
+        srcsize = self.len * self.itemsize
+        for i in range(srcsize):
+            if srcbuf[i] != '\x00':
+                break
+        else:
+            # the source is entirely zero: initialize the target
+            # with zeroes too
+            a.setlen(newlen, zero=True, overallocate=False)
+            return a
+        #
+        a.setlen(newlen, overallocate=False)
+        srcbuf = self._buffer   # reload this, in case self is a
+        if oldlen == 1:
+            self._repeat_single_item(a, start, repeat)
+        else:
+            dstbuf = a._buffer
+            if start == 1:
+                dstbuf = rffi.ptradd(dstbuf, srcsize)
+            for r in range(start, repeat):
+                rffi.c_memcpy(rffi.cast(rffi.VOIDP, dstbuf),
+                              rffi.cast(rffi.VOIDP, srcbuf),
+                              srcsize)
+                dstbuf = rffi.ptradd(dstbuf, srcsize)
+        keepalive_until_here(self)
+        keepalive_until_here(a)
+        return a
 
     def descr_mul(self, space, w_repeat):
-        raise NotImplementedError
+        return self._mul_helper(space, w_repeat, False)
 
     def descr_inplace_mul(self, space, w_repeat):
-        raise NotImplementedError
+        return self._mul_helper(space, w_repeat, True)
 
     def descr_radd(self, space, w_other):
         return self.descr_add(space, w_other)
@@ -600,6 +805,7 @@
         self.itemtype = itemtype
         self.bytes = rffi.sizeof(itemtype)
         self.arraytype = lltype.Array(itemtype, hints={'nolength': True})
+        self.arrayptrtype = lltype.Ptr(self.arraytype)
         self.unwrap, _, self.convert = unwrap.partition('.')
         self.signed = signed
         self.canoverflow = canoverflow
@@ -694,22 +900,21 @@
         return self.array._charbuf_start()
 
 
+unpack_driver = jit.JitDriver(name='unpack_array',
+                              greens=['selfclass', 'tp'],
+                              reds=['self', 'w_iterator'])
+
 def make_array(mytype):
     W_ArrayBase = globals()['W_ArrayBase']
 
-    unpack_driver = jit.JitDriver(name='unpack_array',
-                                  greens=['tp'],
-                                  reds=['self', 'w_iterator'])
-
     class W_Array(W_ArrayBase):
         itemsize = mytype.bytes
         typecode = mytype.typecode
 
-        _attrs_ = ('space', 'len', 'allocated', '_lifeline_', 'buffer')
+        _attrs_ = W_ArrayBase._attrs_
 
-        def __init__(self, space):
-            W_ArrayBase.__init__(self, space)
-            self.buffer = lltype.nullptr(mytype.arraytype)
+        def get_buffer(self):
+            return rffi.cast(mytype.arrayptrtype, self._buffer)
 
         def item_w(self, w_item):
             space = self.space
@@ -765,46 +970,6 @@
                                          self.space.wrap(msg))
             return result
 
-        @rgc.must_be_light_finalizer
-        def __del__(self):
-            if self.buffer:
-                lltype.free(self.buffer, flavor='raw')
-
-        def setlen(self, size, zero=False, overallocate=True):
-            if size > 0:
-                if size > self.allocated or size < self.allocated / 2:
-                    if overallocate:
-                        if size < 9:
-                            some = 3
-                        else:
-                            some = 6
-                        some += size >> 3
-                    else:
-                        some = 0
-                    self.allocated = size + some
-                    if zero:
-                        new_buffer = lltype.malloc(
-                            mytype.arraytype, self.allocated, flavor='raw',
-                            add_memory_pressure=True, zero=True)
-                    else:
-                        new_buffer = lltype.malloc(
-                            mytype.arraytype, self.allocated, flavor='raw',
-                            add_memory_pressure=True)
-                        for i in range(min(size, self.len)):
-                            new_buffer[i] = self.buffer[i]
-                else:
-                    self.len = size
-                    return
-            else:
-                assert size == 0
-                self.allocated = 0
-                new_buffer = lltype.nullptr(mytype.arraytype)
-
-            if self.buffer:
-                lltype.free(self.buffer, flavor='raw')
-            self.buffer = new_buffer
-            self.len = size
-
         def fromsequence(self, w_seq):
             space = self.space
             oldlen = self.len
@@ -820,20 +985,21 @@
             if lst is not None:
                 self.setlen(oldlen + len(lst))
                 try:
-                    buf = self.buffer
+                    buf = self.get_buffer()
                     for num in lst:
                         buf[newlen] = self.item_from_int_or_float(num)
                         newlen += 1
                 except OperationError:
                     self.setlen(newlen)
                     raise
+                keepalive_until_here(self)
                 return
 
             # this is the common case: w_seq is a list or a tuple
             lst_w = space.listview_no_unpack(w_seq)
             if lst_w is not None:
                 self.setlen(oldlen + len(lst_w))
-                buf = self.buffer
+                buf = self.get_buffer()
                 try:
                     for w_num in lst_w:
                         # note: self.item_w() might invoke arbitrary code.
@@ -844,30 +1010,14 @@
                         buf[newlen] = self.item_w(w_num)
                         newlen += 1
                 except OperationError:
-                    if buf == self.buffer:
+                    if buf == self.get_buffer():
                         self.setlen(newlen)
                     raise
+                keepalive_until_here(self)
                 return
 
             self._fromiterable(w_seq)
 
-        def _fromiterable(self, w_seq):
-            # a more careful case if w_seq happens to be a very large
-            # iterable: don't copy the items into some intermediate list
-            w_iterator = self.space.iter(w_seq)
-            tp = self.space.type(w_iterator)
-            while True:
-                unpack_driver.jit_merge_point(tp=tp, self=self,
-                                              w_iterator=w_iterator)
-                space = self.space
-                try:
-                    w_item = space.next(w_iterator)
-                except OperationError as e:
-                    if not e.match(space, space.w_StopIteration):
-                        raise
-                    break  # done
-                self.descr_append(space, w_item)
-
         def extend(self, w_iterable, accept_different_array=False):
             space = self.space
             if isinstance(w_iterable, W_Array):
@@ -875,11 +1025,14 @@
                 new = w_iterable.len
                 self.setlen(self.len + new)
                 i = 0
+                buf = self.get_buffer()
+                srcbuf = w_iterable.get_buffer()
                 while i < new:
                     if oldlen + i >= self.len:
                         self.setlen(oldlen + i + 1)
-                    self.buffer[oldlen + i] = w_iterable.buffer[i]
+                    buf[oldlen + i] = srcbuf[i]
                     i += 1
+                keepalive_until_here(w_iterable)
                 self.setlen(oldlen + i)
             elif (not accept_different_array
                   and isinstance(w_iterable, W_ArrayBase)):
@@ -888,17 +1041,9 @@
             else:
                 self.fromsequence(w_iterable)
 
-        def _charbuf_start(self):
-            return rffi.cast(rffi.CCHARP, self.buffer)
-
-        def _buffer_as_unsigned(self):
-            return rffi.cast(lltype.Unsigned, self.buffer)
-
-        def _charbuf_stop(self):
+        def w_getitem(self, space, idx):
+            item = self.get_buffer()[idx]
             keepalive_until_here(self)
-
-        def w_getitem(self, space, idx):
-            item = self.buffer[idx]
             if mytype.typecode in 'bBhHil':
                 item = rffi.cast(lltype.Signed, item)
             elif mytype.typecode == 'f':
@@ -916,29 +1061,16 @@
             x = self.item_w(w_x)
             index = self.len
             self.setlen(index + 1)
-            self.buffer[index] = x
+            self.get_buffer()[index] = x
+            keepalive_until_here(self)
 
         # List interface
-        def descr_count(self, space, w_val):
-            cnt = 0
-            for i in range(self.len):
-                # XXX jitdriver
-                w_item = self.w_getitem(space, i)
-                if space.is_true(space.eq(w_item, w_val)):
-                    cnt += 1
-            return space.wrap(cnt)
-
-        def descr_index(self, space, w_val):
-            for i in range(self.len):
-                w_item = self.w_getitem(space, i)
-                if space.is_true(space.eq(w_item, w_val)):
-                    return space.wrap(i)
-            raise oefmt(space.w_ValueError, "array.index(x): x not in list")
 
         def descr_reverse(self, space):
-            b = self.buffer
+            b = self.get_buffer()
             for i in range(self.len / 2):
                 b[i], b[self.len - i - 1] = b[self.len - i - 1], b[i]
+            keepalive_until_here(self)
 
         def descr_pop(self, space, i):
             if i < 0:
@@ -946,16 +1078,14 @@
             if i < 0 or i >= self.len:
                 raise oefmt(space.w_IndexError, "pop index out of range")
             w_val = self.w_getitem(space, i)
+            b = self.get_buffer()
             while i < self.len - 1:
-                self.buffer[i] = self.buffer[i + 1]
+                b[i] = b[i + 1]
                 i += 1
+            keepalive_until_here(self)
             self.setlen(self.len - 1)
             return w_val
 
-        def descr_remove(self, space, w_val):
-            w_idx = self.descr_index(space, w_val)
-            self.descr_pop(space, space.int_w(w_idx))
-
         def descr_insert(self, space, idx, w_val):
             if idx < 0:
                 idx += self.len
@@ -967,10 +1097,12 @@
             val = self.item_w(w_val)
             self.setlen(self.len + 1)
             i = self.len - 1
+            b = self.get_buffer()
             while i > idx:
-                self.buffer[i] = self.buffer[i - 1]
+                b[i] = b[i - 1]
                 i -= 1
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to