Author: Armin Rigo <[email protected]>
Branch: stm-thread-2
Changeset: r57078:78dfa129ccef
Date: 2012-09-02 13:21 +0200
http://bitbucket.org/pypy/pypy/changeset/78dfa129ccef/
Log: Track more precisely the category of individual pointers, not the
category of general objects.
diff --git a/pypy/translator/stm/test/test_transform2.py
b/pypy/translator/stm/test/test_transform2.py
--- a/pypy/translator/stm/test/test_transform2.py
+++ b/pypy/translator/stm/test/test_transform2.py
@@ -1,18 +1,42 @@
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.llinterp import LLFrame
from pypy.rpython.test.test_llinterp import get_interpreter, clear_tcache
+from pypy.objspace.flow.model import Constant
from pypy.translator.stm.transform2 import STMTransformer
from pypy.conftest import option
+class _stmptr(lltype._ptr):
+ """Like lltype._ptr, but also keeps a current category level"""
+
+ __slots__ = ['_category']
+
+ def __init__(self, ptr, category):
+ lltype._ptr.__init__(self, ptr._TYPE, ptr._obj0, ptr._solid)
+ _stmptr._category.__set__(self, category)
+
+
class BaseTestTransform(object):
prebuilt = ()
+ def build_state(self):
+ self.writemode = set()
+ self.barriers = []
+
+ def get_category(self, p):
+ if isinstance(p, _stmptr):
+ return p._category
+ if not p:
+ return 'N'
+ if p in self.prebuilt:
+ return 'G'
+ raise AssertionError("unknown category on %r" % (p,))
+
def interpret(self, fn, args):
+ self.build_state()
clear_tcache()
- self.stmstate = STMState(self.prebuilt)
interp, self.graph = get_interpreter(fn, args, view=False)
- interp.stmstate = self.stmstate
+ interp.tester = self
interp.frame_class = LLSTMFrame
#
self.translator = interp.typer.annotator.translator
@@ -25,33 +49,6 @@
return result
-class STMState(object):
- def __init__(self, prebuilt=()):
- self.categories = {None: 'N'} # Null
- for p in prebuilt:
- self.categories[self._getkey(p)] = 'G' # Global
- self.writemode = set()
-
- def _getkey(self, p):
- assert lltype.typeOf(p).TO._gckind == 'gc'
- p = lltype.normalizeptr(p)
- if p:
- return p._obj0
- else:
- return None
-
- def get_category(self, p):
- key = self._getkey(p)
- return self.categories[key]
-
- def set_category(self, p, ncat):
- key = self._getkey(p)
- assert key is not None and ncat != 'N'
- self.categories[key] = ncat
- if ncat == 'W':
- self.writemode.add(key)
-
-
class LLSTMFrame(LLFrame):
_MORE_PRECISE_CATEGORIES = {
'P': 'PGORLWN',
@@ -63,21 +60,21 @@
'N': 'N'}
def get_category(self, p):
- return self.llinterpreter.stmstate.get_category(p)
-
- def set_category(self, p, ncat):
- self.llinterpreter.stmstate.set_category(p, ncat)
+ return self.llinterpreter.tester.get_category(p)
def check_category(self, p, expected):
cat = self.get_category(p)
assert cat in self._MORE_PRECISE_CATEGORIES[expected]
def op_stm_barrier(self, kind, obj):
- frm, digittwo, to = kind
- assert digittwo == '2'
+ frm, middledigit, to = kind
+ assert middledigit == '2'
self.check_category(obj, frm)
- self.set_category(obj, to)
- return obj
+ ptr2 = _stmptr(obj, to)
+ if to == 'W':
+ self.llinterpreter.tester.writemode.add(ptr2._obj)
+ self.llinterpreter.tester.barriers.append(kind)
+ return ptr2
def op_getfield(self, obj, field):
self.check_category(obj, 'R')
@@ -106,10 +103,11 @@
res = self.interpret(f1, [4])
assert res == 81
- assert len(self.stmstate.writemode) == 0
+ assert len(self.writemode) == 0
res = self.interpret(f1, [-5])
assert res == 42
- assert len(self.stmstate.writemode) == 0
+ assert len(self.writemode) == 0
+ assert self.barriers == ['G2R']
def test_simple_write(self):
X = lltype.GcStruct('X', ('foo', lltype.Signed))
@@ -122,4 +120,27 @@
self.interpret(f1, [4])
assert x1.foo == 4
- assert len(self.stmstate.writemode) == 1
+ assert len(self.writemode) == 1
+ assert self.barriers == ['G2W']
+
+ def test_multiple_reads(self):
+ X = lltype.GcStruct('X', ('foo', lltype.Signed),
+ ('bar', lltype.Signed))
+ x1 = lltype.malloc(X, immortal=True)
+ x1.foo = 6
+ x1.bar = 7
+ x2 = lltype.malloc(X, immortal=True)
+ x2.foo = 81
+ x2.bar = -1
+ self.prebuilt = [x1, x2]
+
+ def f1(n):
+ if n > 1:
+ return x2.foo * x2.bar
+ else:
+ return x1.foo * x1.bar
+
+ res = self.interpret(f1, [4])
+ assert res == -81
+ assert len(self.writemode) == 0
+ assert self.barriers == ['G2R', 'P2R'] # XXX remove the 2nd one
diff --git a/pypy/translator/stm/transform2.py
b/pypy/translator/stm/transform2.py
--- a/pypy/translator/stm/transform2.py
+++ b/pypy/translator/stm/transform2.py
@@ -71,9 +71,13 @@
for op in block.operations:
to = wants_a_barrier.get(op)
if to is not None:
- c_info = Constant('P2%s' % to, lltype.Void)
v = op.args[0]
v = renamings.get(v, v)
+ if isinstance(v, Constant):
+ frm = 'G'
+ else:
+ frm = 'P' # XXX improve
+ c_info = Constant('%s2%s' % (frm, to), lltype.Void)
w = varoftype(v.concretetype)
newop = SpaceOperation('stm_barrier', [c_info, v], w)
newoperations.append(newop)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit