[pypy-commit] pypy faster-rstruct-2: backout 85d3ab6fe80b, which was broken, and start to rewrite the logic in a more generic way. Also, write tests in such a way that we can check that gc_{load, store}_indexed produce effects corresponding to their equivalent

antocuni pypy.commits at gmail.com
Mon May 22 13:03:49 EDT 2017


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: faster-rstruct-2
Changeset: r91374:356dacc477eb
Date: 2017-05-22 18:30 +0200
http://bitbucket.org/pypy/pypy/changeset/356dacc477eb/

Log:	backout 85d3ab6fe80b, which was broken, and start to rewrite the
	logic in a more generic way. Also, write tests in such a way that we
	can check that gc_{load,store}_indexed produce effects corresponding
	to their equivalent

diff --git a/rpython/translator/backendopt/test/test_writeanalyze.py b/rpython/translator/backendopt/test/test_writeanalyze.py
--- a/rpython/translator/backendopt/test/test_writeanalyze.py
+++ b/rpython/translator/backendopt/test/test_writeanalyze.py
@@ -1,5 +1,7 @@
 import py
-from rpython.rtyper.lltypesystem import lltype
+from rpython.rtyper.lltypesystem import lltype, llmemory
+from rpython.rtyper.lltypesystem.lloperation import llop
+from rpython.rtyper.lltypesystem.rstr import STR
 from rpython.translator.translator import TranslationContext, graphof
 from rpython.translator.backendopt.writeanalyze import WriteAnalyzer, top_set
 from rpython.translator.backendopt.writeanalyze import ReadWriteAnalyzer
@@ -269,34 +271,6 @@
         assert struct == "struct"
         assert name.endswith("foobar")
 
-    def test_gc_store_indexed(self):
-        from rpython.rtyper.lltypesystem import lltype, llmemory
-        from rpython.rtyper.lltypesystem.lloperation import llop
-        from rpython.rlib.rgc import (resizable_list_supporting_raw_ptr,
-                                      ll_for_resizable_list)
-
-        def write_item(lst, byte_offset, value):
-            ll_data = ll_for_resizable_list(lst)
-            ll_items = ll_data.items
-            LIST = lltype.typeOf(ll_data).TO # rlist.LIST_OF(lltype.Char)
-            base_ofs = llmemory.itemoffsetof(LIST.items.TO, 0)
-            scale_factor = llmemory.sizeof(lltype.Char)
-            llop.gc_store_indexed(lltype.Void, ll_items, byte_offset, value,
-                                  scale_factor, base_ofs)
-
-        def f(x):
-            lst = resizable_list_supporting_raw_ptr(['A', 'B', 'C', 'D'])
-            write_item(lst, 0, 'E')
-        t, wa = self.translate(f, [int])
-        fgraph = graphof(t, f)
-        result = wa.analyze(fgraph.startblock.operations[-1])
-        #
-        assert len(result) == 1
-        array, A = list(result)[0]
-        assert array == "array"
-        assert A.TO.OF == lltype.Char
-
-
 
 class TestLLtypeReadWriteAnalyze(BaseTest):
     Analyzer = ReadWriteAnalyzer
@@ -433,3 +407,42 @@
         res = list(result)
         assert ('readinteriorfield', lltype.Ptr(A), 'y') in res
         assert ('interiorfield', lltype.Ptr(A), 'x') in res
+
+
+class TestGcLoadStoreIndexed(BaseTest):
+    Analyzer = ReadWriteAnalyzer
+
+    def _analyze_graph_single(self, t, wa, fn):
+        graph = graphof(t, fn)
+        result = wa.analyze(graph.startblock.operations[-1])
+        result = list(result)
+        return result
+
+    def test_gc_load_indexed_str(self):
+        from rpython.rlib.buffer import StringBuffer
+
+        def typed_read(buf):
+            return buf.typed_read(lltype.Signed, 0)
+
+        def direct_read(buf):
+            return buf.value[0]
+
+        def f(x):
+            buf = StringBuffer(x)
+            return direct_read(buf), typed_read(buf)
+
+        t, wa = self.translate(f, [str])
+        # check that the effect of direct_read
+        direct_effects = self._analyze_graph_single(t, wa, direct_read)
+        assert len(direct_effects) == 1
+        effect = direct_effects[0]
+        what, T, field = effect
+        assert what == 'readinteriorfield'
+        assert T == lltype.Ptr(STR)
+        assert field == 'chars'
+        #
+        # typed_read contains many effects because it reads the vtable etc.,
+        # but we want to check that it contains also the same effect as
+        # direct_read
+        typed_effects = self._analyze_graph_single(t, wa, typed_read)
+        assert effect in typed_effects
diff --git a/rpython/translator/backendopt/writeanalyze.py b/rpython/translator/backendopt/writeanalyze.py
--- a/rpython/translator/backendopt/writeanalyze.py
+++ b/rpython/translator/backendopt/writeanalyze.py
@@ -1,5 +1,6 @@
 from rpython.flowspace.model import Variable, Constant
 from rpython.translator.backendopt import graphanalyze
+from rpython.rtyper.lltypesystem import lltype, llmemory
 
 top_set = object()
 empty_set = frozenset()
@@ -62,8 +63,7 @@
                 name = self._getinteriorname(op)
                 return self._interiorfield_result(op.args[0].concretetype, name)
         elif op.opname == "gc_store_indexed":
-            if graphinfo is None or not graphinfo.is_fresh_malloc(op.args[0]):
-                return self._array_result(op.args[0].concretetype)
+            assert False, 'implement me'
         return empty_set
 
     def _array_result(self, TYPE):
@@ -125,4 +125,37 @@
             name = self._getinteriorname(op)
             return frozenset([("readinteriorfield", op.args[0].concretetype,
                             name)])
+        elif op.opname == "gc_load_indexed":
+            return self._gc_load_store_result(op)
         return WriteAnalyzer.analyze_simple_operation(self, op, graphinfo)
+
+    def _gc_load_store_result(self, op):
+        base_offset = op.args[3].value
+        effect = self._get_effect_for_offset(base_offset)
+        return frozenset([effect])
+
+    def _get_effect_for_offset(self, ofs):
+        # gc_{load,store}_indexed are generic operation which operate on
+        # various data types: depending on the symbolic offset, they can be
+        # equivalent as reading/writing an array, and interiorfield, etc. The
+        # following logic tries to catch all the known usages. If you see an
+        # 'implement me', please update the logic accordingly
+        if isinstance(ofs, llmemory.CompositeOffset):
+            # get the effect for the first component and modify it if
+            # necessary
+            sub_offsets = ofs.offsets
+            effect = self._get_effect_for_offset(sub_offsets[0])
+            for sub_ofs in sub_offsets[1:]:
+                if isinstance(sub_ofs, llmemory.ArrayItemsOffset):
+                    # reading from the middle of an array is the same as
+                    # reading from the beginning, so we don't need to change
+                    # the effect
+                    pass
+                else:
+                    assert False, 'implement me'
+            return effect
+        elif isinstance(ofs, llmemory.FieldOffset):
+            T = ofs.TYPE
+            return ('readinteriorfield', lltype.Ptr(T), ofs.fldname)
+        else:
+            assert False, 'implement me'


More information about the pypy-commit mailing list