[pypy-svn] r58811 - in pypy/dist/pypy: config rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory/gc rpython/memory/gc/test rpython/memory/test translator/c/src translator/c/test
arigo at codespeak.net
arigo at codespeak.net
Wed Oct 8 14:10:37 CEST 2008
Author: arigo
Date: Wed Oct 8 14:10:36 2008
New Revision: 58811
Added:
pypy/dist/pypy/rpython/memory/gc/markcompact.py
- copied unchanged from r58809, pypy/branch/gc-experiments/pypy/rpython/memory/gc/markcompact.py
Modified:
pypy/dist/pypy/config/translationoption.py
pypy/dist/pypy/rpython/llinterp.py
pypy/dist/pypy/rpython/lltypesystem/llarena.py
pypy/dist/pypy/rpython/lltypesystem/llmemory.py
pypy/dist/pypy/rpython/lltypesystem/lloperation.py
pypy/dist/pypy/rpython/lltypesystem/test/test_llarena.py
pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
pypy/dist/pypy/rpython/memory/gc/base.py
pypy/dist/pypy/rpython/memory/gc/hybrid.py
pypy/dist/pypy/rpython/memory/gc/marksweep.py
pypy/dist/pypy/rpython/memory/gc/semispace.py
pypy/dist/pypy/rpython/memory/gc/test/test_direct.py
pypy/dist/pypy/rpython/memory/test/test_gc.py
pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
pypy/dist/pypy/translator/c/src/mem.h
pypy/dist/pypy/translator/c/test/test_lladdresses.py
pypy/dist/pypy/translator/c/test/test_newgc.py
Log:
(fijal, arigo)
Merge the gc-experiments branch, adding the markcompact gc.
svn merge svn+ssh://codespeak.net/svn/pypy/dist@58225 \
svn+ssh://codespeak.net/svn/pypy/branch/gc-experiments
Modified: pypy/dist/pypy/config/translationoption.py
==============================================================================
--- pypy/dist/pypy/config/translationoption.py (original)
+++ pypy/dist/pypy/config/translationoption.py Wed Oct 8 14:10:36 2008
@@ -45,7 +45,7 @@
# gc
ChoiceOption("gc", "Garbage Collection Strategy",
["boehm", "ref", "marksweep", "semispace", "statistics",
- "generation", "hybrid", "none"],
+ "generation", "hybrid", "markcompact", "none"],
"ref", requires={
"ref": [("translation.rweakref", False), # XXX
("translation.gctransformer", "ref")],
@@ -57,6 +57,7 @@
"generation": [("translation.gctransformer", "framework")],
"hybrid": [("translation.gctransformer", "framework")],
"boehm": [("translation.gctransformer", "boehm")],
+ "markcompact": [("translation.gctransformer", "framework")],
},
cmdline="--gc"),
ChoiceOption("gctransformer", "GC transformer that is used - internal",
@@ -299,7 +300,7 @@
'0': 'boehm nobackendopt',
'1': 'boehm lowinline',
'size': 'boehm lowinline remove_asserts',
- 'mem': 'generation lowinline remove_asserts',
+ 'mem': 'markcompact lowinline remove_asserts',
'2': 'hybrid extraopts',
'3': 'hybrid extraopts remove_asserts',
}
Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py (original)
+++ pypy/dist/pypy/rpython/llinterp.py Wed Oct 8 14:10:36 2008
@@ -895,6 +895,8 @@
checkadr(toaddr)
llmemory.raw_memcopy(fromaddr, toaddr, size)
+ op_raw_memmove = op_raw_memcopy # this is essentially the same here
+
def op_raw_load(self, addr, typ, offset):
checkadr(addr)
value = getattr(addr, str(typ).lower())[offset]
Modified: pypy/dist/pypy/rpython/lltypesystem/llarena.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llarena.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/llarena.py Wed Oct 8 14:10:36 2008
@@ -264,6 +264,9 @@
# work with fakearenaaddresses on which arbitrary arithmetic is
# possible even on top of the llinterpreter.
+# arena_new_view(ptr) is a no-op when translated, returns fresh view
+# on previous arena when run on top of llinterp
+
def arena_malloc(nbytes, zero):
"""Allocate and return a new arena, optionally zero-initialized."""
return Arena(nbytes, zero).getaddr(0)
@@ -299,6 +302,11 @@
following an object. For arenas containing heterogenous objects."""
return RoundedUpForAllocation(size)
+def arena_new_view(ptr):
+ """Return a fresh memory view on an arena
+ """
+ return Arena(ptr.arena.nbytes, False).getaddr(0)
+
# ____________________________________________________________
#
# Translation support: the functions above turn into the code below.
@@ -399,3 +407,9 @@
llimpl=llimpl_round_up_for_allocation,
llfakeimpl=round_up_for_allocation,
sandboxsafe=True)
+
+def llimpl_arena_new_view(addr):
+ return addr
+register_external(arena_new_view, [llmemory.Address], llmemory.Address,
+ 'll_arena.arena_new_view', llimpl=llimpl_arena_new_view,
+ llfakeimpl=arena_new_view, sandboxsafe=True)
Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Wed Oct 8 14:10:36 2008
@@ -736,6 +736,12 @@
assert lltype.typeOf(dest) == Address
size.raw_memcopy(source, dest)
+def raw_memmove(source, dest, size):
+ # for now let's assume that raw_memmove is the same as raw_memcopy,
+ # when run on top of fake addresses, but we _free the source object
+ raw_memcopy(source, dest, size)
+ source.ptr._as_obj()._free()
+
def cast_any_ptr(EXPECTED_TYPE, ptr):
# this is a generalization of the various cast_xxx_ptr() functions.
PTRTYPE = lltype.typeOf(ptr)
@@ -785,3 +791,19 @@
setattr(dest._obj, name, llvalue)
else:
raise TypeError(T)
+
+from pypy.rpython.extregistry import ExtRegistryEntry
+
+class RawMemmoveEntry(ExtRegistryEntry):
+ _about_ = raw_memmove
+
+ def compute_result_annotation(self, s_from, s_to, s_size):
+ from pypy.annotation.model import SomeAddress, SomeInteger
+ assert isinstance(s_from, SomeAddress)
+ assert isinstance(s_to, SomeAddress)
+ assert isinstance(s_size, SomeInteger)
+
+ def specialize_call(self, hop):
+ hop.exception_cannot_occur()
+ v_list = hop.inputargs(Address, Address, lltype.Signed)
+ return hop.genop('raw_memmove', v_list)
Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Wed Oct 8 14:10:36 2008
@@ -368,6 +368,7 @@
'raw_free': LLOp(),
'raw_memclear': LLOp(),
'raw_memcopy': LLOp(),
+ 'raw_memmove': LLOp(),
'raw_load': LLOp(sideeffects=False),
'raw_store': LLOp(),
'stack_malloc': LLOp(), # mmh
Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llarena.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llarena.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llarena.py Wed Oct 8 14:10:36 2008
@@ -4,7 +4,7 @@
from pypy.rpython.lltypesystem.llarena import arena_malloc, arena_reset
from pypy.rpython.lltypesystem.llarena import arena_reserve, arena_free
from pypy.rpython.lltypesystem.llarena import round_up_for_allocation
-from pypy.rpython.lltypesystem.llarena import ArenaError
+from pypy.rpython.lltypesystem.llarena import ArenaError, arena_new_view
def test_arena():
S = lltype.Struct('S', ('x',lltype.Signed))
@@ -150,6 +150,13 @@
arena_free(a)
return 42
+def test_arena_new_view():
+ a = arena_malloc(50, False)
+ arena_reserve(a, precomputed_size)
+ # we can now allocate the same space in new view
+ b = arena_new_view(a)
+ arena_reserve(b, precomputed_size)
+
def test_partial_arena_reset():
a = arena_malloc(50, False)
def reserve(i):
Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py Wed Oct 8 14:10:36 2008
@@ -504,6 +504,18 @@
raw_memcopy(at1, at2, sizeof(T))
assert t2.x == 1
+def test_raw_memmove():
+ T = lltype.GcStruct('T', ('x', lltype.Signed))
+ t1 = lltype.malloc(T)
+ t2 = lltype.malloc(T)
+ t1.x = 1
+ t2.x = 2
+ at1 = cast_ptr_to_adr(t1)
+ at2 = cast_ptr_to_adr(t2)
+ raw_memmove(at1, at2, sizeof(T))
+ assert t2.x == 1
+ py.test.raises(RuntimeError, "t1.x")
+
def test_raw_memcopy_nonrec():
T = lltype.GcStruct('T', ('x', lltype.Signed))
A = lltype.FixedSizeArray(lltype.Ptr(T), 1)
Modified: pypy/dist/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/base.py (original)
+++ pypy/dist/pypy/rpython/memory/gc/base.py Wed Oct 8 14:10:36 2008
@@ -1,5 +1,10 @@
-from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.lltypesystem import lltype, llmemory, llarena
from pypy.rlib.debug import ll_assert
+from pypy.rpython.memory.gcheader import GCHeaderBuilder
+from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE
+from pypy.rpython.memory.support import get_address_stack, get_address_deque
+from pypy.rpython.memory.support import AddressDict
+from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
class GCBase(object):
_alloc_flavor_ = "raw"
@@ -9,6 +14,13 @@
prebuilt_gc_objects_are_static_roots = True
can_realloc = False
+ def __init__(self, chunk_size=DEFAULT_CHUNK_SIZE):
+ self.gcheaderbuilder = GCHeaderBuilder(self.HDR)
+ self.AddressStack = get_address_stack(chunk_size)
+ self.AddressDeque = get_address_deque(chunk_size)
+ self.AddressDict = AddressDict
+ self.finalizer_lock_count = 0
+
def can_malloc_nonmovable(self):
return not self.moving_gc
@@ -46,7 +58,7 @@
pass
def setup(self):
- pass
+ self.run_finalizers = self.AddressDeque()
def statistics(self, index):
return -1
@@ -54,6 +66,23 @@
def size_gc_header(self, typeid=0):
return self.gcheaderbuilder.size_gc_header
+ def header(self, addr):
+ addr -= self.gcheaderbuilder.size_gc_header
+ return llmemory.cast_adr_to_ptr(addr, lltype.Ptr(self.HDR))
+
+ def get_size(self, obj):
+ typeid = self.get_type_id(obj)
+ size = self.fixed_size(typeid)
+ if self.is_varsize(typeid):
+ lenaddr = obj + self.varsize_offset_to_length(typeid)
+ length = lenaddr.signed[0]
+ size += length * self.varsize_item_sizes(typeid)
+ size = llarena.round_up_for_allocation(size)
+ # XXX maybe we should parametrize round_up_for_allocation()
+ # per GC; if we do, we also need to fix the call in
+ # gctypelayout.encode_type_shape()
+ return size
+
def malloc(self, typeid, length=0, zero=False):
"""For testing. The interface used by the gctransformer is
the four malloc_[fixed,var]size[_clear]() functions.
@@ -181,13 +210,86 @@
def debug_check_object(self, obj):
pass
+ def execute_finalizers(self):
+ self.finalizer_lock_count += 1
+ try:
+ while self.run_finalizers.non_empty():
+ if self.finalizer_lock_count > 1:
+ # the outer invocation of execute_finalizers() will do it
+ break
+ obj = self.run_finalizers.popleft()
+ finalizer = self.getfinalizer(self.get_type_id(obj))
+ finalizer(obj)
+ finally:
+ self.finalizer_lock_count -= 1
+
class MovingGCBase(GCBase):
moving_gc = True
+ def setup(self):
+ GCBase.setup(self)
+ self.objects_with_id = self.AddressDict()
+ self.id_free_list = self.AddressStack()
+ self.next_free_id = 1
+
def can_move(self, addr):
return True
+ def id(self, ptr):
+ # Default implementation for id(), assuming that "external" objects
+ # never move. Overriden in the HybridGC.
+ obj = llmemory.cast_ptr_to_adr(ptr)
+ if self._is_external(obj):
+ result = obj
+ else:
+ result = self._compute_id(obj)
+ return llmemory.cast_adr_to_int(result)
+
+ def _next_id(self):
+ # return an id not currently in use (as an address instead of an int)
+ if self.id_free_list.non_empty():
+ result = self.id_free_list.pop() # reuse a dead id
+ else:
+ # make up a fresh id number
+ result = llmemory.cast_int_to_adr(self.next_free_id)
+ self.next_free_id += 2 # only odd numbers, to make lltype
+ # and llmemory happy and to avoid
+ # clashes with real addresses
+ return result
+
+ def _compute_id(self, obj):
+ # look if the object is listed in objects_with_id
+ result = self.objects_with_id.get(obj)
+ if not result:
+ result = self._next_id()
+ self.objects_with_id.setitem(obj, result)
+ return result
+
+ def update_objects_with_id(self):
+ old = self.objects_with_id
+ new_objects_with_id = self.AddressDict(old.length())
+ old.foreach(self._update_object_id_FAST, new_objects_with_id)
+ old.delete()
+ self.objects_with_id = new_objects_with_id
+
+ def _update_object_id(self, obj, id, new_objects_with_id):
+ # safe version (used by subclasses)
+ if self.surviving(obj):
+ newobj = self.get_forwarding_address(obj)
+ new_objects_with_id.setitem(newobj, id)
+ else:
+ self.id_free_list.append(id)
+
+ def _update_object_id_FAST(self, obj, id, new_objects_with_id):
+ # unsafe version, assumes that the new_objects_with_id is large enough
+ if self.surviving(obj):
+ newobj = self.get_forwarding_address(obj)
+ new_objects_with_id.insertclean(newobj, id)
+ else:
+ self.id_free_list.append(id)
+
+
def choose_gc_from_config(config):
"""Return a (GCClass, GC_PARAMS) from the given config object.
"""
@@ -199,6 +301,7 @@
"semispace": "semispace.SemiSpaceGC",
"generation": "generation.GenerationGC",
"hybrid": "hybrid.HybridGC",
+ "markcompact" : "markcompact.MarkCompactGC",
}
try:
modulename, classname = classes[config.translation.gc].split('.')
Modified: pypy/dist/pypy/rpython/memory/gc/hybrid.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/hybrid.py (original)
+++ pypy/dist/pypy/rpython/memory/gc/hybrid.py Wed Oct 8 14:10:36 2008
@@ -1,8 +1,8 @@
import sys
from pypy.rpython.memory.gc.semispace import SemiSpaceGC
from pypy.rpython.memory.gc.semispace import DEBUG_PRINT
-from pypy.rpython.memory.gc.generation import GenerationGC, GCFLAG_FORWARDED
-from pypy.rpython.memory.gc.semispace import GCFLAG_EXTERNAL
+from pypy.rpython.memory.gc.generation import GenerationGC
+from pypy.rpython.memory.gc.semispace import GCFLAG_EXTERNAL, GCFLAG_FORWARDED
from pypy.rpython.memory.gc.generation import GCFLAG_NO_YOUNG_PTRS
from pypy.rpython.memory.gc.generation import GCFLAG_NO_HEAP_PTRS
from pypy.rpython.lltypesystem import lltype, llmemory, llarena
@@ -550,19 +550,23 @@
dead_size, "bytes in",
dead_count, "objs")
- def _compute_id_for_external(self, obj):
- # the base classes make the assumption that all external objects
- # have an id equal to their address. This is wrong if the object
- # is a generation 3 rawmalloced object that initially lived in
- # the semispaces.
- if self.is_last_generation(obj):
- # in this case, we still need to check if the object had its
- # id taken before. If not, we can use its address as its id.
- return self.objects_with_id.get(obj, obj)
- else:
- # a generation 2 external object was never non-external in
- # the past, so it cannot be listed in self.objects_with_id.
- return obj
+ def id(self, ptr):
+ obj = llmemory.cast_ptr_to_adr(ptr)
+ if self._is_external(obj):
+ # a prebuilt or rawmalloced object
+ if self.is_last_generation(obj):
+ # a generation 3 object may be one that used to live in
+ # the semispace. So we still need to check if the object had
+ # its id taken before. If not, we can use its address as its
+ # id as it is not going to move any more.
+ result = self.objects_with_id.get(obj, obj)
+ else:
+ # a generation 2 external object was never non-external in
+ # the past, so it cannot be listed in self.objects_with_id.
+ result = obj
+ else:
+ result = self._compute_id(obj) # common case
+ return llmemory.cast_adr_to_int(result)
# XXX a possible optimization would be to use three dicts, one
# for each generation, instead of mixing gen2 and gen3 objects.
Modified: pypy/dist/pypy/rpython/memory/gc/marksweep.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/marksweep.py (original)
+++ pypy/dist/pypy/rpython/memory/gc/marksweep.py Wed Oct 8 14:10:36 2008
@@ -22,8 +22,6 @@
DEBUG_PRINT = False
memoryError = MemoryError()
class MarkSweepGC(GCBase):
- _alloc_flavor_ = "raw"
-
HDR = lltype.ForwardReference()
HDRPTR = lltype.Ptr(HDR)
# need to maintain a linked list of malloced objects, since we used the
@@ -44,17 +42,16 @@
TRANSLATION_PARAMS = {'start_heap_size': 8*1024*1024} # XXX adjust
def __init__(self, chunk_size=DEFAULT_CHUNK_SIZE, start_heap_size=4096):
+ GCBase.__init__(self, chunk_size)
self.heap_usage = 0 # at the end of the latest collection
self.bytes_malloced = 0 # since the latest collection
self.bytes_malloced_threshold = start_heap_size
self.total_collection_time = 0.0
- self.AddressStack = get_address_stack(chunk_size)
self.malloced_objects = lltype.nullptr(self.HDR)
self.malloced_objects_with_finalizer = lltype.nullptr(self.HDR)
# these are usually only the small bits of memory that make a
# weakref object
self.objects_with_weak_pointers = lltype.nullptr(self.HDR)
- self.gcheaderbuilder = GCHeaderBuilder(self.HDR)
# pools, for x_swap_pool():
# 'curpool' is the current pool, lazily allocated (i.e. NULL means
# the current POOL object is not yet malloc'ed). POOL objects are
Modified: pypy/dist/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/semispace.py (original)
+++ pypy/dist/pypy/rpython/memory/gc/semispace.py Wed Oct 8 14:10:36 2008
@@ -4,7 +4,6 @@
from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE
from pypy.rpython.memory.support import get_address_stack, get_address_deque
from pypy.rpython.memory.support import AddressDict
-from pypy.rpython.memory.gcheader import GCHeaderBuilder
from pypy.rpython.lltypesystem import lltype, llmemory, llarena
from pypy.rlib.objectmodel import free_non_gc_object
from pypy.rlib.debug import ll_assert
@@ -45,17 +44,10 @@
def __init__(self, chunk_size=DEFAULT_CHUNK_SIZE, space_size=4096,
max_space_size=sys.maxint//2+1):
- MovingGCBase.__init__(self)
+ MovingGCBase.__init__(self, chunk_size)
self.space_size = space_size
self.max_space_size = max_space_size
- self.gcheaderbuilder = GCHeaderBuilder(self.HDR)
- self.AddressStack = get_address_stack(chunk_size)
- self.AddressDeque = get_address_deque(chunk_size)
- self.AddressDict = AddressDict
- self.finalizer_lock_count = 0
self.red_zone = 0
- self.id_free_list = self.AddressStack()
- self.next_free_id = 1
def setup(self):
if DEBUG_PRINT:
@@ -67,10 +59,9 @@
self.fromspace = llarena.arena_malloc(self.space_size, True)
ll_assert(bool(self.fromspace), "couldn't allocate fromspace")
self.free = self.tospace
+ MovingGCBase.setup(self)
self.objects_with_finalizers = self.AddressDeque()
- self.run_finalizers = self.AddressDeque()
self.objects_with_weakrefs = self.AddressStack()
- self.objects_with_id = self.AddressDict()
# This class only defines the malloc_{fixed,var}size_clear() methods
# because the spaces are filled with zeroes in advance.
@@ -388,20 +379,6 @@
stub = llmemory.cast_adr_to_ptr(obj, self.FORWARDSTUBPTR)
stub.forw = newobj
- def get_size(self, obj):
- typeid = self.get_type_id(obj)
- size = self.fixed_size(typeid)
- if self.is_varsize(typeid):
- lenaddr = obj + self.varsize_offset_to_length(typeid)
- length = lenaddr.signed[0]
- size += length * self.varsize_item_sizes(typeid)
- size = llarena.round_up_for_allocation(size)
- return size
-
- def header(self, addr):
- addr -= self.gcheaderbuilder.size_gc_header
- return llmemory.cast_adr_to_ptr(addr, lltype.Ptr(self.HDR))
-
def get_type_id(self, addr):
tid = self.header(addr).tid
ll_assert(tid & (GCFLAG_FORWARDED|GCFLAG_EXTERNAL) != GCFLAG_FORWARDED,
@@ -556,75 +533,8 @@
self.run_finalizers.delete()
self.run_finalizers = new_run_finalizer
- def execute_finalizers(self):
- self.finalizer_lock_count += 1
- try:
- while self.run_finalizers.non_empty():
- #print "finalizer"
- if self.finalizer_lock_count > 1:
- # the outer invocation of execute_finalizers() will do it
- break
- obj = self.run_finalizers.popleft()
- finalizer = self.getfinalizer(self.get_type_id(obj))
- finalizer(obj)
- finally:
- self.finalizer_lock_count -= 1
-
- def id(self, ptr):
- obj = llmemory.cast_ptr_to_adr(ptr)
- if self.header(obj).tid & GCFLAG_EXTERNAL:
- result = self._compute_id_for_external(obj)
- else:
- result = self._compute_id(obj)
- return llmemory.cast_adr_to_int(result)
-
- def _next_id(self):
- # return an id not currently in use (as an address instead of an int)
- if self.id_free_list.non_empty():
- result = self.id_free_list.pop() # reuse a dead id
- else:
- # make up a fresh id number
- result = llmemory.cast_int_to_adr(self.next_free_id)
- self.next_free_id += 2 # only odd numbers, to make lltype
- # and llmemory happy and to avoid
- # clashes with real addresses
- return result
-
- def _compute_id(self, obj):
- # look if the object is listed in objects_with_id
- result = self.objects_with_id.get(obj)
- if not result:
- result = self._next_id()
- self.objects_with_id.setitem(obj, result)
- return result
-
- def _compute_id_for_external(self, obj):
- # For prebuilt objects, we can simply return their address.
- # This method is overriden by the HybridGC.
- return obj
-
- def update_objects_with_id(self):
- old = self.objects_with_id
- new_objects_with_id = self.AddressDict(old.length())
- old.foreach(self._update_object_id_FAST, new_objects_with_id)
- old.delete()
- self.objects_with_id = new_objects_with_id
-
- def _update_object_id(self, obj, id, new_objects_with_id):
- # safe version (used by subclasses)
- if self.surviving(obj):
- newobj = self.get_forwarding_address(obj)
- new_objects_with_id.setitem(newobj, id)
- else:
- self.id_free_list.append(id)
-
- def _update_object_id_FAST(self, obj, id, new_objects_with_id):
- # unsafe version, assumes that the new_objects_with_id is large enough
- if self.surviving(obj):
- newobj = self.get_forwarding_address(obj)
- new_objects_with_id.insertclean(newobj, id)
- else:
- self.id_free_list.append(id)
+ def _is_external(self, obj):
+ return (self.header(obj).tid & GCFLAG_EXTERNAL) != 0
def debug_check_object(self, obj):
"""Check the invariants about 'obj' that should be true
Modified: pypy/dist/pypy/rpython/memory/gc/test/test_direct.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/test/test_direct.py (original)
+++ pypy/dist/pypy/rpython/memory/gc/test/test_direct.py Wed Oct 8 14:10:36 2008
@@ -279,3 +279,7 @@
'large_object_gcptrs': 12,
'generation3_collect_threshold': 5,
}
+
+class TestMarkCompactGC(DirectGCTest):
+ from pypy.rpython.memory.gc.markcompact import MarkCompactGC as GCClass
+
Modified: pypy/dist/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_gc.py (original)
+++ pypy/dist/pypy/rpython/memory/test/test_gc.py Wed Oct 8 14:10:36 2008
@@ -9,7 +9,7 @@
from pypy.rpython.lltypesystem.rstr import STR
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rlib.objectmodel import we_are_translated
-from pypy.rlib.objectmodel import compute_unique_id
+from pypy.rlib.objectmodel import compute_unique_id, keepalive_until_here
def stdout_ignore_ll_functions(msg):
@@ -263,10 +263,6 @@
assert res
def test_id(self):
- py.test.skip("the MovingGCBase.id() logic can't be directly run")
- # XXX ^^^ the problem is that the MovingGCBase instance holds
- # references to GC objects - a list of weakrefs and a dict - and
- # there is no way we can return these from get_roots_from_llinterp().
class A(object):
pass
a1 = A()
@@ -318,6 +314,44 @@
res = self.interpret(f, [500])
assert res == 1 + 500
+
+ def test_collect_during_collect(self):
+ class B(object):
+ pass
+ b = B()
+ b.nextid = 1
+ b.num_deleted = 0
+ b.num_deleted_c = 0
+ class A(object):
+ def __init__(self):
+ self.id = b.nextid
+ b.nextid += 1
+ def __del__(self):
+ llop.gc__collect(lltype.Void)
+ b.num_deleted += 1
+ C()
+ C()
+ class C(A):
+ def __del__(self):
+ b.num_deleted += 1
+ b.num_deleted_c += 1
+ def f(x, y):
+ persistent_a1 = A()
+ persistent_a2 = A()
+ i = 0
+ while i < x:
+ i += 1
+ a = A()
+ persistent_a3 = A()
+ persistent_a4 = A()
+ llop.gc__collect(lltype.Void)
+ llop.gc__collect(lltype.Void)
+ b.bla = persistent_a1.id + persistent_a2.id + persistent_a3.id + persistent_a4.id
+ print b.num_deleted_c
+ return b.num_deleted
+ res = self.interpret(f, [4, 42])
+ assert res == 12
+
def test_weakref_across_minor_collection(self):
import weakref
class A:
@@ -455,6 +489,15 @@
class TestGenerationalGC(TestSemiSpaceGC):
from pypy.rpython.memory.gc.generation import GenerationGC as GCClass
+class TestMarkCompactGC(TestSemiSpaceGC):
+ from pypy.rpython.memory.gc.markcompact import MarkCompactGC as GCClass
+
+ def test_finalizer_order(self):
+ py.test.skip("Not implemented yet")
+
+class TestMarkCompactGCGrowing(TestMarkCompactGC):
+ GC_PARAMS = {'space_size': 64}
+
class TestHybridGC(TestGenerationalGC):
from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass
GC_CANNOT_MALLOC_NONMOVABLE = False
Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original)
+++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Wed Oct 8 14:10:36 2008
@@ -341,6 +341,7 @@
b = B()
b.nextid = 1
b.num_deleted = 0
+ b.num_deleted_c = 0
class A(object):
def __init__(self):
self.id = b.nextid
@@ -353,6 +354,7 @@
class C(A):
def __del__(self):
b.num_deleted += 1
+ b.num_deleted_c += 1
def f(x, y):
persistent_a1 = A()
persistent_a2 = A()
@@ -365,6 +367,7 @@
llop.gc__collect(lltype.Void)
llop.gc__collect(lltype.Void)
b.bla = persistent_a1.id + persistent_a2.id + persistent_a3.id + persistent_a4.id
+ print b.num_deleted_c
return b.num_deleted
run = self.runner(f, nbargs=2)
# runs collect recursively 4 times
@@ -798,6 +801,15 @@
GC_PARAMS = {'space_size': 2048}
root_stack_depth = 200
+class TestMarkCompactGC(GenericMovingGCTests):
+ gcname = 'markcompact'
+
+ class gcpolicy(gc.FrameworkGcPolicy):
+ class transformerclass(framework.FrameworkGCTransformer):
+ from pypy.rpython.memory.gc.markcompact import MarkCompactGC as GCClass
+ GC_PARAMS = {'space_size': 2048}
+ root_stack_depth = 200
+
class TestGenerationGC(GenericMovingGCTests):
gcname = "generation"
Modified: pypy/dist/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/mem.h (original)
+++ pypy/dist/pypy/translator/c/src/mem.h Wed Oct 8 14:10:36 2008
@@ -90,6 +90,7 @@
if (r != NULL) memset((void*) r, 0, size);
#define OP_RAW_MEMCOPY(x,y,size,r) memcpy(y,x,size);
+#define OP_RAW_MEMMOVE(x,y,size,r) memmove(y,x,size);
/************************************************************/
Modified: pypy/dist/pypy/translator/c/test/test_lladdresses.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_lladdresses.py (original)
+++ pypy/dist/pypy/translator/c/test/test_lladdresses.py Wed Oct 8 14:10:36 2008
@@ -96,6 +96,19 @@
res = fc()
assert res
+def test_raw_memmove():
+ def f():
+ addr = raw_malloc(100)
+ addr.signed[0] = 12
+ (addr + 10).signed[0] = 42
+ raw_memmove(addr, addr + 4, 96)
+ result = (addr + 4).signed[0] + (addr + 14).signed[0]
+ raw_free(addr)
+ return result
+ fc = compile(f, [])
+ res = fc()
+ assert res
+
def test_pointer_comparison():
def f():
result = 0
Modified: pypy/dist/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_newgc.py (original)
+++ pypy/dist/pypy/translator/c/test/test_newgc.py Wed Oct 8 14:10:36 2008
@@ -1028,3 +1028,13 @@
def test_gc_set_max_heap_size(self):
py.test.skip("not implemented")
+
+class TestMarkCompactGC(TestSemiSpaceGC):
+ gcpolicy = "markcompact"
+ should_be_moving = True
+
+ def test_gc_set_max_heap_size(self):
+ py.test.skip("not implemented")
+
+ def test_finalizer_order(self):
+ py.test.skip("not implemented")
More information about the Pypy-commit
mailing list