[pypy-commit] pypy faster-rstruct: introduce rawstorage.str_storage_getitem{, _unaligned}, which works as rawstorage.raw_storage_* but operates on RPython strings instead of raw buffers: since strings are immutable, we provide only the functions for reading out of them, not writing
antocuni
noreply at buildbot.pypy.org
Fri Nov 13 11:36:32 EST 2015
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: faster-rstruct
Changeset: r80668:84c49eed1754
Date: 2015-05-15 22:38 +0200
http://bitbucket.org/pypy/pypy/changeset/84c49eed1754/
Log: introduce rawstorage.str_storage_getitem{,_unaligned}, which works
as rawstorage.raw_storage_* but operates on RPython strings instead
of raw buffers: since strings are immutable, we provide only the
functions for reading out of them, not writing
diff --git a/rpython/rlib/rawstorage.py b/rpython/rlib/rawstorage.py
--- a/rpython/rlib/rawstorage.py
+++ b/rpython/rlib/rawstorage.py
@@ -1,10 +1,13 @@
-from rpython.rlib.objectmodel import we_are_translated
+from rpython.rlib.objectmodel import we_are_translated, keepalive_until_here
from rpython.rtyper.extregistry import ExtRegistryEntry
from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
from rpython.annotator import model as annmodel
from rpython.rtyper.llannotation import lltype_to_annotation
+from rpython.rlib import rgc
from rpython.rlib.rgc import lltype_is_gc
from rpython.rlib.objectmodel import specialize
+from rpython.rtyper.lltypesystem.rstr import STR, _get_raw_str_buf
+from rpython.rtyper.annlowlevel import llstr
RAW_STORAGE = rffi.CCHARP.TO
RAW_STORAGE_PTR = rffi.CCHARP
@@ -40,6 +43,29 @@
def free_raw_storage(storage, track_allocation=True):
lltype.free(storage, flavor='raw', track_allocation=track_allocation)
+
+ at rgc.no_collect
+def str_storage_getitem(TP, s, index):
+ lls = llstr(s)
+ # from here, no GC operations can happen
+ buf = _get_raw_str_buf(STR, lls, 0)
+ storage = rffi.cast(RAW_STORAGE_PTR, buf)
+ res = raw_storage_getitem(TP, storage, index)
+ # end of "no GC" section
+ keepalive_until_here(lls)
+ return res
+
+ at rgc.no_collect
+def str_storage_getitem_unaligned(TP, s, index):
+ lls = llstr(s)
+ # from here, no GC operations can happen
+ buf = _get_raw_str_buf(STR, lls, 0)
+ storage = rffi.cast(RAW_STORAGE_PTR, buf)
+ res = raw_storage_getitem_unaligned(TP, storage, index)
+ # end of "no GC" section
+ keepalive_until_here(lls)
+ return res
+
# ____________________________________________________________
#
# Support for possibly-unaligned accesses
diff --git a/rpython/rlib/test/test_rawstorage.py b/rpython/rlib/test/test_rawstorage.py
--- a/rpython/rlib/test/test_rawstorage.py
+++ b/rpython/rlib/test/test_rawstorage.py
@@ -4,7 +4,8 @@
from rpython.rlib import rawstorage
from rpython.rlib.rawstorage import alloc_raw_storage, free_raw_storage,\
raw_storage_setitem, raw_storage_getitem, AlignmentError,\
- raw_storage_setitem_unaligned, raw_storage_getitem_unaligned
+ raw_storage_setitem_unaligned, raw_storage_getitem_unaligned,\
+ str_storage_getitem, str_storage_getitem_unaligned
from rpython.rtyper.test.tool import BaseRtypingTest
from rpython.translator.c.test.test_genc import compile
@@ -32,6 +33,26 @@
assert res == 3.14
free_raw_storage(r)
+def test_untranslated_str_storage():
+ import struct
+ buf = struct.pack('@lld', 42, 43, 123.0)
+ size = struct.calcsize('@l')
+ res = str_storage_getitem(lltype.Signed, buf, 0)
+ assert res == 42
+ res = str_storage_getitem(lltype.Signed, buf, size)
+ assert res == 43
+ res = str_storage_getitem(lltype.Float, buf, size*2)
+ assert res == 123.0
+
+def test_untranslated_str_storage_unaligned(monkeypatch):
+ import struct
+ monkeypatch.setattr(rawstorage, 'misaligned_is_fine', False)
+ buf = 'foo' + struct.pack('@ll', 42, 43)
+ size = struct.calcsize('@l')
+ res = str_storage_getitem_unaligned(lltype.Signed, buf, 3)
+ assert res == 42
+ res = str_storage_getitem_unaligned(lltype.Signed, buf, size+3)
+ assert res == 43
class TestRawStorage(BaseRtypingTest):
@@ -46,6 +67,21 @@
x = self.interpret(f, [1<<30])
assert x == 1 << 30
+ def test_str_storage_int(self):
+ import struct
+ buf = struct.pack('@ll', 42, 43)
+ size = struct.calcsize('@l')
+
+ def f(i):
+ res = str_storage_getitem(lltype.Signed, buf, i)
+ return res
+
+ x = self.interpret(f, [0])
+ assert x == 42
+ x = self.interpret(f, [8])
+ assert x == 43
+
+
def test_storage_float_unaligned(self, monkeypatch):
def f(v):
r = alloc_raw_storage(24)
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
@@ -60,6 +60,13 @@
@signature(types.any(), types.any(), types.int(), returns=types.any())
@specialize.arg(0)
def _get_raw_buf(TP, src, ofs):
+ """
+ WARNING: dragons ahead.
+ Return the address of the internal char* buffer of the low level
+ string. The return value is valid as long as no GC operation occur, so
+ you must ensure that it will be used inside a "GC safe" section, for
+ example by marking your function with @rgc.no_collect
+ """
assert typeOf(src).TO == TP
assert ofs >= 0
return llmemory.cast_ptr_to_adr(src) + _str_ofs(TP, ofs)
@@ -129,11 +136,17 @@
copy_raw_to_string = func_with_new_name(copy_raw_to_string,
'copy_raw_to_%s' % name)
- return copy_string_to_raw, copy_raw_to_string, copy_string_contents
+ return _get_raw_buf, copy_string_to_raw, copy_raw_to_string, copy_string_contents
-copy_string_to_raw, copy_raw_to_string, copy_string_contents = _new_copy_contents_fun(STR, STR, Char, 'string')
-copy_unicode_to_raw, copy_raw_to_unicode, copy_unicode_contents = _new_copy_contents_fun(UNICODE, UNICODE,
- UniChar, 'unicode')
+(_get_raw_str_buf,
+ copy_string_to_raw,
+ copy_raw_to_string,
+ copy_string_contents) = _new_copy_contents_fun(STR, STR, Char, 'string')
+
+(_get_raw_unicode_buf,
+ copy_unicode_to_raw,
+ copy_raw_to_unicode,
+ copy_unicode_contents) = _new_copy_contents_fun(UNICODE, UNICODE, UniChar, 'unicode')
CONST_STR_CACHE = WeakValueDictionary()
CONST_UNICODE_CACHE = WeakValueDictionary()
More information about the pypy-commit
mailing list