Author: Armin Rigo <[email protected]>
Branch: bitstring
Changeset: r83895:ce207cea6d2c
Date: 2016-04-26 10:43 +0200
http://bitbucket.org/pypy/pypy/changeset/ce207cea6d2c/

Log:    Compute the bitstrings

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
@@ -1,7 +1,9 @@
+import sys
 from rpython.jit.metainterp.typesystem import deref, fieldType, arrayItem
 from rpython.rtyper.rclass import OBJECT
 from rpython.rtyper.lltypesystem import lltype, llmemory
 from rpython.translator.backendopt.graphanalyze import BoolGraphAnalyzer
+from rpython.tool.algo import bitstring
 
 
 class EffectInfo(object):
@@ -110,12 +112,20 @@
                 can_invalidate=False,
                 call_release_gil_target=_NO_CALL_RELEASE_GIL_TARGET,
                 extradescrs=None):
-        key = (frozenset_or_none(readonly_descrs_fields),
-               frozenset_or_none(readonly_descrs_arrays),
-               frozenset_or_none(readonly_descrs_interiorfields),
-               frozenset_or_none(write_descrs_fields),
-               frozenset_or_none(write_descrs_arrays),
-               frozenset_or_none(write_descrs_interiorfields),
+        readonly_descrs_fields = frozenset_or_none(readonly_descrs_fields)
+        readonly_descrs_arrays = frozenset_or_none(readonly_descrs_arrays)
+        readonly_descrs_interiorfields = frozenset_or_none(
+                                              readonly_descrs_interiorfields)
+        write_descrs_fields = frozenset_or_none(write_descrs_fields)
+        write_descrs_arrays = frozenset_or_none(write_descrs_arrays)
+        write_descrs_interiorfields = frozenset_or_none(
+                                              write_descrs_interiorfields)
+        key = (readonly_descrs_fields,
+               readonly_descrs_arrays,
+               readonly_descrs_interiorfields,
+               write_descrs_fields,
+               write_descrs_arrays,
+               write_descrs_interiorfields,
                extraeffect,
                oopspecindex,
                can_invalidate)
@@ -139,22 +149,24 @@
             assert write_descrs_arrays is not None
             assert write_descrs_interiorfields is not None
         result = object.__new__(cls)
-        result.readonly_descrs_fields = readonly_descrs_fields
-        result.readonly_descrs_arrays = readonly_descrs_arrays
-        result.readonly_descrs_interiorfields = readonly_descrs_interiorfields
+        # the frozensets "._readonly_xxx" and "._write_xxx" should not be
+        # translated.
+        result._readonly_descrs_fields = readonly_descrs_fields
+        result._readonly_descrs_arrays = readonly_descrs_arrays
+        result._readonly_descrs_interiorfields = readonly_descrs_interiorfields
         if extraeffect == EffectInfo.EF_LOOPINVARIANT or \
            extraeffect == EffectInfo.EF_ELIDABLE_CANNOT_RAISE or \
            extraeffect == EffectInfo.EF_ELIDABLE_OR_MEMORYERROR or \
            extraeffect == EffectInfo.EF_ELIDABLE_CAN_RAISE:
             # Ignore the writes.  Note that this ignores also writes with
             # no corresponding reads (rarely the case, but possible).
-            result.write_descrs_fields = []
-            result.write_descrs_arrays = []
-            result.write_descrs_interiorfields = []
+            result._write_descrs_fields = frozenset()
+            result._write_descrs_arrays = frozenset()
+            result._write_descrs_interiorfields = frozenset()
         else:
-            result.write_descrs_fields = write_descrs_fields
-            result.write_descrs_arrays = write_descrs_arrays
-            result.write_descrs_interiorfields = write_descrs_interiorfields
+            result._write_descrs_fields = write_descrs_fields
+            result._write_descrs_arrays = write_descrs_arrays
+            result._write_descrs_interiorfields = write_descrs_interiorfields
         result.extraeffect = extraeffect
         result.can_invalidate = can_invalidate
         result.oopspecindex = oopspecindex
@@ -165,6 +177,25 @@
         cls._cache[key] = result
         return result
 
+    def check_readonly_descr_field(self, fielddescr):
+        return bitstring.bitcheck(self.bitstring_readonly_descrs_fields,
+                                  fielddescr.ei_index)
+    def check_write_descr_field(self, fielddescr):
+        return bitstring.bitcheck(self.bitstring_write_descrs_fields,
+                                  fielddescr.ei_index)
+    def check_readonly_descr_array(self, arraydescr):
+        return bitstring.bitcheck(self.bitstring_readonly_descrs_arrays,
+                                  arraydescr.ei_index)
+    def check_write_descr_array(self, arraydescr):
+        return bitstring.bitcheck(self.bitstring_write_descrs_arrays,
+                                  arraydescr.ei_index)
+    def check_readonly_descr_interiorfield(self, interiorfielddescr):
+        return 
bitstring.bitcheck(self.bitstring_readonly_descrs_interiorfields,
+                                  interiorfielddescr.ei_index)
+    def check_write_descr_interiorfield(self, interiorfielddescr):
+        return bitstring.bitcheck(self.bitstring_write_descrs_interiorfields,
+                                  interiorfielddescr.ei_index)
+
     def check_can_raise(self, ignore_memoryerror=False):
         if ignore_memoryerror:
             return self.extraeffect > self.EF_ELIDABLE_OR_MEMORYERROR
@@ -382,3 +413,55 @@
         assert funcptr
         return funcptr
     funcptr_for_oopspec._annspecialcase_ = 'specialize:arg(1)'
+
+# ____________________________________________________________
+
+def compute_bitstrings(all_descrs):
+    # Compute the bitstrings in the EffectInfo,
+    # bitstring_{readonly,write}_descrs_{fieldd,arrays,interiordescrs},
+    # and for each FieldDescrs and ArrayDescrs compute 'ei_index'.
+    # Each bit in the bitstrings says whether this Descr is present in
+    # this EffectInfo or not.  We try to share the value of 'ei_index'
+    # across multiple Descrs if they always give the same answer (in
+    # PyPy, it reduces the length of the bitstrings from 4000+ to
+    # 373).
+    effectinfos = []
+    descrs = {'fields': set(), 'arrays': set(), 'interiorfields': set()}
+    for descr in all_descrs:
+        if hasattr(descr, 'get_extra_info'):
+            ei = descr.get_extra_info()
+            if ei._readonly_descrs_fields is None:
+                for key in descrs:
+                    assert getattr(ei, '_readonly_descrs_' + key) is None
+                    assert getattr(ei, '_write_descrs_' + key) is None
+                    setattr(ei, 'bitstring_readonly_descrs_' + key, None)
+                    setattr(ei, 'bitstring_write_descrs_' + key, None)
+            else:
+                effectinfos.append(ei)
+                for key in descrs:
+                    descrs[key].update(getattr(ei, '_readonly_descrs_' + key))
+                    descrs[key].update(getattr(ei, '_write_descrs_' + key))
+        else:
+            descr.ei_index = sys.maxint
+    for key in descrs:
+        mapping = {}
+        for descr in descrs[key]:
+            assert descr.ei_index == sys.maxint    # not modified yet
+            eisetr = [ei for ei in effectinfos
+                         if descr in getattr(ei, '_readonly_descrs_' + key)]
+            eisetw = [ei for ei in effectinfos
+                         if descr in getattr(ei, '_write_descrs_' + key)]
+            eisetr = frozenset(eisetr)
+            eisetw = frozenset(eisetw)
+            descr.ei_index = mapping.setdefault((eisetr, eisetw), len(mapping))
+        for ei in effectinfos:
+            bitstrr = [descr.ei_index
+                           for descr in getattr(ei, '_readonly_descrs_' + key)]
+            bitstrw = [descr.ei_index
+                           for descr in getattr(ei, '_write_descrs_' + key)]
+            assert sys.maxint not in bitstrr
+            assert sys.maxint not in bitstrw
+            bitstrr = bitstring.make_bitstring(bitstrr)
+            bitstrw = bitstring.make_bitstring(bitstrw)
+            setattr(ei, 'bitstring_readonly_descrs_' + key, bitstrr)
+            setattr(ei, 'bitstring_write_descrs_' + key, bitstrw)
diff --git a/rpython/jit/codewriter/test/test_effectinfo.py 
b/rpython/jit/codewriter/test/test_effectinfo.py
--- a/rpython/jit/codewriter/test/test_effectinfo.py
+++ b/rpython/jit/codewriter/test/test_effectinfo.py
@@ -1,11 +1,12 @@
-import pytest
+import pytest, sys
 
 from rpython.jit.codewriter.effectinfo import (effectinfo_from_writeanalyze,
-    EffectInfo, VirtualizableAnalyzer)
+    EffectInfo, VirtualizableAnalyzer, compute_bitstrings)
 from rpython.rlib import jit
 from rpython.rtyper.lltypesystem import lltype
 from rpython.rtyper.rclass import OBJECT
 from rpython.translator.translator import TranslationContext, graphof
+from rpython.tool.algo.bitstring import bitcheck
 
 
 class FakeCPU(object):
@@ -29,37 +30,37 @@
     S = lltype.GcStruct("S", ("a", lltype.Signed))
     effects = frozenset([("readstruct", lltype.Ptr(S), "a")])
     effectinfo = effectinfo_from_writeanalyze(effects, FakeCPU())
-    assert list(effectinfo.readonly_descrs_fields) == [('fielddescr', S, "a")]
-    assert not effectinfo.write_descrs_fields
-    assert not effectinfo.write_descrs_arrays
+    assert list(effectinfo._readonly_descrs_fields) == [('fielddescr', S, "a")]
+    assert not effectinfo._write_descrs_fields
+    assert not effectinfo._write_descrs_arrays
 
 
 def test_include_write_field():
     S = lltype.GcStruct("S", ("a", lltype.Signed))
     effects = frozenset([("struct", lltype.Ptr(S), "a")])
     effectinfo = effectinfo_from_writeanalyze(effects, FakeCPU())
-    assert list(effectinfo.write_descrs_fields) == [('fielddescr', S, "a")]
-    assert not effectinfo.readonly_descrs_fields
-    assert not effectinfo.write_descrs_arrays
+    assert list(effectinfo._write_descrs_fields) == [('fielddescr', S, "a")]
+    assert not effectinfo._readonly_descrs_fields
+    assert not effectinfo._write_descrs_arrays
 
 
 def test_include_read_array():
     A = lltype.GcArray(lltype.Signed)
     effects = frozenset([("readarray", lltype.Ptr(A))])
     effectinfo = effectinfo_from_writeanalyze(effects, FakeCPU())
-    assert not effectinfo.readonly_descrs_fields
-    assert list(effectinfo.readonly_descrs_arrays) == [('arraydescr', A)]
-    assert not effectinfo.write_descrs_fields
-    assert not effectinfo.write_descrs_arrays
+    assert not effectinfo._readonly_descrs_fields
+    assert list(effectinfo._readonly_descrs_arrays) == [('arraydescr', A)]
+    assert not effectinfo._write_descrs_fields
+    assert not effectinfo._write_descrs_arrays
 
 
 def test_include_write_array():
     A = lltype.GcArray(lltype.Signed)
     effects = frozenset([("array", lltype.Ptr(A))])
     effectinfo = effectinfo_from_writeanalyze(effects, FakeCPU())
-    assert not effectinfo.readonly_descrs_fields
-    assert not effectinfo.write_descrs_fields
-    assert list(effectinfo.write_descrs_arrays) == [('arraydescr', A)]
+    assert not effectinfo._readonly_descrs_fields
+    assert not effectinfo._write_descrs_fields
+    assert list(effectinfo._write_descrs_arrays) == [('arraydescr', A)]
 
 
 def test_dont_include_read_and_write_field():
@@ -67,9 +68,9 @@
     effects = frozenset([("readstruct", lltype.Ptr(S), "a"),
                          ("struct", lltype.Ptr(S), "a")])
     effectinfo = effectinfo_from_writeanalyze(effects, FakeCPU())
-    assert not effectinfo.readonly_descrs_fields
-    assert list(effectinfo.write_descrs_fields) == [('fielddescr', S, "a")]
-    assert not effectinfo.write_descrs_arrays
+    assert not effectinfo._readonly_descrs_fields
+    assert list(effectinfo._write_descrs_fields) == [('fielddescr', S, "a")]
+    assert not effectinfo._write_descrs_arrays
 
 
 def test_dont_include_read_and_write_array():
@@ -77,34 +78,34 @@
     effects = frozenset([("readarray", lltype.Ptr(A)),
                          ("array", lltype.Ptr(A))])
     effectinfo = effectinfo_from_writeanalyze(effects, FakeCPU())
-    assert not effectinfo.readonly_descrs_fields
-    assert not effectinfo.readonly_descrs_arrays
-    assert not effectinfo.write_descrs_fields
-    assert list(effectinfo.write_descrs_arrays) == [('arraydescr', A)]
+    assert not effectinfo._readonly_descrs_fields
+    assert not effectinfo._readonly_descrs_arrays
+    assert not effectinfo._write_descrs_fields
+    assert list(effectinfo._write_descrs_arrays) == [('arraydescr', A)]
 
 
 def test_filter_out_typeptr():
     effects = frozenset([("struct", lltype.Ptr(OBJECT), "typeptr")])
     effectinfo = effectinfo_from_writeanalyze(effects, None)
-    assert not effectinfo.readonly_descrs_fields
-    assert not effectinfo.write_descrs_fields
-    assert not effectinfo.write_descrs_arrays
+    assert not effectinfo._readonly_descrs_fields
+    assert not effectinfo._write_descrs_fields
+    assert not effectinfo._write_descrs_arrays
 
 
 def test_filter_out_array_of_void():
     effects = frozenset([("array", lltype.Ptr(lltype.GcArray(lltype.Void)))])
     effectinfo = effectinfo_from_writeanalyze(effects, None)
-    assert not effectinfo.readonly_descrs_fields
-    assert not effectinfo.write_descrs_fields
-    assert not effectinfo.write_descrs_arrays
+    assert not effectinfo._readonly_descrs_fields
+    assert not effectinfo._write_descrs_fields
+    assert not effectinfo._write_descrs_arrays
 
 
 def test_filter_out_struct_with_void():
     effects = frozenset([("struct", lltype.Ptr(lltype.GcStruct("x", ("a", 
lltype.Void))), "a")])
     effectinfo = effectinfo_from_writeanalyze(effects, None)
-    assert not effectinfo.readonly_descrs_fields
-    assert not effectinfo.write_descrs_fields
-    assert not effectinfo.write_descrs_arrays
+    assert not effectinfo._readonly_descrs_fields
+    assert not effectinfo._write_descrs_fields
+    assert not effectinfo._write_descrs_arrays
 
 
 class TestVirtualizableAnalyzer(object):
@@ -138,3 +139,64 @@
 
         res = self.analyze(entry, [int])
         assert not res
+
+
+def test_compute_bitstrings():
+    class FDescr:
+        pass
+    class ADescr:
+        pass
+    class CDescr:
+        def __init__(self, ei):
+            self._ei = ei
+        def get_extra_info(self):
+            return self._ei
+
+    f1descr = FDescr()
+    f2descr = FDescr()
+    f3descr = FDescr()
+    a1descr = ADescr()
+    a2descr = ADescr()
+
+    ei1 = EffectInfo(None, None, None, None, None, None,
+                         EffectInfo.EF_RANDOM_EFFECTS)
+    ei2 = EffectInfo([f1descr], [], [], [], [], [])
+    ei3 = EffectInfo([f1descr], [a1descr, a2descr], [], [f2descr], [], [])
+
+    compute_bitstrings([CDescr(ei1), CDescr(ei2), CDescr(ei3),
+                        f1descr, f2descr, f3descr, a1descr, a2descr])
+
+    assert f1descr.ei_index in (0, 1)
+    assert f2descr.ei_index == 1 - f1descr.ei_index
+    assert f3descr.ei_index == sys.maxint
+    assert a1descr.ei_index == 0
+    assert a2descr.ei_index == 0
+
+    assert ei1.bitstring_readonly_descrs_fields is None
+    assert ei1.bitstring_readonly_descrs_arrays is None
+    assert ei1.bitstring_write_descrs_fields is None
+
+    def expand(bitstr):
+        return [n for n in range(10) if bitcheck(bitstr, n)]
+
+    assert expand(ei2.bitstring_readonly_descrs_fields) == [f1descr.ei_index]
+    assert expand(ei2.bitstring_write_descrs_fields) == []
+    assert expand(ei2.bitstring_readonly_descrs_arrays) == []
+    assert expand(ei2.bitstring_write_descrs_arrays) == []
+
+    assert expand(ei3.bitstring_readonly_descrs_fields) == [f1descr.ei_index]
+    assert expand(ei3.bitstring_write_descrs_fields) == [f2descr.ei_index]
+    assert expand(ei3.bitstring_readonly_descrs_arrays) == [0] #a1descr,a2descr
+    assert expand(ei3.bitstring_write_descrs_arrays) == []
+
+    for ei in [ei2, ei3]:
+        for fdescr in [f1descr, f2descr]:
+            assert ei.check_readonly_descr_field(fdescr) == (
+                fdescr in ei._readonly_descrs_fields)
+            assert ei.check_write_descr_field(fdescr) == (
+                fdescr in ei._write_descrs_fields)
+        for adescr in [a1descr, a2descr]:
+            assert ei.check_readonly_descr_array(adescr) == (
+                adescr in ei._readonly_descrs_arrays)
+            assert ei.check_write_descr_array(adescr) == (
+                adescr in ei._write_descrs_arrays)
diff --git a/rpython/jit/metainterp/pyjitpl.py 
b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -1809,6 +1809,7 @@
         self._addr2name_values = [value for key, value in list_of_addr2name]
 
     def finish_setup(self, codewriter, optimizer=None):
+        from rpython.jit.codewriter import effectinfo
         from rpython.jit.metainterp.blackhole import BlackholeInterpBuilder
         self.blackholeinterpbuilder = BlackholeInterpBuilder(codewriter, self)
         #
@@ -1839,6 +1840,7 @@
         #
         self.globaldata = MetaInterpGlobalData(self)
         self.all_descrs = self.cpu.setup_descrs()
+        effectinfo.compute_bitstrings(self.all_descrs)
 
     def _setup_once(self):
         """Runtime setup needed by the various components of the JIT."""
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to