[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