Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r70157:7e2b44e79080
Date: 2014-03-22 09:17 +0100
http://bitbucket.org/pypy/pypy/changeset/7e2b44e79080/

Log:    Test and fix for the issue of dicts occasionally not updating their
        cached status on a "del". The fix is to record the whole array-of-
        struct in the 'write_descrs_arrays' as soon as we write in one
        interior field, which is probably a good idea.

        This removes the last usage of
        effectinfo.write_descrs_interiorfields, which will no longer be
        translated right now -- but I'm leaving it in as the way forward.

diff --git a/rpython/jit/codewriter/effectinfo.py 
b/rpython/jit/codewriter/effectinfo.py
--- a/rpython/jit/codewriter/effectinfo.py
+++ b/rpython/jit/codewriter/effectinfo.py
@@ -224,6 +224,18 @@
             descr = cpu.interiorfielddescrof(T, fieldname)
             descrs_interiorfields.append(descr)
 
+        # a read or a write to an interiorfield, inside an array of
+        # structs, is additionally recorded as a read or write of
+        # the array itself
+        extraef = set()
+        for tup in effects:
+            if tup[0] == "interiorfield" or tup[0] == "readinteriorfield":
+                T = deref(tup[1])
+                if isinstance(T, lltype.Array) and consider_array(T):
+                    extraef.add((tup[0].replace("interiorfield", "array"),
+                                 tup[1]))
+        effects |= extraef
+
         for tup in effects:
             if tup[0] == "struct":
                 add_struct(write_descrs_fields, tup)
diff --git a/rpython/jit/codewriter/jtransform.py 
b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -1854,8 +1854,7 @@
     def _handle_dict_lookup_call(self, op, oopspec_name, args):
         extradescr1 = self.cpu.fielddescrof(op.args[1].concretetype.TO,
                                             'entries')
-        extradescr2 = self.cpu.interiorfielddescrof(
-            op.args[1].concretetype.TO.entries.TO, 'key')
+        extradescr2 = 
self.cpu.arraydescrof(op.args[1].concretetype.TO.entries.TO)
         return self._handle_oopspec_call(op, args, EffectInfo.OS_DICT_LOOKUP,
                                          extradescr=[extradescr1, extradescr2])
 
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py 
b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -177,7 +177,7 @@
         self.cached_arrayitems = {}
         # cached dict items: {dict descr: {(optval, index): box-or-const}}
         self.cached_dict_reads = {}
-        # cache of corresponding array descrs
+        # cache of corresponding {array descrs: dict 'entries' field descr}
         self.corresponding_array_descrs = {}
         #
         self._lazy_setfields_and_arrayitems = []
@@ -346,9 +346,8 @@
             self.force_lazy_setfield(fielddescr, can_cache=False)
         for arraydescr in effectinfo.write_descrs_arrays:
             self.force_lazy_setarrayitem(arraydescr, can_cache=False)
-        for descr in effectinfo.write_descrs_interiorfields:
-            if descr in self.corresponding_array_descrs:
-                dictdescr = self.corresponding_array_descrs.pop(descr)
+            if arraydescr in self.corresponding_array_descrs:
+                dictdescr = self.corresponding_array_descrs.pop(arraydescr)
                 try:
                     del self.cached_dict_reads[dictdescr]
                 except KeyError:
diff --git a/rpython/jit/metainterp/test/test_dict.py 
b/rpython/jit/metainterp/test/test_dict.py
--- a/rpython/jit/metainterp/test/test_dict.py
+++ b/rpython/jit/metainterp/test/test_dict.py
@@ -327,6 +327,21 @@
         self.check_simple_loop(call_may_force=4,    # ll_dict_lookup_trampoline
                                call=1) # ll_dict_setitem_lookup_done_trampoline
 
+    def test_bug42(self):
+        myjitdriver = JitDriver(greens = [], reds = 'auto')
+        def f(n):
+            mdict = {0: None, 1: None, 2: None, 3: None, 4: None,
+                     5: None, 6: None, 7: None, 8: None, 9: None}
+            while n > 0:
+                myjitdriver.jit_merge_point()
+                n -= 1
+                if n in mdict:
+                    del mdict[n]
+                    if n in mdict:
+                        raise Exception
+        self.meta_interp(f, [10])
+        self.check_simple_loop(call_may_force=0, call=3)
+
 
 class TestLLtype(DictTests, LLJitMixin):
     pass
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to