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