Author: Armin Rigo <[email protected]>
Branch: stm
Changeset: r48794:8c30442dc679
Date: 2011-11-05 17:58 +0100
http://bitbucket.org/pypy/pypy/changeset/8c30442dc679/
Log: interiorfield operations.
diff --git a/pypy/rpython/lltypesystem/lloperation.py
b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -399,6 +399,8 @@
'stm_setfield': LLOp(),
'stm_getarrayitem': LLOp(sideeffects=False, canrun=True),
'stm_setarrayitem': LLOp(),
+ 'stm_getinteriorfield': LLOp(sideeffects=False, canrun=True),
+ 'stm_setinteriorfield': LLOp(),
'stm_begin_transaction': LLOp(),
'stm_commit_transaction': LLOp(),
diff --git a/pypy/translator/c/funcgen.py b/pypy/translator/c/funcgen.py
--- a/pypy/translator/c/funcgen.py
+++ b/pypy/translator/c/funcgen.py
@@ -600,6 +600,8 @@
OP_STM_SETFIELD = _OP_STM
OP_STM_GETARRAYITEM = _OP_STM
OP_STM_SETARRAYITEM = _OP_STM
+ OP_STM_GETINTERIORFIELD = _OP_STM
+ OP_STM_SETINTERIORFIELD = _OP_STM
OP_STM_BEGIN_TRANSACTION = _OP_STM
OP_STM_COMMIT_TRANSACTION = _OP_STM
OP_STM_BEGIN_INEVITABLE_TRANSACTION = _OP_STM
diff --git a/pypy/translator/stm/funcgen.py b/pypy/translator/stm/funcgen.py
--- a/pypy/translator/stm/funcgen.py
+++ b/pypy/translator/stm/funcgen.py
@@ -46,7 +46,7 @@
def _stm_generic_set(funcgen, op, targetexpr, T):
basename = funcgen.expr(op.args[0])
- newvalue = funcgen.expr(op.args[2], special_case_void=False)
+ newvalue = funcgen.expr(op.args[-1], special_case_void=False)
#
assert T is not lltype.Void # XXX
fieldsize = rffi.sizeof(T)
@@ -75,42 +75,48 @@
citemtypename, targetexpr, newvalue))
+def field_expr(funcgen, args):
+ STRUCT = funcgen.lltypemap(args[0]).TO
+ structdef = funcgen.db.gettypedefnode(STRUCT)
+ baseexpr_is_const = isinstance(args[0], Constant)
+ return structdef.ptr_access_expr(funcgen.expr(args[0]),
+ args[1].value,
+ baseexpr_is_const)
+
def stm_getfield(funcgen, op):
- STRUCT = funcgen.lltypemap(op.args[0]).TO
- structdef = funcgen.db.gettypedefnode(STRUCT)
- baseexpr_is_const = isinstance(op.args[0], Constant)
- expr = structdef.ptr_access_expr(funcgen.expr(op.args[0]),
- op.args[1].value,
- baseexpr_is_const)
+ expr = field_expr(funcgen, op.args)
return _stm_generic_get(funcgen, op, expr)
def stm_setfield(funcgen, op):
- STRUCT = funcgen.lltypemap(op.args[0]).TO
- structdef = funcgen.db.gettypedefnode(STRUCT)
- baseexpr_is_const = isinstance(op.args[0], Constant)
- expr = structdef.ptr_access_expr(funcgen.expr(op.args[0]),
- op.args[1].value,
- baseexpr_is_const)
+ expr = field_expr(funcgen, op.args)
T = op.args[2].concretetype
return _stm_generic_set(funcgen, op, expr, T)
+def array_expr(funcgen, args):
+ ARRAY = funcgen.lltypemap(args[0]).TO
+ ptr = funcgen.expr(args[0])
+ index = funcgen.expr(args[1])
+ arraydef = funcgen.db.gettypedefnode(ARRAY)
+ return arraydef.itemindex_access_expr(ptr, index)
+
def stm_getarrayitem(funcgen, op):
- ARRAY = funcgen.lltypemap(op.args[0]).TO
- ptr = funcgen.expr(op.args[0])
- index = funcgen.expr(op.args[1])
- arraydef = funcgen.db.gettypedefnode(ARRAY)
- expr = arraydef.itemindex_access_expr(ptr, index)
+ expr = array_expr(funcgen, op.args)
return _stm_generic_get(funcgen, op, expr)
def stm_setarrayitem(funcgen, op):
- ARRAY = funcgen.lltypemap(op.args[0]).TO
- ptr = funcgen.expr(op.args[0])
- index = funcgen.expr(op.args[1])
- arraydef = funcgen.db.gettypedefnode(ARRAY)
- expr = arraydef.itemindex_access_expr(ptr, index)
+ expr = array_expr(funcgen, op.args)
T = op.args[2].concretetype
return _stm_generic_set(funcgen, op, expr, T)
+def stm_getinteriorfield(funcgen, op):
+ expr = funcgen.interior_expr(op.args)
+ return _stm_generic_get(funcgen, op, expr)
+
+def stm_setinteriorfield(funcgen, op):
+ expr = funcgen.interior_expr(op.args[:-1])
+ T = op.args[-1].concretetype
+ return _stm_generic_set(funcgen, op, expr, T)
+
def stm_begin_transaction(funcgen, op):
return 'STM_begin_transaction();'
diff --git a/pypy/translator/stm/llstminterp.py
b/pypy/translator/stm/llstminterp.py
--- a/pypy/translator/stm/llstminterp.py
+++ b/pypy/translator/stm/llstminterp.py
@@ -156,6 +156,14 @@
self.check_stm_mode(lambda m: m != "not_in_transaction")
LLFrame.op_setarrayitem(self, array, index, value)
+ def opstm_stm_getinteriorfield(self, obj, *offsets):
+ self.check_stm_mode(lambda m: m != "not_in_transaction")
+ return LLFrame.op_getinteriorfield(self, obj, *offsets)
+
+ def opstm_stm_setinteriorfield(self, obj, *fieldnamesval):
+ self.check_stm_mode(lambda m: m != "not_in_transaction")
+ LLFrame.op_setinteriorfield(self, obj, *fieldnamesval)
+
def opstm_stm_begin_transaction(self):
self.check_stm_mode(lambda m: m == "not_in_transaction")
self.llinterpreter.stm_mode = "regular_transaction"
diff --git a/pypy/translator/stm/test/test_funcgen.py
b/pypy/translator/stm/test/test_funcgen.py
--- a/pypy/translator/stm/test/test_funcgen.py
+++ b/pypy/translator/stm/test/test_funcgen.py
@@ -137,6 +137,61 @@
return 0
+def make_array_of_structs(T1, T2):
+ S = lltype.Struct('S', ('x', T1), ('y', T2))
+ a = lltype.malloc(lltype.GcArray(S), 3, immortal=True)
+ for i, (value1, value2) in enumerate([(1, 10), (-1, 20), (-50, -30)]):
+ a[i].x = rffi.cast(T1, value1)
+ a[i].y = rffi.cast(T2, value2)
+ return a
+
+prebuilt_array_signed_signed = make_array_of_structs(lltype.Signed,
+ lltype.Signed)
+prebuilt_array_char_char = make_array_of_structs(lltype.Char,
+ lltype.Char)
+
+def check2(array, expected1, expected2):
+ assert len(array) == len(expected1) == len(expected2)
+ for i in range(len(expected1)):
+ assert array[i].x == expected1[i]
+ assert array[i].y == expected2[i]
+check2._annspecialcase_ = 'specialize:ll'
+
+def change2(array, newvalues1, newvalues2):
+ assert len(newvalues1) <= len(array)
+ assert len(newvalues2) <= len(array)
+ for i in range(len(newvalues1)):
+ array[i].x = rffi.cast(lltype.typeOf(array).TO.OF.x, newvalues1[i])
+ for i in range(len(newvalues2)):
+ array[i].y = rffi.cast(lltype.typeOf(array).TO.OF.y, newvalues2[i])
+change2._annspecialcase_ = 'specialize:ll'
+
+def do_stm_getinteriorfield(argv):
+ check2(prebuilt_array_signed_signed, [1, -1, -50], [10, 20, -30])
+ check2(prebuilt_array_char_char, [chr(1), chr(255), chr(206)],
+ [chr(10), chr(20), chr(226)])
+ return 0
+
+def do_stm_setinteriorfield(argv):
+ change2(prebuilt_array_signed_signed, [500000, -10000000], [102101202])
+ check2(prebuilt_array_signed_signed, [500000, -10000000, -50],
+ [102101202, 20, -30])
+ change2(prebuilt_array_char_char, ['a'], ['b'])
+ check2(prebuilt_array_char_char, ['a', chr(255), chr(206)],
+ ['b', chr(20), chr(226)])
+ #
+ rstm.transaction_boundary()
+ #
+ check2(prebuilt_array_signed_signed, [500000, -10000000, -50],
+ [102101202, 20, -30])
+ check2(prebuilt_array_char_char, ['a', chr(255), chr(206)],
+ ['b', chr(20), chr(226)])
+ return 0
+
+
+# ____________________________________________________________
+
+
class TestFuncGen(CompiledSTMTests):
def test_getfield_all_sizes(self):
@@ -154,3 +209,11 @@
def test_setarrayitem_all_sizes(self):
t, cbuilder = self.compile(do_stm_setarrayitem)
cbuilder.cmdexec('')
+
+ def test_getinteriorfield_all_sizes(self):
+ t, cbuilder = self.compile(do_stm_getinteriorfield)
+ cbuilder.cmdexec('')
+
+ def test_setinteriorfield_all_sizes(self):
+ t, cbuilder = self.compile(do_stm_setinteriorfield)
+ cbuilder.cmdexec('')
diff --git a/pypy/translator/stm/test/test_transform.py
b/pypy/translator/stm/test/test_transform.py
--- a/pypy/translator/stm/test/test_transform.py
+++ b/pypy/translator/stm/test/test_transform.py
@@ -1,4 +1,4 @@
-from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.lltypesystem import lltype, llmemory, rstr
from pypy.rpython.test.test_llinterp import get_interpreter
from pypy.objspace.flow.model import summary
from pypy.translator.stm.llstminterp import eval_stm_graph
@@ -91,6 +91,26 @@
assert summary(graph) == {'stm_setarrayitem': 1}
eval_stm_graph(interp, graph, [p], stm_mode="regular_transaction")
+def test_getinteriorfield():
+ p = lltype.malloc(rstr.STR, 100, immortal=True)
+ p.chars[42] = 'X'
+ def func(p):
+ return p.chars[42]
+ interp, graph = get_interpreter(func, [p])
+ transform_graph(graph)
+ assert summary(graph) == {'stm_getinteriorfield': 1}
+ res = eval_stm_graph(interp, graph, [p], stm_mode="regular_transaction")
+ assert res == 'X'
+
+def test_setinteriorfield():
+ p = lltype.malloc(rstr.STR, 100, immortal=True)
+ def func(p):
+ p.chars[42] = 'Y'
+ interp, graph = get_interpreter(func, [p])
+ transform_graph(graph)
+ assert summary(graph) == {'stm_setinteriorfield': 1}
+ res = eval_stm_graph(interp, graph, [p], stm_mode="regular_transaction")
+
def test_unsupported_operation():
def func(n):
n += 1
diff --git a/pypy/translator/stm/transform.py b/pypy/translator/stm/transform.py
--- a/pypy/translator/stm/transform.py
+++ b/pypy/translator/stm/transform.py
@@ -151,6 +151,28 @@
op1 = SpaceOperation('stm_setarrayitem', op.args, op.result)
newoperations.append(op1)
+ def stt_getinteriorfield(self, newoperations, op):
+ OUTER = op.args[0].concretetype.TO
+ if OUTER._hints.get('immutable'):
+ op1 = op
+ elif OUTER._gckind == 'raw':
+ turn_inevitable(newoperations, "getinteriorfield-raw")
+ op1 = op
+ else:
+ op1 = SpaceOperation('stm_getinteriorfield', op.args, op.result)
+ newoperations.append(op1)
+
+ def stt_setinteriorfield(self, newoperations, op):
+ OUTER = op.args[0].concretetype.TO
+ if OUTER._hints.get('immutable'):
+ op1 = op
+ elif OUTER._gckind == 'raw':
+ turn_inevitable(newoperations, "setinteriorfield-raw")
+ op1 = op
+ else:
+ op1 = SpaceOperation('stm_setinteriorfield', op.args, op.result)
+ newoperations.append(op1)
+
def stt_stm_transaction_boundary(self, newoperations, op):
self.seen_transaction_boundary = True
v_result = op.result
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit