Author: Armin Rigo <[email protected]>
Branch: stm-gc-2
Changeset: r63546:f48a4dfa5400
Date: 2013-04-21 17:33 +0200
http://bitbucket.org/pypy/pypy/changeset/f48a4dfa5400/
Log: Progress, but annoyed by the constant awkward interfacing between C
code and various pieces of RPython. :-/
diff --git a/rpython/memory/gc/stmgc.py b/rpython/memory/gc/stmgc.py
--- a/rpython/memory/gc/stmgc.py
+++ b/rpython/memory/gc/stmgc.py
@@ -238,8 +238,8 @@
stmtls = self.get_tls()
stmtls.stop_transaction()
self.stm_operations.commit_transaction()
+ self.stm_operations.begin_inevitable_transaction()
self.remove_from_linked_list(stmtls)
- self.stm_operations.begin_inevitable_transaction()
stmtls.delete()
teardown_thread._dont_inline_ = True
@@ -535,6 +535,7 @@
return mangle_hash(i)
def can_move(self, addr):
+ raise NotImplementedError("stmgc.can_move")
tls = self.get_tls()
if tls.is_in_nursery(addr):
return True
diff --git a/rpython/memory/gc/stmshared.py b/rpython/memory/gc/stmshared.py
--- a/rpython/memory/gc/stmshared.py
+++ b/rpython/memory/gc/stmshared.py
@@ -106,19 +106,36 @@
debug_start("gc-collect")
debug_print()
debug_print(".----------- Full collection ------------------")
- debug_print("| used before collection:",
+ debug_print("| used before collection: ",
self.fetch_count_total_bytes(), "bytes")
#
- fatalerror("do_major_collection: in-progress")
+ # Note that a major collection is non-moving. The goal is only to
+ # find and free some of the objects allocated by the ArenaCollection.
+ # We first visit all objects and set the flag GCFLAG_VISITED on them.
+ self.objects_to_trace = self.AddressStack()
+ #
+ # The stacks...
+ self.collect_stack_roots_from_every_thread()
#
self.num_major_collects += 1
- debug_print("| used after collection:",
+ debug_print("| used after collection: ",
self.fetch_count_total_bytes(), "bytes")
- debug_print("| number of major collects: ",
+ debug_print("| number of major collects: ",
self.num_major_collects)
debug_print("`----------------------------------------------")
debug_stop("gc-collect")
+ def collect_stack_roots_from_every_thread(self):
+ self.gc.root_walker.walk_all_stack_roots(self._collect_stack_root,
+ None)
+
+ def _collect_stack_root(self, ignored, root):
+ self.visit(root.address[0])
+
+ def visit(self, obj):
+ hdr = self.gc.header(obj)
+ XXX
+
# ------------------------------------------------------------
@@ -133,7 +150,6 @@
def __init__(self, sharedarea):
self.gc = sharedarea.gc
self.sharedarea = sharedarea
- self.chained_list = NULL
#
# The array 'pages_for_size' contains 'length' chained lists
# of pages currently managed by this thread.
@@ -242,12 +258,6 @@
llarena.arena_reserve(addr, _dummy_size(totalsize))
return addr + self.gc.gcheaderbuilder.size_gc_header
- def add_regular(self, obj):
- """After malloc_object(), register the object in the internal chained
- list. For objects whose 'revision' field is not otherwise needed."""
- self.gc.set_obj_revision(obj, self.chained_list)
- self.chained_list = obj
-
def free_object(self, obj):
adr1 = obj - self.gc.gcheaderbuilder.size_gc_header
totalsize = (self.gc.gcheaderbuilder.size_gc_header +
@@ -262,18 +272,6 @@
self.sharedarea.fetch_count_total_bytes_and_add(-totalsize)
llarena.arena_free(llarena.getfakearenaaddress(adr1))
- def free_and_clear(self):
- obj = self.chained_list
- self.chained_list = NULL
- while obj:
- next = self.gc.obj_revision(obj)
- self.free_object(obj)
- obj = next
-
- def free_and_clear_list(self, lst):
- while lst.non_empty():
- self.free_object(lst.pop())
-
def gift_all_pages_to_shared_area(self):
"""Send to the shared area all my pages. For now we don't extract
the information about which locations are free or not; we just stick
diff --git a/rpython/memory/gc/stmtls.py b/rpython/memory/gc/stmtls.py
--- a/rpython/memory/gc/stmtls.py
+++ b/rpython/memory/gc/stmtls.py
@@ -41,9 +41,6 @@
llmemory.Address)
self.adr_of_stack_top = llop.gc_adr_of_root_stack_top(
llmemory.Address)
- if StmGCThreadLocalAllocator is None:
- from rpython.memory.gc.stmshared import StmGCThreadLocalAllocator
- self.StmGCThreadLocalAllocator = StmGCThreadLocalAllocator
#
# --- current position, or NULL when mallocs are forbidden
self.nursery_free = NULL
@@ -62,8 +59,12 @@
self.nursery_top = self.nursery_stop
#
# --- a thread-local allocator for the shared area
- self.sharedarea_tls = self.StmGCThreadLocalAllocator(
+ if StmGCThreadLocalAllocator is None:
+ from rpython.memory.gc.stmshared import StmGCThreadLocalAllocator
+ self.sharedarea_tls = StmGCThreadLocalAllocator(
self.gc.sharedarea)
+ # --- a chained list of regular local objects, linked via 'revision'.
+ self.regular_chained_list = NULL
# --- the LOCAL objects which are weakrefs. They are also listed
# in the appropriate place, like sharedarea_tls, if needed.
self.local_weakrefs = self.AddressStack()
@@ -199,10 +200,9 @@
else:
self.detect_flag_combination = -1
#
- # Move away the previous sharedarea_tls and start a new one.
- previous_sharedarea_tls = self.sharedarea_tls
- self.sharedarea_tls = self.StmGCThreadLocalAllocator(
- self.gc.sharedarea)
+ # Move away the previous chained_list and start a new one.
+ previous_chained_list = self.regular_chained_list
+ self.regular_chained_list = NULL
#
# List of LOCAL objects pending a visit. Note that no GLOBAL
# object can at any point contain a reference to a LOCAL object.
@@ -238,7 +238,7 @@
#
# Visit all previous OLD objects. Free the ones that have not been
# visited above, and reset GCFLAG_VISITED on the others.
- self.mass_free_old_local(previous_sharedarea_tls)
+ self.mass_free_old_local(previous_chained_list)
#
# Note that the last step guarantees the invariant that between
# collections, all the objects linked within 'self.sharedarea_tls'
@@ -310,10 +310,10 @@
def _promote_locals_to_globals(self):
ll_assert(self.local_nursery_is_empty(), "nursery must be empty [1]")
#
- # Promote all objects in sharedarea_tls to global.
+ # Promote all objects in 'regular_chained_list' to global.
# This is the "real" equivalent of _FakeReach() in et.c.
- obj = self.sharedarea_tls.chained_list
- self.sharedarea_tls.chained_list = NULL
+ obj = self.regular_chained_list
+ self.regular_chained_list = NULL
#
while obj:
hdr = self.gc.header(obj)
@@ -338,9 +338,13 @@
#if self.rawmalloced_objects:
# xxx # free the rawmalloced_objects still around
- # free the old unused local objects still allocated in the
- # StmGCThreadLocalAllocator
- self.sharedarea_tls.free_and_clear()
+ # free the old unused local objects still in the chained list
+ obj = self.regular_chained_list
+ self.regular_chained_list = NULL
+ while obj:
+ next = self.gc.obj_revision(obj)
+ self.sharedarea_tls.free_object(obj)
+ obj = next
# forget the local weakrefs.
self.local_weakrefs.clear()
@@ -483,7 +487,7 @@
#
# Register the object here, not before the memcopy() that would
# overwrite its 'revision' field
- self._register_newly_malloced_obj(newobj)
+ self._register_regular_obj(newobj)
#
# Set the YOUNG copy's GCFLAG_VISITED and set its revision to
# point to the OLD copy.
@@ -579,8 +583,9 @@
#
return newobj
- def _register_newly_malloced_obj(self, obj):
- self.sharedarea_tls.add_regular(obj)
+ def _register_regular_obj(self, obj):
+ self.gc.set_obj_revision(obj, self.regular_chained_list)
+ self.regular_chained_list = obj
def collect_roots_from_tldict(self):
if not we_are_translated():
@@ -658,16 +663,14 @@
self.local_weakrefs = new
old.delete()
- def mass_free_old_local(self, previous_sharedarea_tls):
- obj = previous_sharedarea_tls.chained_list
- previous_sharedarea_tls.delete()
+ def mass_free_old_local(self, obj):
while obj != NULL:
hdr = self.gc.header(obj)
next = hdr_revision(hdr)
if hdr.tid & GCFLAG_VISITED:
- # survives: relink in the new sharedarea_tls
+ # survives: relink in the new chained list
hdr.tid -= GCFLAG_VISITED
- self.sharedarea_tls.add_regular(obj)
+ self._register_regular_obj(obj)
else:
# dies
self.sharedarea_tls.free_object(obj)
diff --git a/rpython/memory/gc/test/test_stmshared.py
b/rpython/memory/gc/test/test_stmshared.py
--- a/rpython/memory/gc/test/test_stmshared.py
+++ b/rpython/memory/gc/test/test_stmshared.py
@@ -1,6 +1,7 @@
from rpython.memory.gc.stmshared import WORD
from rpython.memory.gc.stmshared import StmGCSharedArea
from rpython.memory.gc.stmshared import StmGCThreadLocalAllocator
+from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
SGH = 3
@@ -20,6 +21,17 @@
def release_global_lock(self):
pass
+class FakeRootWalker:
+ def __init__(self, rootobjlist):
+ self._rootobjlist = rootobjlist
+ def walk_all_stack_roots(self, collect_stack_root, arg):
+ for obj in self._rootobjlist:
+ p = lltype.malloc(rffi.CArray(llmemory.Address), 1, flavor='raw')
+ p[0] = obj
+ collect_stack_root(arg, llmemory.cast_ptr_to_adr(p))
+ assert p[0] == obj # should not move
+ lltype.free(p)
+
def test_simple():
gc = FakeGC()
@@ -93,3 +105,16 @@
assert shared.count_global_pages == 0
thl1.delete()
assert shared.count_global_pages == 1
+
+def test_do_major_collection():
+ gc = FakeGC()
+ shared = StmGCSharedArea(gc, 9*WORD, 2*WORD)
+ shared.setup()
+ thl1 = StmGCThreadLocalAllocator(shared)
+ obj1 = thl1.malloc_object(2*WORD-SGH)
+ obj2 = thl1.malloc_object(2*WORD-SGH)
+ #
+ gc.root_walker = FakeRootWalker([obj2])
+ shared.do_major_collection()
+ #
+ xxx
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit