[pypy-commit] pypy faster-rstruct-2: introduce GCBuffer, to share the implementation of typed_read and type_write among all buffers which are baked by GC-managed memory. Use it for StringBuffer and BytearrayBuffer

antocuni pypy.commits at gmail.com
Mon May 15 11:09:59 EDT 2017


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: faster-rstruct-2
Changeset: r91301:d59317a1258f
Date: 2017-05-15 16:52 +0200
http://bitbucket.org/pypy/pypy/changeset/d59317a1258f/

Log:	introduce GCBuffer, to share the implementation of typed_read and
	type_write among all buffers which are baked by GC-managed memory.
	Use it for StringBuffer and BytearrayBuffer

diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -9,7 +9,7 @@
                               nonmoving_raw_ptr_for_resizable_list,
                               ll_for_resizable_list)
 from rpython.rlib import jit
-from rpython.rlib.buffer import Buffer
+from rpython.rlib.buffer import GCBuffer
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec
@@ -1257,7 +1257,7 @@
         start += step
 
 
-class BytearrayBuffer(Buffer):
+class BytearrayBuffer(GCBuffer):
     _immutable_ = True
 
     def __init__(self, ba, readonly=False):
@@ -1308,25 +1308,7 @@
         ll_items = ll_data.items
         LIST = lltype.typeOf(ll_data).TO # rlist.LIST_OF(lltype.Char)
         base_ofs = llmemory.itemoffsetof(LIST.items.TO, 0)
-        scale_factor = llmemory.sizeof(lltype.Char)
-        return ll_items, scale_factor, base_ofs
-
-    @specialize.ll_and_arg(1)
-    def typed_read(self, TP, byte_offset):
-        from rpython.rtyper.lltypesystem.lloperation import llop
-        ll_items, scale_factor, base_ofs = self._get_gc_data()
-        return llop.gc_load_indexed(TP, ll_items, byte_offset,
-                                    scale_factor, base_ofs)
-
-    @specialize.ll_and_arg(1)
-    def typed_write(self, TP, byte_offset, value):
-        from rpython.rtyper.lltypesystem import lltype
-        from rpython.rtyper.lltypesystem.lloperation import llop
-        ll_items, scale_factor, base_ofs = self._get_gc_data()
-        value = lltype.cast_primitive(TP, value)
-        return llop.gc_store_indexed(lltype.Void, ll_items, byte_offset, value,
-                                     scale_factor, base_ofs)
-
+        return ll_items, base_ofs
 
 
 @specialize.argtype(1)
diff --git a/rpython/rlib/buffer.py b/rpython/rlib/buffer.py
--- a/rpython/rlib/buffer.py
+++ b/rpython/rlib/buffer.py
@@ -26,7 +26,13 @@
     """
 
 class Buffer(object):
-    """Base class for buffers of bytes"""
+    """
+    Base class for buffers of bytes.
+
+    Most probably, you do NOT want to use this as a base class, but either
+    GCBuffer or RawBuffer, so that you automatically get the proper
+    implementation of typed_read and typed_write.
+    """
     _attrs_ = ['readonly']
     _immutable_ = True
 
@@ -89,7 +95,8 @@
 class RawBuffer(Buffer):
     """
     A buffer which is baked by a raw, non-movable memory area. It implementes
-    typed_read in terms of get_raw_address()
+    typed_read and typed_write in terms of get_raw_address(), llop.raw_load,
+    llop.raw_store.
 
     NOTE: this assumes that get_raw_address() is cheap. Do not use this as a
     base class if get_raw_address() is potentially costly, like for example if
@@ -117,6 +124,49 @@
         return llop.raw_store(lltype.Void, ptr, byte_offset, value)
 
 
+class GCBuffer(Buffer):
+    """
+    A buffer which is baked by a GC-managed memory area. It implements
+    typed_read and typed_write in terms of llop.gc_load_indexed and
+    llop.gc_store_indexed.
+
+    Subclasses MUST override the _get_gc_data method.
+    """
+    _immutable_ = True
+    _attrs_ = ['readonly']
+
+    def _get_gc_data(self):
+        """
+        Return a tuple (data, base_offset), whose items can be used with
+        llop.gc_{load,store}_indexed.
+        """
+        raise NotImplementedError
+
+    @specialize.ll_and_arg(1)
+    def typed_read(self, TP, byte_offset):
+        """
+        Read the value of type TP starting at byte_offset. No bounds checks
+        """
+        lldata, base_ofs = self._get_gc_data()
+        scale_factor = llmemory.sizeof(lltype.Char)
+        return llop.gc_load_indexed(TP, lldata, byte_offset,
+                                    scale_factor, base_ofs)
+
+    @specialize.ll_and_arg(1)
+    def typed_write(self, TP, byte_offset, value):
+        """
+        Write the value of type TP at byte_offset. No bounds checks
+        """
+        if self.readonly:
+            raise CannotWrite
+        lldata, base_ofs = self._get_gc_data()
+        scale_factor = llmemory.sizeof(lltype.Char)
+        value = lltype.cast_primitive(TP, value)
+        return llop.gc_store_indexed(lltype.Void, lldata, byte_offset, value,
+                                     scale_factor, base_ofs)
+
+
+
 class ByteBuffer(Buffer):
     _immutable_ = True
 
@@ -137,7 +187,7 @@
         return nonmoving_raw_ptr_for_resizable_list(self.data)
 
 
-class StringBuffer(Buffer):
+class StringBuffer(GCBuffer):
     _attrs_ = ['readonly', 'value']
     _immutable_ = True
 
@@ -170,17 +220,11 @@
         # may still raise ValueError on some GCs
         return rffi.get_raw_address_of_string(self.value)
 
-    @specialize.ll_and_arg(1)
-    def typed_read(self, TP, byte_offset):
-        # WARNING: the 'byte_offset' is, as its name says, measured in bytes;
-        # however, it should be aligned for TP, otherwise on some platforms this
-        # code will crash!
+    def _get_gc_data(self):
         lls = llstr(self.value)
         base_ofs = (llmemory.offsetof(STR, 'chars') +
                     llmemory.itemoffsetof(STR.chars, 0))
-        scale_factor = llmemory.sizeof(lltype.Char)
-        return llop.gc_load_indexed(TP, lls, byte_offset,
-                                    scale_factor, base_ofs)
+        return lls, base_ofs
 
 
 class SubBuffer(Buffer):


More information about the pypy-commit mailing list