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

Reply via email to