Author: Devin Jeanpierre <[email protected]>
Branch: gc-forkfriendly
Changeset: r84849:11bee4605bdc
Date: 2016-05-31 13:58 -0700
http://bitbucket.org/pypy/pypy/changeset/11bee4605bdc/
Log: Fix type unification problem mentioned in last commit.
A remaining issue is a problem with test_newgc.py like so:
data_rpython_memory_test.c:17655:4: error:
‘pypy_g_header_1433’
undeclared here (not in a function) (&pypy_g_header_1433.h_tid), /*
gcheader.remote_flags */
Interesting! I'll try to fix separately (maybe hg bisect will help
here.)
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -1760,9 +1760,9 @@
# GcStruct is in the list self.old_objects_pointing_to_young.
debug_start("gc-minor-walkroots")
if self.gc_state == STATE_MARKING:
- callback = IncrementalMiniMarkGC._trace_drag_out1_marking_phase
+ callback = IncrementalMiniMarkGCBase._trace_drag_out1_marking_phase
else:
- callback = IncrementalMiniMarkGC._trace_drag_out1
+ callback = IncrementalMiniMarkGCBase._trace_drag_out1
#
# Note a subtlety: if the nursery contains pinned objects "from
# earlier", i.e. created earlier than the previous minor
@@ -2334,21 +2334,11 @@
if self.get_flags(obj) & GCFLAG_VISITED:
new_list.append(obj)
- def _free_if_unvisited(self, hdr):
- size_gc_header = self.gcheaderbuilder.size_gc_header
- obj = hdr + size_gc_header
- if self.get_flags(obj) & GCFLAG_VISITED:
- self.remove_flags(obj, GCFLAG_VISITED)
- return False # survives
- # dies
- self.finalize_header(hdr)
- return True
-
def _reset_gcflag_visited(self, obj, ignored):
self.remove_flags(obj, GCFLAG_VISITED)
def free_unvisited_arena_objects_step(self, limit):
- return self.ac.mass_free_incremental(self._free_if_unvisited, limit)
+ return self.ac.mass_free_incremental(_free_if_unvisited, self, limit)
def free_rawmalloced_object_if_unvisited(self, obj, check_flag):
if self.get_flags(obj) & check_flag:
@@ -2405,8 +2395,8 @@
#
# Add the roots from the other sources.
self.root_walker.walk_roots(
- IncrementalMiniMarkGC._collect_ref_stk, # stack roots
- IncrementalMiniMarkGC._collect_ref_stk, # static in prebuilt
non-gc structures
+ IncrementalMiniMarkGCBase._collect_ref_stk, # stack roots
+ IncrementalMiniMarkGCBase._collect_ref_stk, # static in prebuilt
non-gc structures
None) # we don't need the static in all prebuilt gc objects
#
# If we are in an inner collection caused by a call to a finalizer,
@@ -3055,6 +3045,18 @@
def remove_flags(self, obj, flags):
self.header(obj).tid &= ~flags
+
+def _free_if_unvisited(hdr, gc):
+ size_gc_header = gc.gcheaderbuilder.size_gc_header
+ obj = hdr + size_gc_header
+ if gc.get_flags(obj) & GCFLAG_VISITED:
+ gc.remove_flags(obj, GCFLAG_VISITED)
+ return False # survives
+ # dies
+ gc.finalize_header(hdr)
+ return True
+
+
class IncrementalMiniMarkGC(IncrementalMiniMarkGCBase):
HDR = lltype.Struct('header', ('tid', lltype.Signed))
# During a minor collection, the objects in the nursery that are
diff --git a/rpython/memory/gc/incminimark_remoteheader.py
b/rpython/memory/gc/incminimark_remoteheader.py
--- a/rpython/memory/gc/incminimark_remoteheader.py
+++ b/rpython/memory/gc/incminimark_remoteheader.py
@@ -68,15 +68,10 @@
# __free_flags_if_finalized.
hdr.remote_flags[0] |= incminimark.GCFLAG_DEAD
- def __free_flags_if_finalized(self, adr):
- flag_ptr = llmemory.cast_adr_to_ptr(adr, SIGNEDP)
- # If -42, it was set in finalize_header and the object was freed.
- return flag_ptr[0] & incminimark.GCFLAG_DEAD
-
def free_unvisited_arena_objects_step(self, limit):
done =
incminimark.IncrementalMiniMarkGCBase.free_unvisited_arena_objects_step(self,
limit)
self.__ac_for_flags.mass_free_incremental(
- self.__free_flags_if_finalized, done)
+ _free_flags_if_finalized, None, done)
return done
def start_free(self):
@@ -96,3 +91,9 @@
def remove_flags(self, obj, flags):
self.header(obj).remote_flags[0] &= ~flags
+
+
+def _free_flags_if_finalized(adr, unused_arg):
+ flag_ptr = llmemory.cast_adr_to_ptr(adr, SIGNEDP)
+ # If -42, it was set in finalize_header and the object was freed.
+ return bool(flag_ptr[0] & incminimark.GCFLAG_DEAD)
diff --git a/rpython/memory/gc/minimark.py b/rpython/memory/gc/minimark.py
--- a/rpython/memory/gc/minimark.py
+++ b/rpython/memory/gc/minimark.py
@@ -1632,7 +1632,7 @@
# Ask the ArenaCollection to visit all objects. Free the ones
# that have not been visited above, and reset GCFLAG_VISITED on
# the others.
- self.ac.mass_free(self._free_if_unvisited)
+ self.ac.mass_free(_free_if_unvisited, self)
#
# We also need to reset the GCFLAG_VISITED on prebuilt GC objects.
self.prebuilt_root_objects.foreach(self._reset_gcflag_visited, None)
@@ -1682,15 +1682,6 @@
# more allocations.
self.execute_finalizers()
-
- def _free_if_unvisited(self, hdr):
- size_gc_header = self.gcheaderbuilder.size_gc_header
- obj = hdr + size_gc_header
- if self.header(obj).tid & GCFLAG_VISITED:
- self.header(obj).tid &= ~GCFLAG_VISITED
- return False # survives
- return True # dies
-
def _reset_gcflag_visited(self, obj, ignored):
self.header(obj).tid &= ~GCFLAG_VISITED
@@ -2077,3 +2068,12 @@
(obj + offset).address[0] = llmemory.NULL
self.old_objects_with_weakrefs.delete()
self.old_objects_with_weakrefs = new_with_weakref
+
+
+def _free_if_unvisited(hdr, gc):
+ size_gc_header = gc.gcheaderbuilder.size_gc_header
+ obj = hdr + size_gc_header
+ if gc.header(obj).tid & GCFLAG_VISITED:
+ gc.header(obj).tid &= ~GCFLAG_VISITED
+ return False # survives
+ return True # dies
diff --git a/rpython/memory/gc/minimarkpage.py
b/rpython/memory/gc/minimarkpage.py
--- a/rpython/memory/gc/minimarkpage.py
+++ b/rpython/memory/gc/minimarkpage.py
@@ -3,6 +3,7 @@
from rpython.rlib.rarithmetic import LONG_BIT, r_uint
from rpython.rlib.objectmodel import we_are_translated
from rpython.rlib.debug import ll_assert, fatalerror
+from rpython.rlib.objectmodel import specialize
WORD = LONG_BIT // 8
NULL = llmemory.NULL
@@ -334,9 +335,10 @@
size_class -= 1
- def mass_free_incremental(self, ok_to_free_func, max_pages):
- """For each object, if ok_to_free_func(obj) returns True, then free
- the object. This returns True if complete, or False if the limit
+ @specialize.arg(1)
+ def mass_free_incremental(self, ok_to_free_func, func_arg, max_pages):
+ """For each object, if ok_to_free_func(obj, func_arg) returns True,
then
+ free the object. This returns True if complete, or False if the limit
'max_pages' is reached.
"""
size_class = self.size_class_with_old_pages
@@ -350,7 +352,7 @@
# not completely freed are re-chained either in
# 'full_page_for_size[]' or 'page_for_size[]'.
max_pages = self.mass_free_in_pages(size_class, ok_to_free_func,
- max_pages)
+ func_arg, max_pages)
if max_pages <= 0:
self.size_class_with_old_pages = size_class
return False
@@ -364,13 +366,14 @@
return True
- def mass_free(self, ok_to_free_func):
- """For each object, if ok_to_free_func(obj) returns True, then free
- the object.
+ @specialize.arg(1)
+ def mass_free(self, ok_to_free_func, func_arg):
+ """For each object, if ok_to_free_func(obj, func_arg) returns True,
then
+ free the object.
"""
self.mass_free_prepare()
#
- res = self.mass_free_incremental(ok_to_free_func, sys.maxint)
+ res = self.mass_free_incremental(ok_to_free_func, func_arg, sys.maxint)
ll_assert(res, "non-incremental mass_free_in_pages() returned False")
@@ -412,7 +415,9 @@
self.min_empty_nfreepages = 1
- def mass_free_in_pages(self, size_class, ok_to_free_func, max_pages):
+ @specialize.arg(2)
+ def mass_free_in_pages(self, size_class, ok_to_free_func, func_arg,
+ max_pages):
nblocks = self.nblocks_for_size[size_class]
block_size = size_class * WORD
remaining_partial_pages = self.page_for_size[size_class]
@@ -430,7 +435,8 @@
while page != PAGE_NULL:
#
# Collect the page.
- surviving = self.walk_page(page, block_size, ok_to_free_func)
+ surviving = self.walk_page(
+ page, block_size, ok_to_free_func, func_arg)
nextpage = page.nextpage
#
if surviving == nblocks:
@@ -491,7 +497,8 @@
arena.freepages = pageaddr
- def walk_page(self, page, block_size, ok_to_free_func):
+ @specialize.arg(3)
+ def walk_page(self, page, block_size, ok_to_free_func, func_arg):
"""Walk over all objects in a page, and ask ok_to_free_func()."""
#
# 'freeblock' is the next free block
@@ -528,7 +535,7 @@
ll_assert(freeblock > obj,
"freeblocks are linked out of order")
#
- if ok_to_free_func(obj):
+ if ok_to_free_func(obj, func_arg):
#
# The object should die.
llarena.arena_reset(obj, _dummy_size(block_size), 0)
diff --git a/rpython/memory/gc/minimarktest.py
b/rpython/memory/gc/minimarktest.py
--- a/rpython/memory/gc/minimarktest.py
+++ b/rpython/memory/gc/minimarktest.py
@@ -38,11 +38,11 @@
self.all_objects = []
self.total_memory_used = 0
- def mass_free_incremental(self, ok_to_free_func, max_pages):
+ def mass_free_incremental(self, ok_to_free_func, func_arg, max_pages):
old = self.old_all_objects
while old:
rawobj, nsize = old.pop()
- if ok_to_free_func(rawobj):
+ if ok_to_free_func(rawobj, func_arg):
llarena.arena_free(rawobj)
else:
self.all_objects.append((rawobj, nsize))
@@ -52,7 +52,7 @@
return False
return True
- def mass_free(self, ok_to_free_func):
+ def mass_free(self, ok_to_free_func, func_arg):
self.mass_free_prepare()
- res = self.mass_free_incremental(ok_to_free_func, sys.maxint)
+ res = self.mass_free_incremental(ok_to_free_func, func_arg, sys.maxint)
assert res
diff --git a/rpython/memory/gc/test/test_minimarkpage.py
b/rpython/memory/gc/test/test_minimarkpage.py
--- a/rpython/memory/gc/test/test_minimarkpage.py
+++ b/rpython/memory/gc/test/test_minimarkpage.py
@@ -260,7 +260,7 @@
self.lastnum = 0.0
self.seen = {}
- def __call__(self, addr):
+ def __call__(self, addr, arg):
if callable(self.answer):
ok_to_free = self.answer(addr)
else:
@@ -280,7 +280,7 @@
pagesize = hdrsize + 7*WORD
ac = arena_collection_for_test(pagesize, "2", fill_with_objects=2)
ok_to_free = OkToFree(ac, False)
- ac.mass_free(ok_to_free)
+ ac.mass_free(ok_to_free, None)
assert ok_to_free.seen == {hdrsize + 0*WORD: False,
hdrsize + 2*WORD: False}
page = getpage(ac, 0)
@@ -295,7 +295,7 @@
pagesize = hdrsize + 7*WORD
ac = arena_collection_for_test(pagesize, "2", fill_with_objects=2)
ok_to_free = OkToFree(ac, True)
- ac.mass_free(ok_to_free)
+ ac.mass_free(ok_to_free, None)
assert ok_to_free.seen == {hdrsize + 0*WORD: True,
hdrsize + 2*WORD: True}
pageaddr = pagenum(ac, 0)
@@ -307,7 +307,7 @@
pagesize = hdrsize + 7*WORD
ac = arena_collection_for_test(pagesize, "#", fill_with_objects=2)
ok_to_free = OkToFree(ac, False)
- ac.mass_free(ok_to_free)
+ ac.mass_free(ok_to_free, None)
assert ok_to_free.seen == {hdrsize + 0*WORD: False,
hdrsize + 2*WORD: False,
hdrsize + 4*WORD: False}
@@ -323,7 +323,7 @@
pagesize = hdrsize + 9*WORD
ac = arena_collection_for_test(pagesize, "#", fill_with_objects=2)
ok_to_free = OkToFree(ac, 0.5)
- ac.mass_free(ok_to_free)
+ ac.mass_free(ok_to_free, None)
assert ok_to_free.seen == {hdrsize + 0*WORD: False,
hdrsize + 2*WORD: True,
hdrsize + 4*WORD: False,
@@ -348,7 +348,7 @@
assert page.nfree == 4
#
ok_to_free = OkToFree(ac, False)
- ac.mass_free(ok_to_free)
+ ac.mass_free(ok_to_free, None)
assert ok_to_free.seen == {hdrsize + 0*WORD: False,
hdrsize + 4*WORD: False,
hdrsize + 8*WORD: False,
@@ -376,7 +376,7 @@
assert page.nfree == 4
#
ok_to_free = OkToFree(ac, 0.5)
- ac.mass_free(ok_to_free)
+ ac.mass_free(ok_to_free, None)
assert ok_to_free.seen == {hdrsize + 0*WORD: False,
hdrsize + 4*WORD: True,
hdrsize + 8*WORD: False,
@@ -449,10 +449,10 @@
live_objects_extra = {}
fresh_extra = 0
if not incremental:
- ac.mass_free(ok_to_free)
+ ac.mass_free(ok_to_free, None)
else:
ac.mass_free_prepare()
- while not ac.mass_free_incremental(ok_to_free,
+ while not ac.mass_free_incremental(ok_to_free, None,
random.randrange(1, 3)):
print '[]'
prev = ac.total_memory_used
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit