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