Author: Antonio Cuni <[email protected]>
Branch: faster-rstruct
Changeset: r80898:89a3ecaf0b2d
Date: 2015-11-24 18:05 +0100
http://bitbucket.org/pypy/pypy/changeset/89a3ecaf0b2d/
Log: in case of cross-compilation we need to delay the comparison of
offsets until compile time (where FieldOffset is a symbolic
correctly handled by the C compiler). However, we need to introduce
a bit of extra machinery to make it working also in direct tests and
on top of llinterp
diff --git a/rpython/rlib/strstorage.py b/rpython/rlib/strstorage.py
--- a/rpython/rlib/strstorage.py
+++ b/rpython/rlib/strstorage.py
@@ -30,22 +30,10 @@
from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
from rpython.rtyper.lltypesystem.rstr import STR, _get_raw_str_buf
from rpython.rtyper.annlowlevel import llstr
-from rpython.rlib.objectmodel import specialize
-
-def compute_offsetof(TP, field):
- """
- NOT_RPYTHON
- """
- obj = lltype.malloc(TP, 0)
- baseadr = llmemory.cast_ptr_to_adr(obj)
- offset = llmemory.offsetof(TP, field)
- interioradr = baseadr + offset
- return (llmemory.cast_adr_to_int(interioradr, 'forced') -
- llmemory.cast_adr_to_int(baseadr, 'forced'))
-
+from rpython.rlib.objectmodel import specialize, we_are_translated
@specialize.memo()
-def rpy_string_as_type(TP):
+def _rpy_string_as_type(TP):
# sanity check that STR is actually what we think it is
assert STR._flds == {
'hash': lltype.Signed,
@@ -54,23 +42,32 @@
STR_AS_TP = lltype.GcStruct('rpy_string_as_%s' % TP,
('hash', lltype.Signed),
('chars', lltype.Array(TP, hints={'immutable':
True})))
- # sanity check
- assert compute_offsetof(STR, 'chars') == compute_offsetof(STR_AS_TP,
'chars')
return STR_AS_TP
[email protected]()
[email protected](0)
def str_storage_supported(TP):
- try:
- rpy_string_as_type(TP)
- except AssertionError:
- return False
- else:
- return True
+ STR_AS_TP = _rpy_string_as_type(TP)
+ return _offsetof_chars(STR) == _offsetof_chars(STR_AS_TP)
@specialize.ll()
def str_storage_getitem(TP, s, index):
- STR_AS_TP = rpy_string_as_type(TP)
+ assert str_storage_supported(TP) # sanity check
+ STR_AS_TP = _rpy_string_as_type(TP)
lls = llstr(s)
str_as_tp = rffi.cast(lltype.Ptr(STR_AS_TP), lls)
index = index / rffi.sizeof(TP)
return str_as_tp.chars[index]
+
[email protected](0)
+def _offsetof_chars(TP):
+ # we need to be careful in presence of cross-compilation, because we want
+ # to defer the actual check at compile-time on the target machine, NOT at
+ # translation time on the host machine. However, we still need to support
+ # direct tests, so if we are not translated, we immediately force the
+ # result into an actual int.
+ offset = llmemory.offsetof(TP, 'chars')
+ if we_are_translated():
+ return offset # symbolic
+ else:
+ return offset.force_as_int()
+ return offset
diff --git a/rpython/rlib/test/test_strstorage.py
b/rpython/rlib/test/test_strstorage.py
--- a/rpython/rlib/test/test_strstorage.py
+++ b/rpython/rlib/test/test_strstorage.py
@@ -1,12 +1,29 @@
import py
+import sys
+import platform
import struct
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rlib.strstorage import str_storage_getitem, str_storage_supported
from rpython.rlib.rarithmetic import r_singlefloat
from rpython.rtyper.test.tool import BaseRtypingTest
+IS_WIN32 = (sys.platform == 'win32')
+IS_ARM = (platform.machine().startswith('arm'))
+IS_32BIT = (sys.maxint == 2147483647)
+
class BaseStrStorageTest:
+ def test_str_getitem_supported(self):
+ # on win32 or ARM32, we expect LONGLONG and DOUBLE to be NOT supported
+ # by str_storage_getitem
+ if IS_WIN32 or (IS_ARM and IS_32BIT):
+ expected = False
+ else:
+ expected = True
+ #
+ assert self.str_storage_supported(rffi.LONGLONG) == expected
+ assert self.str_storage_supported(rffi.DOUBLE) == expected
+
def test_signed(self):
buf = struct.pack('@ll', 42, 43)
size = struct.calcsize('@l')
@@ -40,11 +57,18 @@
class TestDirect(BaseStrStorageTest):
+ def str_storage_supported(self, TYPE):
+ return str_storage_supported(TYPE)
+
def str_storage_getitem(self, TYPE, buf, offset):
return str_storage_getitem(TYPE, buf, offset)
+class TestRTyping(BaseStrStorageTest, BaseRtypingTest):
-class TestRTyping(BaseStrStorageTest, BaseRtypingTest):
+ def str_storage_supported(self, TYPE):
+ def fn():
+ return str_storage_supported(TYPE)
+ return self.interpret(fn, [])
def str_storage_getitem(self, TYPE, buf, offset):
def fn(offset):
diff --git a/rpython/rtyper/lltypesystem/llmemory.py
b/rpython/rtyper/lltypesystem/llmemory.py
--- a/rpython/rtyper/lltypesystem/llmemory.py
+++ b/rpython/rtyper/lltypesystem/llmemory.py
@@ -214,6 +214,20 @@
dst = cast_adr_to_ptr(dstadr, PTR)
_reccopy(src, dst)
+ def force_as_int(self):
+ """
+ NOT_RPYTHON
+ Return the actual offset as an integer.
+ """
+ if self.TYPE._arrayfld:
+ obj = lltype.malloc(self.TYPE, 0)
+ else:
+ obj = lltype.malloc(self.TYPE)
+ baseadr = cast_ptr_to_adr(obj)
+ interioradr = baseadr + self
+ return cast_adr_to_int(interioradr, 'forced') -
cast_adr_to_int(baseadr, 'forced')
+
+
class CompositeOffset(AddressOffset):
diff --git a/rpython/rtyper/lltypesystem/opimpl.py
b/rpython/rtyper/lltypesystem/opimpl.py
--- a/rpython/rtyper/lltypesystem/opimpl.py
+++ b/rpython/rtyper/lltypesystem/opimpl.py
@@ -103,6 +103,13 @@
def op_int_eq(x, y):
+ # so far we support only == and only for FieldOffset. In theory, we could
+ # generalize support for direct comparisons of AddressOffsets
+ if isinstance(x, llmemory.FieldOffset):
+ x = x.force_as_int()
+ if isinstance(y, llmemory.FieldOffset):
+ y = y.force_as_int()
+ #
if not isinstance(x, (int, long)):
from rpython.rtyper.lltypesystem import llgroup
assert isinstance(x, llgroup.CombinedSymbolic), (
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit