Author: Antonio Cuni <[email protected]>
Branch: improve-str2charp
Changeset: r65264:db736b323df1
Date: 2013-07-08 15:43 +0200
http://bitbucket.org/pypy/pypy/changeset/db736b323df1/

Log:    1) simplify the implementation of _new_copy_contents_fun, because we
        can assume to have always the same SRC and DST type; 2) add a new
        function to copy the content of an rpython string to a raw buffer,
        using llmemory.raw_memcopy, which is much faster than doing the copy
        char-by-char

diff --git a/rpython/rtyper/lltypesystem/rstr.py 
b/rpython/rtyper/lltypesystem/rstr.py
--- a/rpython/rtyper/lltypesystem/rstr.py
+++ b/rpython/rtyper/lltypesystem/rstr.py
@@ -49,16 +49,18 @@
 def emptyunicodefun():
     return emptyunicode
 
-def _new_copy_contents_fun(SRC_TP, DST_TP, CHAR_TP, name):
-    def _str_ofs_src(item):
-        return (llmemory.offsetof(SRC_TP, 'chars') +
-                llmemory.itemoffsetof(SRC_TP.chars, 0) +
+def _new_copy_contents_fun(STR_TP, CHAR_TP, name):
+    def _str_ofs(item):
+        return (llmemory.offsetof(STR_TP, 'chars') +
+                llmemory.itemoffsetof(STR_TP.chars, 0) +
                 llmemory.sizeof(CHAR_TP) * item)
 
-    def _str_ofs_dst(item):
-        return (llmemory.offsetof(DST_TP, 'chars') +
-                llmemory.itemoffsetof(DST_TP.chars, 0) +
-                llmemory.sizeof(CHAR_TP) * item)
+    @signature(types.any(), types.int(), returns=types.any())
+    def _get_raw_buf(src, ofs):
+        assert typeOf(src).TO == STR_TP
+        assert ofs >= 0
+        return llmemory.cast_ptr_to_adr(src) + _str_ofs(ofs)
+    _get_raw_buf._always_inline_ = True
 
     @jit.oopspec('stroruni.copy_contents(src, dst, srcstart, dststart, 
length)')
     @signature(types.any(), types.any(), types.int(), types.int(), 
types.int(), returns=types.none())
@@ -71,22 +73,37 @@
         # because it might move the strings.  The keepalive_until_here()
         # are obscurely essential to make sure that the strings stay alive
         # longer than the raw_memcopy().
-        assert typeOf(src).TO == SRC_TP
-        assert typeOf(dst).TO == DST_TP
-        assert srcstart >= 0
-        assert dststart >= 0
         assert length >= 0
-        src = llmemory.cast_ptr_to_adr(src) + _str_ofs_src(srcstart)
-        dst = llmemory.cast_ptr_to_adr(dst) + _str_ofs_dst(dststart)
+        src = _get_raw_buf(src, srcstart)
+        dst = _get_raw_buf(dst, dststart)
         llmemory.raw_memcopy(src, dst, llmemory.sizeof(CHAR_TP) * length)
         keepalive_until_here(src)
         keepalive_until_here(dst)
     copy_string_contents._always_inline_ = True
-    return func_with_new_name(copy_string_contents, 'copy_%s_contents' % name)
+    copy_string_contents = func_with_new_name(copy_string_contents,
+                                              'copy_%s_contents' % name)
 
-copy_string_contents = _new_copy_contents_fun(STR, STR, Char, 'string')
-copy_unicode_contents = _new_copy_contents_fun(UNICODE, UNICODE, UniChar,
-                                               'unicode')
+    def copy_string_to_raw(src, ptrdst, srcstart, length):
+        """
+        Copies 'length' characters from the 'src' string to the 'ptrdst'
+        buffer, starting at position 'srcstart'.
+        'ptrdst' must be a non-gc Array of Char.
+        """
+        # xxx Warning: same note as above apply: don't do this at home
+        assert length >= 0
+        src = _get_raw_buf(src, srcstart)
+        adr = llmemory.cast_ptr_to_adr(ptrdst)
+        dstbuf = adr + llmemory.itemoffsetof(typeOf(ptrdst).TO, 0)
+        llmemory.raw_memcopy(src, dstbuf, llmemory.sizeof(CHAR_TP) * length)
+        keepalive_until_here(src)
+    copy_string_to_raw._always_inline_ = True
+    copy_string_to_raw = func_with_new_name(copy_string_to_raw, 
'copy_%s_to_raw' % name)
+
+    return copy_string_to_raw, copy_string_contents
+
+copy_string_to_raw, copy_string_contents = _new_copy_contents_fun(STR, Char, 
'string')
+copy_unicode_do_raw, copy_unicode_contents = _new_copy_contents_fun(UNICODE,
+                                                                    UniChar, 
'unicode')
 
 CONST_STR_CACHE = WeakValueDictionary()
 CONST_UNICODE_CACHE = WeakValueDictionary()
diff --git a/rpython/rtyper/test/test_rstr.py b/rpython/rtyper/test/test_rstr.py
--- a/rpython/rtyper/test/test_rstr.py
+++ b/rpython/rtyper/test/test_rstr.py
@@ -1118,6 +1118,30 @@
         res = self.interpret(f, [5])
         assert res == 0
 
+    def test_copy_string_to_raw(self):
+        from rpython.rtyper.lltypesystem import lltype, llmemory
+        from rpython.rtyper.annlowlevel import llstr
+        from rpython.rtyper.lltypesystem.rstr import copy_string_to_raw
+
+        def f(buf, n):
+            s = 'abc' * n
+            ll_s = llstr(s)
+            copy_string_to_raw(ll_s, buf, 0, n*3)
+
+        TP = lltype.Array(lltype.Char)
+        array = lltype.malloc(TP, 12, flavor='raw')
+        f(array, 4)
+        assert list(array) == list('abc'*4)
+        lltype.free(array, flavor='raw')
+
+        array = lltype.malloc(TP, 12, flavor='raw')
+        self.interpret(f, [array, 4])
+        assert list(array) == list('abc'*4)
+        lltype.free(array, flavor='raw')
+        
+
+
+        
 
 class TestOOtype(BaseTestRstr, OORtypeMixin):
     pass
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to