[pypy-commit] pypy stmgc-c4: merge (I should pull before doing things..)
Raemi
noreply at buildbot.pypy.org
Mon Jul 22 09:06:52 CEST 2013
Author: Remi Meier <remi.meier at gmail.com>
Branch: stmgc-c4
Changeset: r65524:b8c3b478c594
Date: 2013-07-22 09:01 +0200
http://bitbucket.org/pypy/pypy/changeset/b8c3b478c594/
Log: merge (I should pull before doing things..)
diff --git a/rpython/translator/stm/test/test_writebarrier.py b/rpython/translator/stm/test/test_writebarrier.py
--- a/rpython/translator/stm/test/test_writebarrier.py
+++ b/rpython/translator/stm/test/test_writebarrier.py
@@ -24,7 +24,7 @@
res = self.interpret(f1, [-5])
assert res == 42
assert len(self.writemode) == 0
- assert self.barriers == ['G2R']
+ assert self.barriers == ['P2R']
def test_simple_write(self):
X = lltype.GcStruct('X', ('foo', lltype.Signed))
@@ -37,7 +37,7 @@
self.interpret(f1, [4])
assert x1.foo == 4
assert len(self.writemode) == 1
- assert self.barriers == ['G2W']
+ assert self.barriers == ['P2W']
def test_multiple_reads(self):
X = lltype.GcStruct('X', ('foo', lltype.Signed),
@@ -58,7 +58,7 @@
res = self.interpret(f1, [4])
assert res == -81
assert len(self.writemode) == 0
- assert self.barriers == ['G2R']
+ assert self.barriers == ['P2R']
def test_malloc(self):
X = lltype.GcStruct('X', ('foo', lltype.Signed))
@@ -81,7 +81,7 @@
self.interpret(f1, [4])
assert len(self.writemode) == 2
- assert self.barriers == ['G2W', 'r2w']
+ assert self.barriers == ['P2W', 'r2w']
def test_repeat_read_barrier_after_malloc(self):
X = lltype.GcStruct('X', ('foo', lltype.Signed))
@@ -95,7 +95,7 @@
self.interpret(f1, [4])
assert len(self.writemode) == 1
- assert self.barriers == ['G2R']
+ assert self.barriers == ['P2R']
def test_write_may_alias(self):
X = lltype.GcStruct('X', ('foo', lltype.Signed))
@@ -109,10 +109,10 @@
y = lltype.malloc(X, immortal=True)
res = self.interpret(f1, [x, y])
assert res == 36
- assert self.barriers == ['P2R', 'P2W', 'o2r']
+ assert self.barriers == ['P2R', 'P2W', 'p2r']
res = self.interpret(f1, [x, x])
assert res == 42
- assert self.barriers == ['P2R', 'P2W', 'O2R']
+ assert self.barriers == ['P2R', 'P2W', 'P2R']
def test_write_cannot_alias(self):
X = lltype.GcStruct('X', ('foo', lltype.Signed))
@@ -254,18 +254,31 @@
x.foo = 815
x.zbar = 'A'
external_stuff()
- result = x.foo
- if isinstance(x, Y):
- result += x.ybar
+ result = x.foo # 1
+ if isinstance(x, Y): # 2
+ result += x.ybar # 3
return result
res = self.interpret(f1, [10])
assert res == 42 + 10
- assert self.barriers == ['p2r', 'p2r'] # from two blocks (could be
- # optimized later)
+ assert self.barriers == ['p2r', 'p2r', 'p2r'] # from 3 blocks (could be
+ # optimized later)
res = self.interpret(f1, [-10])
assert res == 815
- assert self.barriers == ['p2r']
+ assert self.barriers == ['p2r', 'p2r']
+
+ def test_write_barrier_repeated(self):
+ class X:
+ pass
+ x = X()
+ def f1(i):
+ x.a = i # write barrier
+ y = X() # malloc
+ x.a += 1 # write barrier again
+ return y
+
+ res = self.interpret(f1, [10])
+ assert self.barriers == ['P2W', 'r2w']
external_stuff = rffi.llexternal('external_stuff', [], lltype.Void,
diff --git a/rpython/translator/stm/test/transform_support.py b/rpython/translator/stm/test/transform_support.py
--- a/rpython/translator/stm/test/transform_support.py
+++ b/rpython/translator/stm/test/transform_support.py
@@ -2,7 +2,7 @@
from rpython.rtyper.llinterp import LLFrame
from rpython.rtyper.test.test_llinterp import get_interpreter, clear_tcache
from rpython.translator.stm.transform import STMTransformer
-from rpython.translator.stm.writebarrier import MORE_PRECISE_CATEGORIES
+from rpython.translator.stm.writebarrier import NEEDS_BARRIER
from rpython.conftest import option
@@ -29,13 +29,13 @@
self.writemode = set()
self.barriers = []
- def get_category(self, p):
+ def get_category_or_null(self, p):
if isinstance(p, _stmptr):
return p._category
if not p:
return 'N'
if p._solid:
- return 'G' # allocated with immortal=True
+ return 'P' # allocated with immortal=True
raise AssertionError("unknown category on %r" % (p,))
def interpret(self, fn, args):
@@ -71,19 +71,19 @@
if isinstance(value, _stmptr):
yield value
- def get_category(self, p):
- return self.llinterpreter.tester.get_category(p)
+ def get_category_or_null(self, p):
+ return self.llinterpreter.tester.get_category_or_null(p)
def check_category(self, p, expected):
- cat = self.get_category(p)
- assert cat in MORE_PRECISE_CATEGORIES[expected]
+ cat = self.get_category_or_null(p)
+ assert cat in 'NPRW'
return cat
def op_stm_barrier(self, kind, obj):
frm, middledigit, to = kind
assert middledigit == '2'
cat = self.check_category(obj, frm)
- if cat in MORE_PRECISE_CATEGORIES[to]:
+ if not NEEDS_BARRIER[cat, to]:
# a barrier, but with no effect
self.llinterpreter.tester.barriers.append(kind.lower())
return obj
@@ -109,10 +109,10 @@
def op_setfield(self, obj, fieldname, fieldvalue):
if not obj._TYPE.TO._immutable_field(fieldname):
self.check_category(obj, 'W')
- # convert R -> O all other pointers to the same object we can find
+ # convert R -> P all other pointers to the same object we can find
for p in self.all_stm_ptrs():
if p._category == 'R' and p._T == obj._T and p == obj:
- _stmptr._category.__set__(p, 'O')
+ _stmptr._category.__set__(p, 'P')
return LLFrame.op_setfield(self, obj, fieldname, fieldvalue)
def op_cast_pointer(self, RESTYPE, obj):
diff --git a/rpython/translator/stm/transform.py b/rpython/translator/stm/transform.py
--- a/rpython/translator/stm/transform.py
+++ b/rpython/translator/stm/transform.py
@@ -4,6 +4,7 @@
from rpython.translator.stm.jitdriver import reorganize_around_jit_driver
from rpython.translator.stm.threadlocalref import transform_tlref
from rpython.translator.c.support import log
+from rpython.memory.gctransform.framework import CollectAnalyzer
class STMTransformer(object):
@@ -26,9 +27,11 @@
def transform_write_barrier(self):
self.write_analyzer = WriteAnalyzer(self.translator)
+ self.collect_analyzer = CollectAnalyzer(self.translator)
for graph in self.translator.graphs:
insert_stm_barrier(self, graph)
del self.write_analyzer
+ del self.collect_analyzer
def transform_turn_inevitable(self):
for graph in self.translator.graphs:
diff --git a/rpython/translator/stm/writebarrier.py b/rpython/translator/stm/writebarrier.py
--- a/rpython/translator/stm/writebarrier.py
+++ b/rpython/translator/stm/writebarrier.py
@@ -9,14 +9,14 @@
'malloc_nonmovable', 'malloc_nonmovable_varsize',
])
-MORE_PRECISE_CATEGORIES = {
- 'P': 'PGORLWN', # Pointer: the most general category
- 'G': 'GN', # Global: known to be a non-local pointer
- 'O': 'ORLWN', # Old: used to be read-ready, but maybe someone wrote
- 'R': 'RLWN', # Read-ready: direct reads from there are ok
- 'L': 'LWN', # Local: a local pointer
- 'W': 'WN', # Write-ready: direct writes here are ok
- 'N': 'N'} # NULL (the other categories also all contain NULL)
+NEEDS_BARRIER = {
+ ('P', 'R'): True,
+ ('P', 'W'): True,
+ ('R', 'R'): False,
+ ('R', 'W'): True,
+ ('W', 'R'): False,
+ ('W', 'W'): False,
+ }
def unwraplist(list_v):
for v in list_v:
@@ -44,14 +44,20 @@
def insert_stm_barrier(stmtransformer, graph):
+ """This function uses the following characters for 'categories':
+
+ * 'P': a general pointer
+ * 'R': the read barrier was applied
+ * 'W': the write barrier was applied
+ """
graphinfo = stmtransformer.write_analyzer.compute_graph_info(graph)
def get_category(v):
- if isinstance(v, Constant):
- if v.value:
- return 'G'
- else:
- return 'N' # NULL
+ return category.get(v, 'P')
+
+ def get_category_or_null(v):
+ if isinstance(v, Constant) and not v.value:
+ return 'N'
return category.get(v, 'P')
def renamings_get(v):
@@ -82,7 +88,7 @@
op.result.concretetype is not lltype.Void and
op.args[0].concretetype.TO._gckind == 'gc' and
True): #not is_immutable(op)): XXX see [1]
- wants_a_barrier.setdefault(op, 'R')
+ wants_a_barrier[op] = 'R'
elif (op.opname in ('setfield', 'setarrayitem',
'setinteriorfield') and
op.args[-1].concretetype is not lltype.Void and
@@ -113,7 +119,7 @@
v_holder = renamings.setdefault(v, [v])
v = v_holder[0]
frm = get_category(v)
- if frm not in MORE_PRECISE_CATEGORIES[to]:
+ if NEEDS_BARRIER[frm, to]:
c_info = Constant('%s2%s' % (frm, to), lltype.Void)
w = varoftype(v.concretetype)
newop = SpaceOperation('stm_barrier', [c_info, v], w)
@@ -127,9 +133,9 @@
newoperations.append(newop)
#
if op in expand_comparison:
- cats = ''.join([get_category(v) for v in newop.args])
- if ('N' not in cats and
- cats not in ('LL', 'LW', 'WL', 'WW')):
+ cats = (get_category_or_null(newop.args[0]),
+ get_category_or_null(newop.args[1]))
+ if 'N' not in cats and cats != ('W', 'W'):
if newop.opname == 'ptr_ne':
v = varoftype(lltype.Bool)
negop = SpaceOperation('bool_not', [v],
@@ -137,24 +143,33 @@
newoperations.append(negop)
newop.result = v
newop.opname = 'stm_ptr_eq'
- #
+
+ if stmtransformer.collect_analyzer.analyze(op):
+ # this operation can collect: we bring all 'W'
+ # categories back to 'R', because we would need
+ # another stm_write_barrier on them afterwards
+ for v, cat in category.items():
+ if cat == 'W':
+ category[v] = 'R'
+
effectinfo = stmtransformer.write_analyzer.analyze(
op, graphinfo=graphinfo)
if effectinfo:
if effectinfo is top_set:
- category.clear()
+ # this operation can perform random writes: any
+ # 'R'-category object falls back to 'P' because
+ # we would need another stm_read_barrier()
+ for v, cat in category.items():
+ if cat == 'R':
+ category[v] = 'P'
else:
+ # the same, but only on objects of the right types
types = set([entry[1] for entry in effectinfo])
for v in category.keys():
if v.concretetype in types and category[v] == 'R':
- category[v] = 'O'
- #
+ category[v] = 'P'
+
if op.opname in MALLOCS:
- # write barriers after a possible minor collection
- # are not valid anymore:
- for v, c in category.items():
- if c == 'W':
- category[v] = 'R'
category[op.result] = 'W'
block.operations = newoperations
More information about the pypy-commit
mailing list