[pypy-commit] pypy stm: interiorfield operations.

arigo noreply at buildbot.pypy.org
Sat Nov 5 18:03:08 CET 2011


Author: Armin Rigo <arigo at tunes.org>
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


More information about the pypy-commit mailing list