[pypy-commit] pypy stmgc-c8-gcc: same changes for stmdict and some cleanup (that may be suboptimal for performance)

Raemi noreply at buildbot.pypy.org
Tue Sep 8 18:28:01 CEST 2015


Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch: stmgc-c8-gcc
Changeset: r79549:196fe36e9067
Date: 2015-09-08 18:31 +0200
http://bitbucket.org/pypy/pypy/changeset/196fe36e9067/

Log:	same changes for stmdict and some cleanup (that may be suboptimal
	for performance)

diff --git a/pypy/module/pypystm/stmdict.py b/pypy/module/pypystm/stmdict.py
--- a/pypy/module/pypystm/stmdict.py
+++ b/pypy/module/pypystm/stmdict.py
@@ -17,7 +17,27 @@
 
 
 
-def find_equal_item(space, array, w_key):
+def really_find_equal_item(space, h, w_key):
+    hkey = space.hash_w(w_key)
+    entry = h.lookup(hkey)
+    array = lltype.cast_opaque_ptr(PARRAY, entry.object)
+    while True:
+        if not array:
+            return (entry, array, -1)
+
+        i = _find_equal_item(space, array, w_key)
+        if not space.type(w_key).compares_by_identity():
+            entry2 = h.lookup(hkey)
+            array2 = lltype.cast_opaque_ptr(PARRAY, entry2.object)
+            if array2 != array:
+                entry = entry2
+                array = array2
+                continue
+
+        return (entry, array, i)
+
+
+def _find_equal_item(space, array, w_key):
     # result by this function is based on 'array'. If the entry
     # changes, the result is stale.
     w_item = cast_gcref_to_instance(W_Root, array[0])
@@ -27,15 +47,17 @@
         return _run_next_iterations(space, array, w_key)
     return -1
 
+
 @jit.dont_look_inside
 def _run_next_iterations(space, array, w_key):
     i = 2
+    limit = len(array) # fixed size
     while True:
         w_item = cast_gcref_to_instance(W_Root, array[i])
-        if space.eq_w(w_key, w_item): # array may change here
+        if space.eq_w(w_key, w_item):
             return i
         i += 2
-        if i >= len(array):
+        if i >= limit:
             return -1
 
 def ll_arraycopy(source, dest, source_start, dest_start, length):
@@ -46,35 +68,20 @@
             dest[dest_start + i] = source[source_start + i]
 
 def pop_from_entry(h, space, w_key):
-    hkey = space.hash_w(w_key)
-    entry = h.lookup(hkey)
-    array = lltype.cast_opaque_ptr(PARRAY, entry.object)
-    while True:
-        if not array:
-            return None
-
-        i = find_equal_item(space, array, w_key)
-        if not space.type(w_key).compares_by_identity():
-            entry2 = h.lookup(hkey)
-            array2 = lltype.cast_opaque_ptr(PARRAY, entry2.object)
-            if array2 != array:
-                entry = entry2
-                array = array2
-                continue # not utopia yet
-
-        if i < 0:
-            return None
-        # found
-        w_value = cast_gcref_to_instance(W_Root, array[i + 1])
-        L = len(array) - 2
-        if L == 0:
-            narray = lltype.nullptr(ARRAY)
-        else:
-            narray = lltype.malloc(ARRAY, L)
-            ll_arraycopy(array, narray, 0, 0, i)
-            ll_arraycopy(array, narray, i + 2, i, L - i)
-        h.writeobj(entry, lltype.cast_opaque_ptr(llmemory.GCREF, narray))
-        return w_value
+    entry, array, i = really_find_equal_item(space, h, w_key)
+    if i < 0:
+        return None
+    # found
+    w_value = cast_gcref_to_instance(W_Root, array[i + 1])
+    L = len(array) - 2
+    if L == 0:
+        narray = lltype.nullptr(ARRAY)
+    else:
+        narray = lltype.malloc(ARRAY, L)
+        ll_arraycopy(array, narray, 0, 0, i)
+        ll_arraycopy(array, narray, i + 2, i, L - i)
+    h.writeobj(entry, lltype.cast_opaque_ptr(llmemory.GCREF, narray))
+    return w_value
 
 
 
@@ -84,28 +91,10 @@
         self.h = rstm.create_hashtable()
 
     def getitem_w(self, space, w_key):
-        hkey = space.hash_w(w_key)
-        entry = self.h.lookup(hkey)
-        array = lltype.cast_opaque_ptr(PARRAY, entry.object)
-        while True:
-            if array:
-                i = find_equal_item(space, array, w_key)
-
-                if not space.type(w_key).compares_by_identity():
-                    # the world may have changed:
-                    # if entry has changed, we are lost
-                    # if array has changed, the result we got from find_equal_item
-                    #    is not trustworthy; should also imply entry!=entry2
-                    entry2 = self.h.lookup(hkey)
-                    array2 = lltype.cast_opaque_ptr(PARRAY, entry2.object)
-                    if array2 != array:
-                        entry = entry2
-                        array = array2
-                        continue # not utopia yet
-
-                if i >= 0:
-                    return cast_gcref_to_instance(W_Root, array[i + 1])
-            space.raise_key_error(w_key)
+        entry, array, i = really_find_equal_item(space, self.h, w_key)
+        if array and i >= 0:
+            return cast_gcref_to_instance(W_Root, array[i + 1])
+        space.raise_key_error(w_key)
 
     def setitem_w(self, space, w_key, w_value):
         hkey = space.hash_w(w_key)
@@ -113,15 +102,9 @@
         array = lltype.cast_opaque_ptr(PARRAY, entry.object)
         while True:
             if array:
-                i = find_equal_item(space, array, w_key)
-                if not space.type(w_key).compares_by_identity():
-                    entry2 = self.h.lookup(hkey)
-                    array2 = lltype.cast_opaque_ptr(PARRAY, entry2.object)
-                    if array2 != array:
-                        entry = entry2
-                        array = array2
-                        continue
-
+                entry, array, i = really_find_equal_item(space, self.h, w_key)
+                if not array:
+                    continue
                 if i >= 0:
                     # already there, update the value
                     array[i + 1] = cast_instance_to_gcref(w_value)
@@ -142,35 +125,17 @@
             space.raise_key_error(w_key)
 
     def contains_w(self, space, w_key):
-        hkey = space.hash_w(w_key)
-        gcref = self.h.get(hkey)
-        array = lltype.cast_opaque_ptr(PARRAY, gcref)
-        while True:
-            if array and find_equal_item(space, array, w_key) >= 0:
-                if not space.type(w_key).compares_by_identity():
-                    array2 = lltype.cast_opaque_ptr(PARRAY, self.h.get(hkey))
-                    if array2 != array:
-                        array = array2
-                        continue
-                return space.w_True
-            return space.w_False
+        entry, array, i = really_find_equal_item(space, self.h, w_key)
+        if array and i >= 0:
+            return space.w_True
+        return space.w_False
 
     @unwrap_spec(w_default=WrappedDefault(None))
     def get_w(self, space, w_key, w_default):
-        hkey = space.hash_w(w_key)
-        gcref = self.h.get(hkey)
-        array = lltype.cast_opaque_ptr(PARRAY, gcref)
-        while True:
-            if array:
-                i = find_equal_item(space, array, w_key)
-                if not space.type(w_key).compares_by_identity():
-                    array2 = lltype.cast_opaque_ptr(PARRAY, self.h.get(hkey))
-                    if array2 != array:
-                        array = array2
-                        continue
-                if i >= 0:
-                    return cast_gcref_to_instance(W_Root, array[i + 1])
-            return w_default
+        entry, array, i = really_find_equal_item(space, self.h, w_key)
+        if array and i >= 0:
+            return cast_gcref_to_instance(W_Root, array[i + 1])
+        return w_default
 
     def pop_w(self, space, w_key, w_default=None):
         w_value = pop_from_entry(self.h, space, w_key)
@@ -188,14 +153,9 @@
         array = lltype.cast_opaque_ptr(PARRAY, entry.object)
         while True:
             if array:
-                i = find_equal_item(space, array, w_key)
-                if not space.type(w_key).compares_by_identity():
-                    entry2 = self.h.lookup(hkey)
-                    array2 = lltype.cast_opaque_ptr(PARRAY, entry2.object)
-                    if array2 != array:
-                        entry = entry2
-                        array = array2
-                        continue
+                entry, array, i = really_find_equal_item(space, self.h, w_key)
+                if not array:
+                    continue
                 if i >= 0:
                     # already there, return the existing value
                     return cast_gcref_to_instance(W_Root, array[i + 1])
diff --git a/pypy/module/pypystm/stmset.py b/pypy/module/pypystm/stmset.py
--- a/pypy/module/pypystm/stmset.py
+++ b/pypy/module/pypystm/stmset.py
@@ -17,7 +17,27 @@
 PARRAY = lltype.Ptr(ARRAY)
 
 
-def find_equal_item(space, array, w_key):
+
+def really_find_equal_item(space, h, w_key):
+    hkey = space.hash_w(w_key)
+    entry = h.lookup(hkey)
+    array = lltype.cast_opaque_ptr(PARRAY, entry.object)
+    while True:
+        if not array:
+            return (entry, array, -1)
+
+        i = _find_equal_item(space, array, w_key)
+        if not space.type(w_key).compares_by_identity():
+            entry2 = h.lookup(hkey)
+            array2 = lltype.cast_opaque_ptr(PARRAY, entry2.object)
+            if array2 != array:
+                entry = entry2
+                array = array2
+                continue
+
+        return (entry, array, i)
+
+def _find_equal_item(space, array, w_key):
     w_item = cast_gcref_to_instance(W_Root, array[0])
     if space.eq_w(w_key, w_item):
         return 0
@@ -44,10 +64,8 @@
         self.h = rstm.create_hashtable()
 
     def contains_w(self, space, w_key):
-        hkey = space.hash_w(w_key)
-        gcref = self.h.get(hkey)
-        array = lltype.cast_opaque_ptr(PARRAY, gcref)
-        if array and find_equal_item(space, array, w_key) >= 0:
+        entry, array, i = really_find_equal_item(space, self.h, w_key)
+        if array and i >= 0:
             return space.w_True
         return space.w_False
 
@@ -55,17 +73,22 @@
         hkey = space.hash_w(w_key)
         entry = self.h.lookup(hkey)
         array = lltype.cast_opaque_ptr(PARRAY, entry.object)
-        if array:
-            if find_equal_item(space, array, w_key) >= 0:
-                return      # already there
-            L = len(array)
-            narray = lltype.malloc(ARRAY, L + 1)
-            ll_arraycopy(array, narray, 0, 0, L)
-        else:
-            narray = lltype.malloc(ARRAY, 1)
-            L = 0
-        narray[L] = cast_instance_to_gcref(w_key)
-        self.h.writeobj(entry, lltype.cast_opaque_ptr(llmemory.GCREF, narray))
+        while True:
+            if array:
+                entry, array, i = really_find_equal_item(space, self.h, w_key)
+                if not array:
+                    continue
+                if i >= 0:
+                    return      # already there
+                L = len(array)
+                narray = lltype.malloc(ARRAY, L + 1)
+                ll_arraycopy(array, narray, 0, 0, L)
+            else:
+                narray = lltype.malloc(ARRAY, 1)
+                L = 0
+            narray[L] = cast_instance_to_gcref(w_key)
+            self.h.writeobj(entry, lltype.cast_opaque_ptr(llmemory.GCREF, narray))
+            return
 
     def try_remove(self, space, w_key):
         hkey = space.hash_w(w_key)
@@ -73,8 +96,8 @@
         array = lltype.cast_opaque_ptr(PARRAY, entry.object)
         if not array:
             return False
-        i = find_equal_item(space, array, w_key)
-        if i < 0:
+        entry, array, i = really_find_equal_item(space, self.h, w_key)
+        if not array or i < 0:
             return False
         # found
         L = len(array) - 1
diff --git a/pypy/module/pypystm/test/test_stmdict.py b/pypy/module/pypystm/test/test_stmdict.py
--- a/pypy/module/pypystm/test/test_stmdict.py
+++ b/pypy/module/pypystm/test/test_stmdict.py
@@ -119,8 +119,6 @@
 
 
     def test_custom_evil_eq(self):
-        import pypystm
-
         class A(object):
             depth = []
             def __hash__(self):
@@ -131,6 +129,7 @@
                     del d[a]
                     print "del a"
                 return self is other
+        import pypystm
         d = pypystm.stmdict()
         a = A()
         b = A()
@@ -140,8 +139,6 @@
         assert b in d
 
     def test_custom_evil_eq2(self):
-        import pypystm
-
         class A(object):
             depth = []
             def __hash__(self):
@@ -152,6 +149,7 @@
                     del d[a]
                     print "del a"
                 return self is other
+        import pypystm
         d = pypystm.stmdict()
         a = A()
         b = A()


More information about the pypy-commit mailing list