Author: Armin Rigo <[email protected]>
Branch: stm
Changeset: r48788:dc24a8407e9e
Date: 2011-11-05 15:40 +0100
http://bitbucket.org/pypy/pypy/changeset/dc24a8407e9e/

Log:    getarrayitem in funcgen.py. Refactor test_funcgen to actually test
        something :-(

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
@@ -598,6 +598,8 @@
         return self.op_stm(op)
     OP_STM_GETFIELD = _OP_STM
     OP_STM_SETFIELD = _OP_STM
+    OP_STM_GETARRAYITEM = _OP_STM
+    OP_STM_SETARRAYITEM = _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
@@ -4,12 +4,7 @@
 from pypy.translator.stm.rstm import size_of_voidp
 
 
-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)
-    basename = funcgen.expr(op.args[0])
-    fieldname = op.args[1].value
+def _stm_generic_get(funcgen, op, expr):
     T = funcgen.lltypemap(op.result)
     fieldtypename = funcgen.db.gettype(T)
     cfieldtypename = cdecl(fieldtypename, '')
@@ -29,19 +24,34 @@
             funcname = 'stm_read_doubleword'
         else:
             raise NotImplementedError(fieldsize)
-        expr = structdef.ptr_access_expr(basename,
-                                         fieldname,
-                                         baseexpr_is_const)
         return '%s = (%s)%s((long*)&%s);' % (
             newvalue, cfieldtypename, funcname, expr)
     else:
-        # assume that the object is aligned, and any possible misalignment
-        # comes from the field offset, so that it can be resolved at
-        # compile-time (by using C macros)
-        return '%s = STM_read_partial_word(%s, %s, offsetof(%s, %s));' % (
-            newvalue, cfieldtypename, basename,
-            cdecl(funcgen.db.gettype(STRUCT), ''),
-            structdef.c_struct_field_name(fieldname))
+        STRUCT = funcgen.lltypemap(op.args[0]).TO
+        if isinstance(STRUCT, lltype.Struct):
+            # assume that the object is aligned, and any possible misalignment
+            # comes from the field offset, so that it can be resolved at
+            # compile-time (by using C macros)
+            structdef = funcgen.db.gettypedefnode(STRUCT)
+            basename = funcgen.expr(op.args[0])
+            fieldname = op.args[1].value
+            return '%s = STM_read_partial_word(%s, %s, offsetof(%s, %s));' % (
+                newvalue, cfieldtypename, basename,
+                cdecl(funcgen.db.gettype(STRUCT), ''),
+                structdef.c_struct_field_name(fieldname))
+        #
+        else:
+            return '%s = stm_read_partial_word(sizeof(%s), &%s);' % (
+                newvalue, cfieldtypename, expr)
+
+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)
+    return _stm_generic_get(funcgen, op, expr)
 
 def stm_setfield(funcgen, op):
     STRUCT = funcgen.lltypemap(op.args[0]).TO
@@ -53,6 +63,10 @@
     fieldtypename = funcgen.db.gettype(T)
     newvalue = funcgen.expr(op.args[2], special_case_void=False)
     #
+    expr = structdef.ptr_access_expr(basename,
+                                     fieldname,
+                                     baseexpr_is_const)
+    #
     assert T is not lltype.Void     # XXX
     fieldsize = rffi.sizeof(T)
     if fieldsize >= size_of_voidp or T == lltype.SingleFloat:
@@ -71,18 +85,21 @@
             newtype = 'long long'
         else:
             raise NotImplementedError(fieldsize)
-        expr = structdef.ptr_access_expr(basename,
-                                         fieldname,
-                                         baseexpr_is_const)
         return '%s((long*)&%s, (%s)%s);' % (
             funcname, expr, newtype, newvalue)
     else:
         cfieldtypename = cdecl(fieldtypename, '')
-        return ('stm_write_partial_word(sizeof(%s), (char*)%s, '
-                'offsetof(%s, %s), (long)%s);' % (
-            cfieldtypename, basename,
-            cdecl(funcgen.db.gettype(STRUCT), ''),
-            structdef.c_struct_field_name(fieldname), newvalue))
+        return ('stm_write_partial_word(sizeof(%s), &%s, %s);' % (
+            cfieldtypename, expr, newvalue))
+
+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)
+    return _stm_generic_get(funcgen, op, expr)
+
 
 def stm_begin_transaction(funcgen, op):
     return 'STM_begin_transaction();'
diff --git a/pypy/translator/stm/src_stm/et.c b/pypy/translator/stm/src_stm/et.c
--- a/pypy/translator/stm/src_stm/et.c
+++ b/pypy/translator/stm/src_stm/et.c
@@ -869,11 +869,19 @@
 }
 
 // XXX little-endian only!
-void stm_write_partial_word(int fieldsize, char *base, long offset,
-                            unsigned long nval)
+unsigned long stm_read_partial_word(int fieldsize, char *addr)
 {
-  long *p = (long*)(base + (offset & ~(sizeof(void*)-1)));
-  int misalignment = offset & (sizeof(void*)-1);
+  int misalignment = ((long)addr) & (sizeof(void*)-1);
+  long *p = (long*)(addr - misalignment);
+  unsigned long word = stm_read_word(p);
+  return word >> (misalignment * 8);
+}
+
+// XXX little-endian only!
+void stm_write_partial_word(int fieldsize, char *addr, unsigned long nval)
+{
+  int misalignment = ((long)addr) & (sizeof(void*)-1);
+  long *p = (long*)(addr - misalignment);
   long val = nval << (misalignment * 8);
   long word = stm_read_word(p);
   long mask = ((1L << (fieldsize * 8)) - 1) << (misalignment * 8);
diff --git a/pypy/translator/stm/src_stm/et.h b/pypy/translator/stm/src_stm/et.h
--- a/pypy/translator/stm/src_stm/et.h
+++ b/pypy/translator/stm/src_stm/et.h
@@ -54,8 +54,8 @@
            (long*)(((char*)(base)) + ((offset) & ~(sizeof(void*)-1))))  \
         >> (8 * ((offset) & (sizeof(void*)-1))))
 
-void stm_write_partial_word(int fieldsize, char *base, long offset,
-                            unsigned long nval);
+unsigned long stm_read_partial_word(int fieldsize, char *addr);
+void stm_write_partial_word(int fieldsize, char *addr, unsigned long nval);
 
 double stm_read_double(long *addr);
 void stm_write_double(long *addr, double val);
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
@@ -1,14 +1,14 @@
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rlib.rarithmetic import r_longlong, r_singlefloat
 from pypy.translator.stm.test.test_transform import CompiledSTMTests
 from pypy.translator.stm import rstm
 
 
-A = lltype.Struct('A', ('x', lltype.Signed), ('y', lltype.Signed),
-                       ('c1', lltype.Char), ('c2', lltype.Char),
-                       ('c3', lltype.Char), ('l', lltype.SignedLongLong),
-                       ('f', lltype.Float), ('sa', lltype.SingleFloat),
-                       ('sb', lltype.SingleFloat))
+A = lltype.GcStruct('A', ('x', lltype.Signed), ('y', lltype.Signed),
+                         ('c1', lltype.Char), ('c2', lltype.Char),
+                         ('c3', lltype.Char), ('l', lltype.SignedLongLong),
+                         ('f', lltype.Float), ('sa', lltype.SingleFloat),
+                         ('sb', lltype.SingleFloat))
 rll1 = r_longlong(-10000000000003)
 rll2 = r_longlong(-300400500600700)
 rf1 = -12.38976129
@@ -19,7 +19,7 @@
 rs2b = r_singlefloat(-9e9)
 
 def make_a_1():
-    a = lltype.malloc(A, flavor='raw')
+    a = lltype.malloc(A, immortal=True)
     a.x = -611
     a.c1 = '/'
     a.c2 = '\\'
@@ -30,11 +30,10 @@
     a.sa = rs1a
     a.sb = rs1b
     return a
-make_a_1._dont_inline_ = True
+a_prebuilt = make_a_1()
 
 def do_stm_getfield(argv):
-    a = make_a_1()
-    #
+    a = a_prebuilt
     assert a.x == -611
     assert a.c1 == '/'
     assert a.c2 == '\\'
@@ -44,12 +43,10 @@
     assert a.f == rf1
     assert float(a.sa) == float(rs1a)
     assert float(a.sb) == float(rs1b)
-    #
-    lltype.free(a, flavor='raw')
     return 0
 
 def do_stm_setfield(argv):
-    a = make_a_1()
+    a = a_prebuilt
     #
     a.x = 12871981
     a.c1 = '('
@@ -86,7 +83,28 @@
     assert float(a.sa) == float(rs2a)
     assert float(a.sb) == float(rs2b)
     #
-    lltype.free(a, flavor='raw')
+    return 0
+
+
+def make_array(OF):
+    a = lltype.malloc(lltype.GcArray(OF), 5, immortal=True)
+    for i, value in enumerate([1, 10, -1, -10, 42]):
+        a[i] = rffi.cast(OF, value)
+    return a
+
+prebuilt_array_signed = make_array(lltype.Signed)
+prebuilt_array_char   = make_array(lltype.Char)
+
+def check(array, expected):
+    assert len(array) == len(expected)
+    for i in range(len(expected)):
+        assert array[i] == expected[i]
+check._annspecialcase_ = 'specialize:ll'
+
+def do_stm_getarrayitem(argv):
+    check(prebuilt_array_signed, [1, 10, -1, -10, 42])
+    check(prebuilt_array_char,   [chr(1), chr(10), chr(255),
+                                  chr(246), chr(42)])
     return 0
 
 
@@ -99,3 +117,7 @@
     def test_setfield_all_sizes(self):
         t, cbuilder = self.compile(do_stm_setfield)
         cbuilder.cmdexec('')
+
+    def test_getarrayitem_all_sizes(self):
+        t, cbuilder = self.compile(do_stm_getarrayitem)
+        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
@@ -56,6 +56,18 @@
     res = eval_stm_graph(interp, graph, [p], stm_mode="regular_transaction")
     assert res == 42
 
+def test_getarraysize():
+    A = lltype.GcArray(lltype.Signed)
+    p = lltype.malloc(A, 100, immortal=True)
+    p[42] = 666
+    def func(p):
+        return len(p)
+    interp, graph = get_interpreter(func, [p])
+    transform_graph(graph)
+    assert summary(graph) == {'getarraysize': 1}
+    res = eval_stm_graph(interp, graph, [p], stm_mode="regular_transaction")
+    assert res == 100
+
 def test_getarrayitem():
     A = lltype.GcArray(lltype.Signed)
     p = lltype.malloc(A, 100, immortal=True)
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
@@ -129,7 +129,7 @@
             op1 = SpaceOperation('stm_setfield', op.args, op.result)
         newoperations.append(op1)
 
-    def FINISHME_stt_getarrayitem(self, newoperations, op):
+    def stt_getarrayitem(self, newoperations, op):
         ARRAY = op.args[0].concretetype.TO
         if ARRAY._immutable_field():
             op1 = op
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to