[pypy-svn] r47293 - in pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem: . test
arigo at codespeak.net
arigo at codespeak.net
Mon Oct 8 17:31:45 CEST 2007
Author: arigo
Date: Mon Oct 8 17:31:44 2007
New Revision: 47293
Modified:
pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/llarena.py
pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lltype.py
pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/test/test_llarena.py
Log:
A cleaner approach: requiring an explicit declaration of the object
we expect to find. This is also where the fakearenaaddress -> fakeaddress
conversion takes place.
Modified: pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/llarena.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/llarena.py (original)
+++ pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/llarena.py Mon Oct 8 17:31:44 2007
@@ -14,20 +14,22 @@
pass
class Arena(object):
+ object_arena_location = {} # {container: (arena, offset)}
def __init__(self, nbytes, zero):
self.nbytes = nbytes
self.usagemap = array.array('c')
- self.objects = {}
+ self.objectptrs = {} # {offset: ptr-to-container}
self.freed = False
self.reset(zero)
def reset(self, zero):
self.check()
- for obj in self.objects.itervalues():
+ for ptr in self.objectptrs.itervalues():
+ obj = ptr._obj
obj._free()
- self.objects.clear()
- self.pendinggcheaders = {}
+ del Arena.object_arena_location[obj]
+ self.objectptrs.clear()
if zero:
initialbyte = "0"
else:
@@ -47,29 +49,34 @@
raise ArenaError("Address offset is outside the arena")
return fakearenaaddress(self, offset)
- def allocate_object(self, offset, TYPE):
+ def allocate_object(self, offset, size):
self.check()
- size = llmemory.raw_malloc_usage(llmemory.sizeof(TYPE))
- if offset + size > self.nbytes:
+ bytes = llmemory.raw_malloc_usage(size)
+ if offset + bytes > self.nbytes:
raise ArenaError("object overflows beyond the end of the arena")
zero = True
- for c in self.usagemap[offset:offset+size]:
+ for c in self.usagemap[offset:offset+bytes]:
if c == '0':
pass
elif c == '#':
zero = False
else:
raise ArenaError("new object overlaps a previous object")
- p = lltype.malloc(TYPE, flavor='raw', zero=zero)
- self.usagemap[offset:offset+size] = array.array('c', 'X' * size)
- self.objects[offset] = p._obj
- if offset in self.pendinggcheaders:
- size_gc_header = self.pendinggcheaders.pop(offset)
- gcheaderbuilder = size_gc_header.gcheaderbuilder
- HDR = gcheaderbuilder.HDR
- headeraddr = self.getaddr(offset) - size_gc_header
- headerptr = llmemory.cast_adr_to_ptr(headeraddr, lltype.Ptr(HDR))
- gcheaderbuilder.attach_header(p, headerptr)
+ assert offset not in self.objectptrs
+ addr2 = size._raw_malloc([], zero=zero)
+ self.usagemap[offset:offset+bytes] = array.array('c', 'X' * bytes)
+ self.objectptrs[offset] = addr2.ptr
+ Arena.object_arena_location[addr2.ptr._obj] = self, offset
+ # common case: 'size' starts with a GCHeaderOffset. In this case
+ # we can also remember that the real object starts after the header.
+ if (isinstance(size, llmemory.CompositeOffset) and
+ isinstance(size.offsets[0], llmemory.GCHeaderOffset)):
+ objaddr = addr2 + size.offsets[0]
+ objoffset = offset + llmemory.raw_malloc_usage(size.offsets[0])
+ assert objoffset not in self.objectptrs
+ self.objectptrs[objoffset] = objaddr.ptr
+ Arena.object_arena_location[objaddr.ptr._obj] = self, objoffset
+ return addr2
class fakearenaaddress(llmemory.fakeaddress):
@@ -79,12 +86,11 @@
def _getptr(self):
try:
- obj = self.arena.objects[self.offset]
+ return self.arena.objectptrs[self.offset]
except KeyError:
self.arena.check()
raise ArenaError("don't know yet what type of object "
"is at offset %d" % (self.offset,))
- return obj._as_ptr()
ptr = property(_getptr)
def __repr__(self):
@@ -95,11 +101,6 @@
position = self.offset + other
elif isinstance(other, llmemory.AddressOffset):
position = self.offset + llmemory.raw_malloc_usage(other)
- if isinstance(other, llmemory.GCHeaderOffset):
- # take the expression 'addr + size_gc_header' as a hint that
- # there is at 'addr' a GC header for the object
- if position not in self.arena.objects:
- self.arena.pendinggcheaders[position] = other
else:
return NotImplemented
return self.arena.getaddr(position)
@@ -110,9 +111,9 @@
if isinstance(other, (int, long)):
return self.arena.getaddr(self.offset - other)
if isinstance(other, fakearenaaddress):
- if self.other is not other.arena:
+ if self.arena is not other.arena:
raise ArenaError("The two addresses are from different arenas")
- return other.offset - self.offset
+ return self.offset - other.offset
return NotImplemented
def __nonzero__(self):
@@ -121,31 +122,31 @@
def __eq__(self, other):
if isinstance(other, fakearenaaddress):
return self.arena is other.arena and self.offset == other.offset
- elif isinstance(other, llmemory.fakeaddress) and not other:
- return False # 'self' can't be equal to NULL
+ elif isinstance(other, llmemory.fakeaddress):
+ if other.ptr and other.ptr._obj in Arena.object_arena_location:
+ arena, offset = Arena.object_arena_location[other.ptr._obj]
+ return self.arena is arena and self.offset == offset
+ else:
+ return False
else:
return llmemory.fakeaddress.__eq__(self, other)
def __lt__(self, other):
if isinstance(other, fakearenaaddress):
- if self.arena is not other.arena:
- return cmp(self.arena._getid(), other.arena._getid())
+ arena = other.arena
+ offset = other.offset
+ elif isinstance(other, llmemory.fakeaddress):
+ if other.ptr and other.ptr._obj in Arena.object_arena_location:
+ arena, offset = Arena.object_arena_location[other.ptr._obj]
else:
- return cmp(self.offset, other.offset)
- elif isinstance(other, llmemory.fakeaddress) and not other:
- return 1 # 'self' > NULL
+ return 1 # arbitrarily, 'self' > any address not in any arena
else:
raise TypeError("comparing a %s and a %s" % (
self.__class__.__name__, other.__class__.__name__))
-
- def _cast_to_ptr(self, EXPECTED_TYPE):
- if EXPECTED_TYPE == llmemory.GCREF:
- obj = lltype._opaque(EXPECTED_TYPE.TO, _original_address = self)
- return obj._as_ptr()
- # the first cast determines what object type is at this address
- if self.offset not in self.arena.objects:
- self.arena.allocate_object(self.offset, EXPECTED_TYPE.TO)
- return llmemory.fakeaddress._cast_to_ptr(self, EXPECTED_TYPE)
+ if self.arena is arena:
+ return cmp(self.offset, offset)
+ else:
+ return cmp(self.arena._getid(), arena._getid())
def _cast_to_int(self):
return self.arena._getid() + self.offset
@@ -176,3 +177,12 @@
assert arena_addr.offset == 0
assert myarenasize == arena_addr.arena.nbytes
arena_addr.arena.reset(zero)
+
+def arena_reserve(addr, size):
+ """Mark some bytes in an arena as reserved, and returns addr.
+ For debugging this can check that reserved ranges of bytes don't
+ overlap. The size must be symbolic; in non-translated version
+ the returned 'addr' is not a fakearenaaddress but a fakeaddress
+ inside a fresh lltype object."""
+ assert isinstance(addr, fakearenaaddress)
+ return addr.arena.allocate_object(addr.offset, size)
Modified: pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/lltype.py Mon Oct 8 17:31:44 2007
@@ -1194,9 +1194,6 @@
## addr = llmemory.fakeaddress(normalizeptr(_ptr(Ptr(T), parent)))
## addr += llmemory.itemoffsetof(T, parentindex)
## return addr
- elif (isinstance(self._obj, _opaque)
- and hasattr(self._obj, '_original_address')):
- return self._obj._original_address # for llarena.py
else:
# normal case
return llmemory.fakeaddress(normalizeptr(self))
Modified: pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/test/test_llarena.py
==============================================================================
--- pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/test/test_llarena.py (original)
+++ pypy/branch/kill-keepalives-again/pypy/rpython/lltypesystem/test/test_llarena.py Mon Oct 8 17:31:44 2007
@@ -2,6 +2,7 @@
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rpython.lltypesystem.llmemory import cast_adr_to_ptr
from pypy.rpython.lltypesystem.llarena import arena_malloc, arena_reset
+from pypy.rpython.lltypesystem.llarena import arena_reserve
from pypy.rpython.lltypesystem.llarena import ArenaError
def test_arena():
@@ -13,12 +14,14 @@
assert a != llmemory.NULL
assert a + 3 != llmemory.NULL
+ arena_reserve(a, llmemory.sizeof(S))
s1_ptr1 = cast_adr_to_ptr(a, SPTR)
s1_ptr1.x = 1
s1_ptr2 = cast_adr_to_ptr(a, SPTR)
assert s1_ptr2.x == 1
assert s1_ptr1 == s1_ptr2
+ arena_reserve(a + ssize + 1, llmemory.sizeof(S))
s2_ptr1 = cast_adr_to_ptr(a + ssize + 1, SPTR)
py.test.raises(lltype.UninitializedMemoryAccess, 's2_ptr1.x')
s2_ptr1.x = 2
@@ -31,20 +34,29 @@
S2 = lltype.Struct('S2', ('y',lltype.Char))
S2PTR = lltype.Ptr(S2)
- py.test.raises(TypeError, cast_adr_to_ptr, a, S2PTR)
+ py.test.raises(lltype.InvalidCast, cast_adr_to_ptr, a, S2PTR)
py.test.raises(ArenaError, cast_adr_to_ptr, a+1, SPTR)
py.test.raises(ArenaError, cast_adr_to_ptr, a+ssize, SPTR)
py.test.raises(ArenaError, cast_adr_to_ptr, a+2*ssize, SPTR)
py.test.raises(ArenaError, cast_adr_to_ptr, a+2*ssize+1, SPTR)
+ py.test.raises(ArenaError, arena_reserve, a+1, llmemory.sizeof(S))
+ py.test.raises(ArenaError, arena_reserve, a+ssize, llmemory.sizeof(S))
+ py.test.raises(ArenaError, arena_reserve, a+2*ssize, llmemory.sizeof(S))
+ py.test.raises(ArenaError, arena_reserve, a+2*ssize+1, llmemory.sizeof(S))
arena_reset(a, myarenasize, True)
+ py.test.raises(ArenaError, cast_adr_to_ptr, a, SPTR)
+ arena_reserve(a, llmemory.sizeof(S))
s1_ptr1 = cast_adr_to_ptr(a, SPTR)
assert s1_ptr1.x == 0
s1_ptr1.x = 5
+ arena_reserve(a + ssize, llmemory.sizeof(S2))
s2_ptr1 = cast_adr_to_ptr(a + ssize, S2PTR)
assert s2_ptr1.y == '\x00'
s2_ptr1.y = 'X'
assert cast_adr_to_ptr(a + 0, SPTR).x == 5
assert cast_adr_to_ptr((a + ssize + 1) - 1, S2PTR).y == 'X'
+
+ assert (a + 4) - (a + 1) == 3
More information about the pypy-svn
mailing list