Author: Antonio Cuni <[email protected]>
Branch: virtual-raw-mallocs
Changeset: r59532:493bb1d1385d
Date: 2012-12-22 10:26 +0100
http://bitbucket.org/pypy/pypy/changeset/493bb1d1385d/
Log: bah, it might happen that we have two arraydescrs which are equal
but not identical: apply the optimization also in those cases
diff --git a/pypy/jit/metainterp/optimizeopt/rawbuffer.py
b/pypy/jit/metainterp/optimizeopt/rawbuffer.py
--- a/pypy/jit/metainterp/optimizeopt/rawbuffer.py
+++ b/pypy/jit/metainterp/optimizeopt/rawbuffer.py
@@ -8,13 +8,14 @@
pass
class RawBuffer(object):
- def __init__(self):
+ def __init__(self, cpu):
# the following lists represents the writes in the buffer: values[i]
# is the value of length lengths[i] stored at offset[i].
#
# the invariant is that they are ordered by offset, and that
# offset[i]+length[i] <= offset[i+1], i.e. that the writes never
# overlaps
+ self.cpu = cpu
self.offsets = []
self.lengths = []
self.descrs = []
@@ -27,12 +28,19 @@
"""
return zip(self.offsets, self.lengths, self.descrs, self.values)
+ def _descrs_are_compatible(self, d1, d2):
+ # two arraydescrs are compatible if they have the same basesize,
+ # itemsize and sign, even if they are not identical
+ unpack = self.cpu.unpack_arraydescr_size
+ return unpack(d1) == unpack(d2)
+
def write_value(self, offset, length, descr, value):
i = 0
N = len(self.offsets)
while i < N:
if self.offsets[i] == offset:
- if length != self.lengths[i] or descr != self.descrs[i]:
+ if (length != self.lengths[i] or not
+ self._descrs_are_compatible(descr, self.descrs[i])):
# in theory we could add support for the cases in which
# the length or descr is different, but I don't think we
# need it in practice
@@ -59,7 +67,8 @@
N = len(self.offsets)
while i < N:
if self.offsets[i] == offset:
- if length != self.lengths[i] or descr != self.descrs[i]:
+ if (length != self.lengths[i] or
+ not self._descrs_are_compatible(descr, self.descrs[i])):
raise InvalidRawRead
return self.values[i]
i += 1
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_rawbuffer.py
b/pypy/jit/metainterp/optimizeopt/test/test_rawbuffer.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_rawbuffer.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_rawbuffer.py
@@ -2,8 +2,12 @@
from pypy.jit.metainterp.optimizeopt.rawbuffer import (InvalidRawWrite,
InvalidRawRead,
RawBuffer)
+class FakeCPU(object):
+ def unpack_arraydescr_size(self, descr):
+ return descr, 'foo', 'bar'
+
def test_write_value():
- buf = RawBuffer()
+ buf = RawBuffer(FakeCPU())
buf.write_value(8, 4, 'descr3', 'three')
buf.write_value(0, 4, 'descr1', 'one')
buf.write_value(4, 2, 'descr2', 'two')
@@ -17,7 +21,7 @@
#
def test_write_value_update():
- buf = RawBuffer()
+ buf = RawBuffer(FakeCPU())
buf.write_value(0, 4, 'descr', 'one')
buf.write_value(4, 2, 'descr', 'two')
buf.write_value(0, 4, 'descr', 'ONE')
@@ -27,7 +31,7 @@
]
def test_write_value_invalid_length():
- buf = RawBuffer()
+ buf = RawBuffer(FakeCPU())
buf.write_value(0, 4, 'descr1', 'one')
with py.test.raises(InvalidRawWrite):
buf.write_value(0, 5, 'descr1', 'two')
@@ -36,20 +40,20 @@
def test_write_value_overlapping_next():
- buf = RawBuffer()
+ buf = RawBuffer(FakeCPU())
buf.write_value(0, 4, 'descr', 'one')
buf.write_value(6, 4, 'descr', 'two')
with py.test.raises(InvalidRawWrite):
buf.write_value(4, 4, 'descr', 'three')
def test_write_value_overlapping_prev():
- buf = RawBuffer()
+ buf = RawBuffer(FakeCPU())
buf.write_value(0, 4, 'descr', 'one')
with py.test.raises(InvalidRawWrite):
buf.write_value(2, 1, 'descr', 'two')
def test_read_value():
- buf = RawBuffer()
+ buf = RawBuffer(FakeCPU())
buf.write_value(0, 4, 'descr', 'one')
buf.write_value(4, 4, 'descr', 'two')
assert buf.read_value(0, 4, 'descr') == 'one'
@@ -61,3 +65,26 @@
with py.test.raises(InvalidRawRead):
buf.read_value(0, 4, 'another descr')
+def test_unpack_descrs():
+ ArrayS_8_1 = object()
+ ArrayS_8_2 = object()
+ ArrayU_8 = object()
+
+ class FakeCPU(object):
+ def unpack_arraydescr_size(self, descr):
+ if descr in (ArrayS_8_1, ArrayS_8_2):
+ return 0, 8, True
+ return 0, 8, False
+
+ buf = RawBuffer(FakeCPU())
+ buf.write_value(0, 4, ArrayS_8_1, 'one')
+ assert buf.read_value(0, 4, ArrayS_8_1) == 'one'
+ assert buf.read_value(0, 4, ArrayS_8_2) == 'one' # with a non-identical
descr
+ #
+ buf.write_value(0, 4, ArrayS_8_2, 'two') # with a non-identical descr
+ assert buf.read_value(0, 4, ArrayS_8_1) == 'two'
+ #
+ with py.test.raises(InvalidRawRead):
+ buf.read_value(0, 4, ArrayU_8)
+ with py.test.raises(InvalidRawWrite):
+ buf.write_value(0, 4, ArrayU_8, 'three')
diff --git a/pypy/jit/metainterp/optimizeopt/virtualize.py
b/pypy/jit/metainterp/optimizeopt/virtualize.py
--- a/pypy/jit/metainterp/optimizeopt/virtualize.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualize.py
@@ -388,14 +388,14 @@
class VRawBufferValue(AbstractVArrayValue):
- def __init__(self, size, keybox, source_op):
+ def __init__(self, cpu, size, keybox, source_op):
AbstractVirtualValue.__init__(self, keybox, source_op)
# note that size is unused, because we assume that the buffer is big
# enough to write/read everything we need. If it's not, it's undefined
# behavior anyway, although in theory we could probably detect such
# cases here
self.size = size
- self.buffer = RawBuffer()
+ self.buffer = RawBuffer(cpu)
def getlength(self):
return len(self.buffer.values)
@@ -491,7 +491,7 @@
return vvalue
def make_virtual_raw_memory(self, size, box, source_op):
- vvalue = VRawBufferValue(size, box, source_op)
+ vvalue = VRawBufferValue(self.optimizer.cpu, size, box, source_op)
self.make_equal_to(box, vvalue)
return vvalue
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -2561,6 +2561,7 @@
box_exchange_buffer = op.getarg(3)
self.history.operations.pop()
arg_boxes = []
+
for i in range(cif_description.nargs):
kind, descr = get_arg_descr(self.cpu, cif_description.atypes[i])
if kind == 'i':
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit