[pypy-svn] r17111 - in pypy/dist/pypy/rpython/memory: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Wed Aug 31 03:59:55 CEST 2005
Author: cfbolz
Date: Wed Aug 31 03:59:46 2005
New Revision: 17111
Modified:
pypy/dist/pypy/rpython/memory/convertlltype.py
pypy/dist/pypy/rpython/memory/gc.py
pypy/dist/pypy/rpython/memory/gcwrapper.py
pypy/dist/pypy/rpython/memory/test/test_gc.py
Log:
fix the deferred refcounting GC and make in running on the llinterpreter +
tests
Modified: pypy/dist/pypy/rpython/memory/convertlltype.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/convertlltype.py (original)
+++ pypy/dist/pypy/rpython/memory/convertlltype.py Wed Aug 31 03:59:46 2005
@@ -58,7 +58,7 @@
self.curraddress += size
if self.gc is not None:
typeid = self.query_types.get_typeid(TYPE)
- self.gc.init_gc_object(startaddr, typeid)
+ self.gc.init_gc_object_immortal(startaddr, typeid)
startaddr += self.gc.size_gc_header(typeid)
self.curraddress += self.gc.size_gc_header(typeid)
ptr = init_object_on_address(startaddr, TYPE, arraylength)
@@ -98,7 +98,7 @@
self.curraddress += size
if self.gc is not None:
typeid = self.query_types.get_typeid(TYPE)
- self.gc.init_gc_object(startaddr, typeid)
+ self.gc.init_gc_object_immortal(startaddr, typeid)
startaddr += self.gc.size_gc_header(typeid)
self.curraddress += self.gc.size_gc_header(typeid)
ptr = init_object_on_address(startaddr, TYPE, inlinedarraylength)
Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py (original)
+++ pypy/dist/pypy/rpython/memory/gc.py Wed Aug 31 03:59:46 2005
@@ -5,6 +5,8 @@
from pypy.rpython import lltype
from pypy.rpython.objectmodel import free_non_gc_object
+import sys
+
int_size = lltypesimulation.sizeof(lltype.Signed)
class GCError(Exception):
@@ -171,7 +173,7 @@
def init_gc_object(self, addr, typeid):
addr.signed[0] = 0
addr.signed[1] = typeid
-
+ init_gc_object_immortal = init_gc_object
class SemiSpaceGC(GCBase):
_alloc_flavor_ = "raw"
@@ -305,17 +307,18 @@
def init_gc_object(self, addr, typeid):
addr.signed[0] = 0
addr.signed[1] = typeid
-
+ init_gc_object_immortal = init_gc_object
class DeferredRefcountingGC(GCBase):
_alloc_flavor_ = "raw"
- def __init__(self, max_refcount_zero=10, get_roots=None):
+ def __init__(self, max_refcount_zero=50, get_roots=None):
self.zero_ref_counts = AddressLinkedList()
self.length_zero_ref_counts = 0
self.max_refcount_zero = max_refcount_zero
self.set_query_functions(None, None, None, None, None, None, None)
self.get_roots = get_roots
+ self.collecting = False
def malloc(self, typeid, length=0):
size = self.fixed_size(typeid)
@@ -323,53 +326,61 @@
size += length * self.varsize_item_sizes(typeid)
size_gc_header = self.size_gc_header()
result = raw_malloc(size + size_gc_header)
- print "mallocing %s, size %s at %s" % (typeid, size, result)
- self.init_gc_object(result, typeid)
+## print "mallocing %s, size %s at %s" % (typeid, size, result)
+ result.signed[0] = 0 # refcount
+ result.signed[1] = typeid
return result + size_gc_header
def collect(self):
+ if self.collecting:
+ return
+ else:
+ self.collecting = True
roots = self.get_roots()
curr = roots.first
while 1:
root = curr.address[1]
- print "root", root, root.address[0]
+## print "root", root, root.address[0]
+## assert self.refcount(root.address[0]) >= 0, "refcount negative"
self.incref(root.address[0])
if curr.address[0] == NULL:
break
curr = curr.address[0]
dealloc_list = AddressLinkedList()
+ self.length_zero_ref_counts = 0
while 1:
candidate = self.zero_ref_counts.pop()
- self.length_zero_ref_counts -= 1
if candidate == NULL:
break
refcount = self.refcount(candidate)
- if (refcount == 0 and
- (candidate - self.size_gc_header()).signed[1] != -1):
- (candidate - self.size_gc_header()).signed[1] = -1
+ typeid = (candidate - self.size_gc_header()).signed[1]
+ if (refcount == 0 and typeid >= 0):
+ (candidate - self.size_gc_header()).signed[1] = -typeid - 1
dealloc_list.append(candidate)
while 1:
deallocate = dealloc_list.pop()
if deallocate == NULL:
break
+ typeid = (deallocate - self.size_gc_header()).signed[1]
+ (deallocate - self.size_gc_header()).signed[1] = -typeid - 1
self.deallocate(deallocate)
free_non_gc_object(dealloc_list)
while 1:
root = roots.pop()
if root == NULL:
break
- print "root", root, root.address[0]
self.decref(root.address[0])
+ self.collecting = False
def write_barrier(self, addr, addr_to, addr_struct):
self.decref(addr_to.address[0])
addr_to.address[0] = addr
self.incref(addr)
- def deallocate(self, addr):
+ def deallocate(self, obj):
gc_info = obj - self.size_gc_header()
typeid = gc_info.signed[1]
- print "deallocating", obj, typeid
+## print "deallocating", obj, typeid
offsets = self.offsets_to_gc_pointers(typeid)
i = 0
while i < len(offsets):
@@ -391,7 +402,7 @@
self.decref(pointer.address[0])
j += 1
i += 1
- raw_free(addr)
+ raw_free(gc_info)
def incref(self, addr):
(addr - self.size_gc_header()).signed[0] += 1
@@ -400,21 +411,25 @@
if addr == NULL:
return
refcount = (addr - self.size_gc_header()).signed[0]
+## assert refcount > 0, "neg refcount"
if refcount == 1:
self.zero_ref_counts.append(addr)
self.length_zero_ref_counts += 1
if self.length_zero_ref_counts > self.max_refcount_zero:
self.collect()
(addr - self.size_gc_header()).signed[0] = refcount - 1
- assert refcount > 0
def refcount(self, addr):
- (addr - self.size_gc_header()).signed[0]
+ return (addr - self.size_gc_header()).signed[0]
def init_gc_object(self, addr, typeid):
addr.signed[0] = 0 # refcount
addr.signed[1] = typeid
+ def init_gc_object_immortal(self, addr, typeid):
+ addr.signed[0] = sys.maxint // 2 # refcount
+ addr.signed[1] = typeid
+
def size_gc_header(self, typeid=0):
return int_size * 2
Modified: pypy/dist/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gcwrapper.py (original)
+++ pypy/dist/pypy/rpython/memory/gcwrapper.py Wed Aug 31 03:59:46 2005
@@ -190,7 +190,7 @@
return self.llinterp.llt.functionptr(gc.gc_interface["write_barrier"],
"write_barrier",
_callable=self.gc.write_barrier)
-
+
def update_changed_addresses(self):
for i, root in enumerate(self.roots):
@@ -251,6 +251,8 @@
fgcc = FlowGraphConstantConverter(a.translator.flowgraphs)
fgcc.convert()
self.malloc_graph = a.translator.flowgraphs[self.gc.malloc.im_func]
+ self.write_barrier_graph = a.translator.flowgraphs[
+ self.gc.write_barrier.im_func]
# create a gc via invoking instantiate_gc
self.gcptr = self.llinterp.eval_function(
@@ -260,7 +262,6 @@
setattr(self.gcptr, "inst_get_roots",
lltypesimulation.functionptr(GETROOTS_FUNCTYPE, "get_roots",
_callable=self.get_roots))
-
#get funcptrs neccessary to build the result of get_roots
self.instantiate_linked_list = getfunctionptr(
a.translator, instantiate_linked_list)
@@ -270,7 +271,7 @@
a.translator, AddressLinkedList.pop.im_func)
self.gc.get_roots = None
self.translator = a.translator
-# a.translator.view()
+## a.translator.view()
def get_arg_malloc(self, TYPE, size=0):
typeid = self.query_types.get_typeid(TYPE)
@@ -286,6 +287,26 @@
self.update_changed_addresses()
return result
+ def get_arg_write_barrier(self, obj, index_or_field, item):
+ #XXX: quick hack to get the correct addresses, fix later
+ layout = lltypelayout.get_layout(lltype.typeOf(obj).TO)
+ if isinstance(lltype.typeOf(obj).TO, lltype.Array):
+ assert isinstance(index_or_field, int)
+ offset = layout[0] + layout[1] * index_or_field
+ addr_to = obj._address + layout[0] + index_or_field * layout[1]
+ return self.gcptr, item._address, addr_to, obj._address
+ else:
+ offset = layout[index_or_field]
+ addr_to = obj._address + offset
+ return self.gcptr, item._address, addr_to, obj._address
+
+ def get_funcptr_write_barrier(self):
+ return self.llinterp.llt.functionptr(gc.gc_interface["write_barrier"],
+ "write_barrier",
+ _callable=self.gc.write_barrier,
+ graph=self.write_barrier_graph)
+
+
def get_roots(self):
# call the llinterpreter to construct the result in a suitable way
self.get_roots_from_llinterp()
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 Aug 31 03:59:46 2005
@@ -30,6 +30,15 @@
gclltype.prepare_graphs_and_create_gc = gclltype.create_no_gc
class TestMarkSweepGC(object):
+ def setup_class(cls):
+ cls.prep_old = gclltype.prepare_graphs_and_create_gc
+ gclltype.use_gc = MarkSweepGC
+ cls.old = gclltype.use_gc
+
+ def teardown_class(cls):
+ gclltype.prepare_graphs_and_create_gc = cls.prep_old.im_func
+ gclltype.use_gc = cls.old
+
def test_llinterp_lists(self):
curr = simulator.current_size
def malloc_a_lot():
@@ -108,11 +117,21 @@
gclltype.prepare_graphs_and_create_gc = cls.prep_old.im_func
gclltype.use_gc = cls.old
-
-class DONOTTestDeferredRefcountingGC(TestMarkSweepGC):
+class TestDeferredRefcountingGC(TestMarkSweepGC):
def setup_class(cls):
gclltype.use_gc = DeferredRefcountingGC
cls.old = gclltype.use_gc
def teardown_class(cls):
gclltype.use_gc = cls.old
+
+class TestDeferredRefcountingGCRunningOnLLinterp(TestMarkSweepGC):
+ def setup_class(cls):
+ cls.prep_old = gclltype.prepare_graphs_and_create_gc
+ gclltype.prepare_graphs_and_create_gc = gclltype.create_gc_run_on_llinterp
+ gclltype.use_gc = DeferredRefcountingGC
+ cls.old = gclltype.use_gc
+
+ def teardown_class(cls):
+ gclltype.prepare_graphs_and_create_gc = cls.prep_old.im_func
+ gclltype.use_gc = cls.old
More information about the Pypy-commit
mailing list