[pypy-commit] pypy stmgc-c8-dictstrategy: hg merge stmgc-c8
arigo
noreply at buildbot.pypy.org
Wed Nov 25 11:17:31 EST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c8-dictstrategy
Changeset: r80956:e884e0b2b29f
Date: 2015-11-25 17:18 +0100
http://bitbucket.org/pypy/pypy/changeset/e884e0b2b29f/
Log: hg merge stmgc-c8
diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -93,6 +93,7 @@
insets = self._in_states
#
# get input variables and their states:
+ assert len(insets[block]) == len(block.inputargs)
writeable = {}
for v, state in zip(block.inputargs, insets[block]):
writeable[v] = state
@@ -106,8 +107,10 @@
writeable = {}
#
if op.opname == "stm_ignored_start":
+ assert not self.in_stm_ignored
self.in_stm_ignored = True
elif op.opname == "stm_ignored_stop":
+ assert self.in_stm_ignored
self.in_stm_ignored = False
elif op.opname == "gc_writebarrier":
assert not self.in_stm_ignored
@@ -115,67 +118,62 @@
elif op.opname == "malloc":
rtti = get_rtti(op.args[0].value)
if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'):
- # XXX: not sure why that matters, copied from
- # find_initializing_stores
- continue
- writeable[op.result] = True
+ # objs with finalizers are allocated directly as "old", so
+ # they need write barriers
+ assert op not in self.clean_ops
+ else:
+ # freshly allocated object
+ writeable[op.result] = True
#
elif op.opname in ("cast_pointer", "same_as"):
- if writeable.get(op.args[0], False):
- writeable[op.result] = True
+ writeable[op.result] = writeable.get(op.args[0], False)
#
elif op.opname in ('setfield', 'setarrayitem', 'setinteriorfield', 'raw_store'):
+ # generic_set case
if op.args[-1].concretetype == lltype.Void:
+ # always ignore setfields of Void type
self.clean_ops.add(op)
- continue # ignore setfields of Void type
elif not var_needsgc(op.args[0]):
+ # setfields on raw don't need a barrier
if (var_needsgc(op.args[-1]) and
'is_excdata' not in op.args[0].concretetype.TO._hints):
raise Exception("%s: GC pointer written into a non-GC location"
% (op,))
self.clean_ops.add(op)
- continue
elif self.in_stm_ignored:
- # detect if we're inside a 'stm_ignored' block and in
- # that case don't call stm_write(). This only works for
- # writing non-GC pointers.
+ # within stm_ignored, don't emit stm_write(). This only works
+ # for writing non-GC pointers.
if var_needsgc(op.args[-1]):
raise Exception("in stm_ignored block: write of a gc pointer")
self.clean_ops.add(op)
- continue
- elif self._set_into_gc_array_part(op) is None:
- # full write barrier required
- if writeable.get(op.args[0], False):
- # already writeable, this op is also clean
- self.clean_ops.add(op)
- elif op in self.clean_ops:
- # we changed our opinion in this iteration
- self.clean_ops.remove(op)
- # always writeable after this op
- writeable[op.args[0]] = True
else:
- # things that need partial write barriers (card marking)
+ # we need a (partial) write barrier if arg0 is not writeable
if writeable.get(op.args[0], False):
self.clean_ops.add(op)
elif op in self.clean_ops:
self.clean_ops.remove(op)
+ #
+ if self._set_into_gc_array_part(op) is None:
+ # this will do a full write barrier, not card marking
+ # arg0 is always writeable afterwards
+ writeable[op.args[0]] = True
#
# update in_states of all successors
- updated = set()
+ to_do = set()
for link in block.exits:
succ = link.target
outset = [writeable.get(v, False) for v in link.args]
if succ in insets:
- to_merge = [insets[succ], outset]
- new = self._merge_out_states(to_merge)
- if new != insets[succ]:
- updated.add(succ)
+ old = insets[succ]
+ new = self._merge_out_states([old, outset])
+ if new != old:
+ to_do.add(succ)
insets[succ] = new
else:
# block not processed yet
insets[succ] = outset
- updated.add(succ)
- return updated
+ to_do.add(succ)
+ return to_do
def collect(self):
@@ -186,8 +184,7 @@
graph = self.graph
#
# initialize blocks
- self._in_states = {}
- self._in_states[graph.startblock] = [False] * len(graph.startblock.inputargs)
+ self._in_states = {graph.startblock: [False] * len(graph.startblock.inputargs)}
#
# fixpoint iteration
# XXX: reverse postorder traversal
diff --git a/rpython/memory/gctransform/test/test_framework.py b/rpython/memory/gctransform/test/test_framework.py
--- a/rpython/memory/gctransform/test/test_framework.py
+++ b/rpython/memory/gctransform/test/test_framework.py
@@ -396,6 +396,141 @@
assert summary(ff)['stm_write'] == 3
+def test_remove_write_barrier_stm4():
+ from rpython.translator.c.genc import CStandaloneBuilder
+ from rpython.flowspace.model import summary
+
+ rS = lltype.Struct('rS')
+ S = lltype.GcStruct('S')
+ rA = lltype.Array(lltype.Ptr(rS))
+ A = lltype.GcArray(lltype.Ptr(S))
+ Ar = lltype.GcArray(lltype.Ptr(rS))
+ def f(ra, a, ar, i):
+ s = lltype.malloc(S)
+ rs = lltype.malloc(rS, flavor='raw')
+ ra[0] = rs
+ ra[1] = rs
+ a[0] = s
+ a[1] = s
+ ar[0] = rs
+ ar[1] = rs
+ def g(argv):
+ n = int(argv[1])
+ ra = lltype.malloc(rA, n, flavor='raw')
+ a = lltype.malloc(A, n)
+ ar = lltype.malloc(Ar, n)
+ f(ra, a, ar, n)
+ return 0
+ t = rtype(g, [s_list_of_strings])
+ t.config.translation.stm = True
+ gcpolicy = StmFrameworkGcPolicy
+ t.config.translation.gc = "stmgc"
+ cbuild = CStandaloneBuilder(t, g, t.config,
+ gcpolicy=gcpolicy)
+ db = cbuild.generate_graphs_for_llinterp()
+
+ ff = graphof(t, f)
+ #ff.show()
+ assert summary(ff)['stm_write'] == 4
+
+def test_remove_write_barrier_stm5():
+ from rpython.translator.c.genc import CStandaloneBuilder
+ from rpython.flowspace.model import summary
+
+ class B(object):
+ def __del__(self):
+ pass
+ class A(object): pass
+ def f():
+ b = B()
+ b.x = 1 # needs WB bc. of finalizer
+ a = A()
+ a.x = 1
+ def g(argv):
+ f()
+ return 0
+ t = rtype(g, [s_list_of_strings])
+ t.config.translation.stm = True
+ gcpolicy = StmFrameworkGcPolicy
+ t.config.translation.gc = "stmgc"
+ cbuild = CStandaloneBuilder(t, g, t.config,
+ gcpolicy=gcpolicy)
+ db = cbuild.generate_graphs_for_llinterp()
+
+ ff = graphof(t, f)
+ #ff.show()
+ assert summary(ff)['stm_write'] == 1
+
+def test_remove_write_barrier_stm6():
+ from rpython.translator.c.genc import CStandaloneBuilder
+ from rpython.flowspace.model import summary
+ #
+ rSi = lltype.Struct('rSi', ('i', lltype.Signed))
+ rSr = lltype.Struct('rSr', ('s', lltype.Ptr(rSi)))
+ Si = lltype.GcStruct('Si', ('i', lltype.Signed))
+ Ss = lltype.GcStruct('Ss', ('s', lltype.Ptr(Si)))
+ Sr = lltype.GcStruct('Sr', ('r', lltype.Ptr(rSi)))
+ def f(rsi, rsr, si, ss, sr):
+ rsi.i = 0
+ rsr.s = rsi
+ si.i = 0
+ ss.s = si
+ sr.r = rsi
+ def g(argv):
+ rsi = lltype.malloc(rSi, flavor='raw')
+ rsr = lltype.malloc(rSr, flavor='raw')
+ si = lltype.malloc(Si, flavor='gc')
+ ss = lltype.malloc(Ss, flavor='gc')
+ sr = lltype.malloc(Sr, flavor='gc')
+ f(rsi, rsr, si, ss, sr)
+ return 0
+ t = rtype(g, [s_list_of_strings])
+ t.config.translation.stm = True
+ gcpolicy = StmFrameworkGcPolicy
+ t.config.translation.gc = "stmgc"
+ cbuild = CStandaloneBuilder(t, g, t.config,
+ gcpolicy=gcpolicy)
+ db = cbuild.generate_graphs_for_llinterp()
+
+ ff = graphof(t, f)
+ #ff.show()
+ assert summary(ff)['stm_write'] == 3
+
+def test_remove_write_barrier_stm7():
+ from rpython.translator.c.genc import CStandaloneBuilder
+ from rpython.flowspace.model import summary
+ #
+ rSi = lltype.Struct('rSi', ('i', lltype.Signed))
+ rSr = lltype.Struct('rSr', ('s', rSi))
+ Si = lltype.GcStruct('Si', ('i', lltype.Signed))
+ Ss = lltype.GcStruct('Ss', ('s', Si))
+ Sr = lltype.GcStruct('Sr', ('r', rSi))
+ def f(rsi, rsr, si, ss, sr):
+ rsi.i = 0
+ rsr.s.i = 0
+ si.i = 0
+ ss.s.i = 0
+ sr.r.i = 0
+ def g(argv):
+ rsi = lltype.malloc(rSi, flavor='raw')
+ rsr = lltype.malloc(rSr, flavor='raw')
+ si = lltype.malloc(Si, flavor='gc')
+ ss = lltype.malloc(Ss, flavor='gc')
+ sr = lltype.malloc(Sr, flavor='gc')
+ f(rsi, rsr, si, ss, sr)
+ return 0
+ t = rtype(g, [s_list_of_strings])
+ t.config.translation.stm = True
+ gcpolicy = StmFrameworkGcPolicy
+ t.config.translation.gc = "stmgc"
+ cbuild = CStandaloneBuilder(t, g, t.config,
+ gcpolicy=gcpolicy)
+ db = cbuild.generate_graphs_for_llinterp()
+
+ ff = graphof(t, f)
+ #ff.show()
+ assert summary(ff)['stm_write'] == 3
+
def test_write_barrier_collector():
class A(object):
pass
@@ -483,6 +618,34 @@
print "\n".join(map(str,wbc.clean_ops))
assert len(wbc.clean_ops) == 11
+def test_write_barrier_collector_stm_inevitable_interaction():
+ from rpython.translator.c.genc import CStandaloneBuilder
+ from rpython.flowspace.model import summary
+ #
+ rS = lltype.Struct('rS', ('i', lltype.Signed))
+ S = lltype.GcStruct('S', ('i', lltype.Signed))
+ def f():
+ rs = lltype.malloc(rS, flavor='raw')
+ s = lltype.malloc(S, flavor='gc')
+ rs.i = 5 # become_inevitable setfield on 'raw'
+ s.i = 6 # become_inevitable canmalloc -> needs WB
+ def g(argv):
+ f()
+ return 0
+ t = rtype(g, [s_list_of_strings])
+ t.config.translation.stm = True
+ gcpolicy = StmFrameworkGcPolicy
+ t.config.translation.gc = "stmgc"
+ cbuild = CStandaloneBuilder(t, g, t.config,
+ gcpolicy=gcpolicy)
+ db = cbuild.generate_graphs_for_llinterp()
+
+ ff = graphof(t, f)
+ #ff.show()
+ assert summary(ff)['stm_write'] == 1
+
+
+
def test_write_barrier_collector_loops():
class A(object):
pass
diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -53,7 +53,7 @@
"""
_pinned_objects.append(obj)
return True
-
+
class PinEntry(ExtRegistryEntry):
_about_ = pin
@@ -296,6 +296,10 @@
slowpath = False
if stm_is_enabled():
slowpath = True
+ # seems to be a good idea to do a *full* write barrier on the
+ # items array, as this prevents repeated stm_write_card() inside
+ # the loop below (see logic in stmframework.py).
+ llop.gc_writebarrier(lltype.Void, dest)
#
elif _contains_gcptr(TP.OF):
# perform a write barrier that copies necessary flags from
@@ -864,7 +868,7 @@
pending.extend(get_rpy_referents(gcref))
all_typeids = {}
-
+
def get_typeid(obj):
raise Exception("does not work untranslated")
diff --git a/rpython/translator/stm/funcgen.py b/rpython/translator/stm/funcgen.py
--- a/rpython/translator/stm/funcgen.py
+++ b/rpython/translator/stm/funcgen.py
@@ -416,8 +416,10 @@
arg1 = funcgen.expr(op.args[1])
arg2 = funcgen.expr(op.args[2])
result = funcgen.expr(op.result)
- return ('%s = stm_hashtable_iter_next(%s, %s, %s);' %
- (result, arg0, arg1, arg2))
+ typename = cdecl(funcgen.lltypename(op.result), '')
+ return ('%s = (%s)stm_hashtable_iter_next((object_t *)%s, %s,'
+ ' (stm_hashtable_entry_t **)%s);' %
+ (result, typename, arg0, arg1, arg2))
def stm_hashtable_iter_tracefn(funcgen, op):
arg0 = funcgen.expr(op.args[0])
diff --git a/rpython/translator/stm/readbarrier.py b/rpython/translator/stm/readbarrier.py
--- a/rpython/translator/stm/readbarrier.py
+++ b/rpython/translator/stm/readbarrier.py
@@ -146,7 +146,7 @@
cat_map[op.result] = 'R'
#
if op.opname in ('setfield', 'setarrayitem', 'setinteriorfield',
- 'raw_store'):
+ 'raw_store', 'gc_writebarrier'):
# compare with logic in stmframework.py
# ops that need a write barrier also make the var 'R'
if (op.args[-1].concretetype is not lltype.Void
More information about the pypy-commit
mailing list