[pypy-commit] pypy fast-gil: hg merge default

arigo noreply at buildbot.pypy.org
Wed Jun 25 19:34:10 CEST 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: fast-gil
Changeset: r72229:ed9493101461
Date: 2014-06-25 19:33 +0200
http://bitbucket.org/pypy/pypy/changeset/ed9493101461/

Log:	hg merge default

diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_verify.py b/pypy/module/test_lib_pypy/cffi_tests/test_verify.py
--- a/pypy/module/test_lib_pypy/cffi_tests/test_verify.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/test_verify.py
@@ -1906,3 +1906,60 @@
     p = lib.f2(42)
     x = lib.f1(p)
     assert x == 42
+
+def _run_in_multiple_threads(test1):
+    test1()
+    import sys
+    try:
+        import thread
+    except ImportError:
+        import _thread as thread
+    errors = []
+    def wrapper(lock):
+        try:
+            test1()
+        except:
+            errors.append(sys.exc_info())
+        lock.release()
+    locks = []
+    for i in range(10):
+        _lock = thread.allocate_lock()
+        _lock.acquire()
+        thread.start_new_thread(wrapper, (_lock,))
+        locks.append(_lock)
+    for _lock in locks:
+        _lock.acquire()
+        if errors:
+            raise errors[0][1]
+
+def test_errno_working_even_with_pypys_jit():
+    ffi = FFI()
+    ffi.cdef("int f(int);")
+    lib = ffi.verify("""
+        #include <errno.h>
+        int f(int x) { return (errno = errno + x); }
+    """)
+    @_run_in_multiple_threads
+    def test1():
+        ffi.errno = 0
+        for i in range(10000):
+            e = lib.f(1)
+            assert e == i + 1
+            assert ffi.errno == e
+        for i in range(10000):
+            ffi.errno = i
+            e = lib.f(42)
+            assert e == i + 42
+
+def test_getlasterror_working_even_with_pypys_jit():
+    if sys.platform != 'win32':
+        py.test.skip("win32-only test")
+    ffi = FFI()
+    ffi.cdef("void SetLastError(DWORD);")
+    lib = ffi.dlopen("Kernel32.dll")
+    @_run_in_multiple_threads
+    def test1():
+        for i in range(10000):
+            n = (1 << 29) + i
+            lib.SetLastError(n)
+            assert ffi.getwinerror()[0] == n
diff --git a/pypy/objspace/std/celldict.py b/pypy/objspace/std/celldict.py
--- a/pypy/objspace/std/celldict.py
+++ b/pypy/objspace/std/celldict.py
@@ -16,7 +16,7 @@
 
 
 class ModuleCell(W_Root):
-    def __init__(self, w_value=None):
+    def __init__(self, w_value):
         self.w_value = w_value
 
     def __repr__(self):
@@ -49,17 +49,24 @@
         return self.erase({})
 
     def mutated(self):
+        # A mutation means changing an existing key to point to a new value.
+        # A value is either a regular wrapped object, or a ModuleCell if we
+        # detect mutations.  It means that each existing key can only trigger
+        # a mutation at most once.
         self.version = VersionTag()
 
-    def getdictvalue_no_unwrapping(self, w_dict, key):
+    def dictvalue_no_unwrapping(self, w_dict, key):
         # NB: it's important to promote self here, so that self.version is a
         # no-op due to the quasi-immutable field
         self = jit.promote(self)
-        return self._getdictvalue_no_unwrapping_pure(self.version, w_dict, key)
+        return self._dictvalue_no_unwrapping_pure(self.version, w_dict, key)
 
     @jit.elidable_promote('0,1,2')
-    def _getdictvalue_no_unwrapping_pure(self, version, w_dict, key):
-        return self.unerase(w_dict.dstorage).get(key, None)
+    def _dictvalue_no_unwrapping_pure(self, version, w_dict, key):
+        # may raise KeyError.  If it does, then the JIT is prevented from
+        # considering this function as elidable.  This is what lets us add
+        # new keys to the dictionary without changing the version.
+        return self.unerase(w_dict.dstorage)[key]
 
     def setitem(self, w_dict, w_key, w_value):
         space = self.space
@@ -70,17 +77,20 @@
             w_dict.setitem(w_key, w_value)
 
     def setitem_str(self, w_dict, key, w_value):
-        cell = self.getdictvalue_no_unwrapping(w_dict, key)
-        if isinstance(cell, ModuleCell):
-            cell.w_value = w_value
-            return
-        if cell is not None:
+        try:
+            cell = self.dictvalue_no_unwrapping(w_dict, key)
+        except KeyError:
+            pass
+        else:
+            if isinstance(cell, ModuleCell):
+                cell.w_value = w_value
+                return
             # If the new value and the current value are the same, don't
             # create a level of indirection, or mutate the version.
             if self.space.is_w(w_value, cell):
                 return
             w_value = ModuleCell(w_value)
-        self.mutated()
+            self.mutated()
         self.unerase(w_dict.dstorage)[key] = w_value
 
     def setdefault(self, w_dict, w_key, w_default):
@@ -130,7 +140,10 @@
             return w_dict.getitem(w_key)
 
     def getitem_str(self, w_dict, key):
-        cell = self.getdictvalue_no_unwrapping(w_dict, key)
+        try:
+            cell = self.dictvalue_no_unwrapping(w_dict, key)
+        except KeyError:
+            return None
         return unwrap_cell(cell)
 
     def w_keys(self, w_dict):
diff --git a/pypy/objspace/std/test/test_celldict.py b/pypy/objspace/std/test/test_celldict.py
--- a/pypy/objspace/std/test/test_celldict.py
+++ b/pypy/objspace/std/test/test_celldict.py
@@ -21,27 +21,27 @@
         w_key = self.FakeString(key)
         d.setitem(w_key, 1)
         v2 = strategy.version
-        assert v1 is not v2
+        assert v1 is v2          # doesn't change when adding new keys
         assert d.getitem(w_key) == 1
-        assert d.strategy.getdictvalue_no_unwrapping(d, key) == 1
+        assert d.strategy.dictvalue_no_unwrapping(d, key) == 1
 
         d.setitem(w_key, 2)
         v3 = strategy.version
         assert v2 is not v3
         assert d.getitem(w_key) == 2
-        assert d.strategy.getdictvalue_no_unwrapping(d, key).w_value == 2
+        assert d.strategy.dictvalue_no_unwrapping(d, key).w_value == 2
 
         d.setitem(w_key, 3)
         v4 = strategy.version
         assert v3 is v4
         assert d.getitem(w_key) == 3
-        assert d.strategy.getdictvalue_no_unwrapping(d, key).w_value == 3
+        assert d.strategy.dictvalue_no_unwrapping(d, key).w_value == 3
 
         d.delitem(w_key)
         v5 = strategy.version
         assert v5 is not v4
         assert d.getitem(w_key) is None
-        assert d.strategy.getdictvalue_no_unwrapping(d, key) is None
+        py.test.raises(KeyError, d.strategy.dictvalue_no_unwrapping, d, key)
 
     def test_same_key_set_twice(self):
         strategy = ModuleDictStrategy(space)
@@ -52,7 +52,7 @@
         x = object()
         d.setitem("a", x)
         v2 = strategy.version
-        assert v1 is not v2
+        assert v1 is v2
         d.setitem("a", x)
         v3 = strategy.version
         assert v2 is v3


More information about the pypy-commit mailing list