[pypy-svn] r54450 - in pypy/branch/gc-tweak/pypy/rpython: lltypesystem memory memory/gc memory/gctransform
arigo at codespeak.net
arigo at codespeak.net
Mon May 5 21:56:10 CEST 2008
Author: arigo
Date: Mon May 5 21:56:10 2008
New Revision: 54450
Modified:
pypy/branch/gc-tweak/pypy/rpython/lltypesystem/opimpl.py
pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py
pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py
pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py
pypy/branch/gc-tweak/pypy/rpython/memory/gctransform/framework.py
pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py
pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py
Log:
Experimental. Build on top of the GenerationGC's GCFLAG_NO_HEAP_PTRS
flag to make the HybridGC a full 3-generations collector. Unsure if
the additional complexity is worth the trouble.
Modified: pypy/branch/gc-tweak/pypy/rpython/lltypesystem/opimpl.py
==============================================================================
--- pypy/branch/gc-tweak/pypy/rpython/lltypesystem/opimpl.py (original)
+++ pypy/branch/gc-tweak/pypy/rpython/lltypesystem/opimpl.py Mon May 5 21:56:10 2008
@@ -384,7 +384,8 @@
def op_debug_print(*args):
for arg in args:
- print arg
+ print arg,
+ print
# ____________________________________________________________
Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py (original)
+++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py Mon May 5 21:56:10 2008
@@ -16,8 +16,12 @@
# pointer to a young object.
GCFLAG_NO_YOUNG_PTRS = SemiSpaceGC.first_unused_gcflag << 0
-# The following flag is set for static roots which are not on the list
-# of static roots yet, but will appear with write barrier
+# The following flag is set on some last-generation objects (== prebuilt
+# objects for GenerationGC, but see also HybridGC). The flag is set
+# unless the object is already listed in 'last_generation_root_objects'.
+# When a pointer is written inside an object with GCFLAG_NO_HEAP_PTRS
+# set, the write_barrier clears the flag and adds the object to
+# 'last_generation_root_objects'.
GCFLAG_NO_HEAP_PTRS = SemiSpaceGC.first_unused_gcflag << 1
class GenerationGC(SemiSpaceGC):
@@ -70,6 +74,7 @@
self.lb_young_var_basesize = sz
def setup(self):
+ self.last_generation_root_objects = self.AddressStack()
SemiSpaceGC.setup(self)
self.set_nursery_size(self.initial_nursery_size)
# the GC is fully setup now. The rest can make use of it.
@@ -281,6 +286,31 @@
obj = self.young_objects_with_weakrefs.pop()
self.objects_with_weakrefs.append(obj)
+ def collect_roots(self):
+ self.root_walker.walk_roots(
+ SemiSpaceGC._collect_root, # stack roots
+ SemiSpaceGC._collect_root, # static in prebuilt non-gc structures
+ None) # we don't need the static in prebuilt gc objects
+ self.collect_last_generation_roots()
+
+ def collect_last_generation_roots(self):
+ stack = self.last_generation_root_objects
+ self.last_generation_root_objects = self.AddressStack()
+ while stack.non_empty():
+ obj = stack.pop()
+ self.header(obj).tid |= GCFLAG_NO_HEAP_PTRS
+ # ^^^ the flag we just added will be removed immediately if
+ # the object still contains pointers to younger objects
+ self.trace(obj, self._trace_external_obj, obj)
+ stack.delete()
+
+ def _trace_external_obj(self, pointer, obj):
+ addr = pointer.address[0]
+ if addr != NULL:
+ newaddr = self.copy(addr)
+ pointer.address[0] = newaddr
+ self.write_into_last_generation_obj(obj, newaddr)
+
# ____________________________________________________________
# Implementation of nursery-only collections
@@ -390,25 +420,28 @@
if self.header(addr_struct).tid & GCFLAG_NO_YOUNG_PTRS:
self.remember_young_pointer(addr_struct, newvalue)
- def append_to_static_roots(self, pointer, arg):
- self.root_walker.append_static_root(pointer)
-
- def move_to_static_roots(self, addr_struct):
- objhdr = self.header(addr_struct)
- objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
- self.trace(addr_struct, self.append_to_static_roots, None)
-
def remember_young_pointer(self, addr_struct, addr):
ll_assert(not self.is_in_nursery(addr_struct),
"nursery object with GCFLAG_NO_YOUNG_PTRS")
- oldhdr = self.header(addr_struct)
if self.is_in_nursery(addr):
self.old_objects_pointing_to_young.append(addr_struct)
- oldhdr.tid &= ~GCFLAG_NO_YOUNG_PTRS
- if oldhdr.tid & GCFLAG_NO_HEAP_PTRS:
- self.move_to_static_roots(addr_struct)
+ self.header(addr_struct).tid &= ~GCFLAG_NO_YOUNG_PTRS
+ elif addr == NULL:
+ return
+ self.write_into_last_generation_obj(addr_struct, addr)
remember_young_pointer._dont_inline_ = True
+ def write_into_last_generation_obj(self, addr_struct, addr):
+ objhdr = self.header(addr_struct)
+ if objhdr.tid & GCFLAG_NO_HEAP_PTRS:
+ if not self.is_last_generation(addr):
+ objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS
+ self.last_generation_root_objects.append(addr_struct)
+
+ def is_last_generation(self, obj):
+ # overridden by HybridGC
+ return (self.header(obj).tid & GCFLAG_EXTERNAL) != 0
+
# ____________________________________________________________
import os
Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py
==============================================================================
--- pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py (original)
+++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py Mon May 5 21:56:10 2008
@@ -2,30 +2,72 @@
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 GCFLAG_NO_YOUNG_PTRS
+from pypy.rpython.memory.gc.generation import GCFLAG_NO_HEAP_PTRS
from pypy.rpython.lltypesystem import lltype, llmemory, llarena
from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rlib.debug import ll_assert
from pypy.rlib.rarithmetic import ovfcheck
-# The "age" of an object is the number of times it is copied between the
-# two semispaces. When an object would reach MAX_SEMISPACE_AGE, it is
-# instead copied to a nonmoving location. For example, a value of 4
+# _______in the semispaces_________ ______external (non-moving)_____
+# / \ / \
+# ___raw_malloc'ed__ _prebuilt_
+# +----------------------------------+ / \ / \
+# | | | | | | | |
+# | | | | | | | | age < max age == max
+# |nur-|o|o|o|o| | | +---+ +---+ +---+
+# |sery|b|b|b|b|free| empty | |obj| |obj| |obj|
+# | |j|j|j|j| | | +---+ +---+ +---+
+# | | | | | | | | +---+ +---+ +---+
+# +-----------------+----------------+ |obj| |obj| |obj|
+# age <= max +---+ +---+ +---+
+#
+# |gen1|------------- generation 2 -----------------|-----generation 3-----|
+#
+# Object lists:
+# * gen2_rawmalloced_objects
+# * gen3_rawmalloced_objects
+# * old_objects_pointing_to_young: gen2or3 objs that point to gen1 objs
+# * last_generation_root_objects: gen3 objs that point to gen1or2 objs
+#
+# How to tell the objects apart:
+# * external: tid & GCFLAG_EXTERNAL
+# * gen1: is_in_nursery(obj)
+# * gen3: (tid & (GCFLAG_EXTERNAL|GCFLAG_AGE_MASK)) ==
+# (GCFLAG_EXTERNAL|GCFLAG_AGE_MAX)
+#
+# Some invariants:
+# * gen3 are either GCFLAG_NO_HEAP_PTRS or in 'last_generation_root_objects'
+# * between collections, GCFLAG_UNVISITED set exactly for gen2_rawmalloced
+#
+# A malloc_varsize() of large objects returns objects that are external
+# but initially of generation 2. Old objects from the semispaces are
+# moved to external objects directly as generation 3.
+
+# The "age" of an object is the number of times it survived a full
+# collections, without counting the step that moved it out of the nursery.
+# When a semispace-based object would grow older than MAX_SEMISPACE_AGE,
+# it is instead copied to a nonmoving location. For example, a value of 3
# ensures that an object is copied at most 5 times in total: from the
# nursery to the semispace, then three times between the two spaces,
# then one last time to a nonmoving location.
-MAX_SEMISPACE_AGE = 4
+MAX_SEMISPACE_AGE = 3
GCFLAG_UNVISITED = GenerationGC.first_unused_gcflag << 0
_gcflag_next_bit = GenerationGC.first_unused_gcflag << 1
GCFLAG_AGE_ONE = _gcflag_next_bit
-GCFLAG_AGE_MAX = _gcflag_next_bit * (MAX_SEMISPACE_AGE-1)
+GCFLAG_AGE_MAX = _gcflag_next_bit * MAX_SEMISPACE_AGE
GCFLAG_AGE_MASK = 0
while GCFLAG_AGE_MASK < GCFLAG_AGE_MAX:
GCFLAG_AGE_MASK |= _gcflag_next_bit
_gcflag_next_bit <<= 1
+# The 3rd generation objects are only collected after the following
+# number of calls to semispace_collect():
+GENERATION3_COLLECT_THRESHOLD = 20
+
class HybridGC(GenerationGC):
"""A two-generations semi-space GC like the GenerationGC,
@@ -33,6 +75,7 @@
they are allocated via raw_malloc/raw_free in a mark-n-sweep fashion.
"""
first_unused_gcflag = _gcflag_next_bit
+ prebuilt_gc_objects_are_static_roots = True
# the following values override the default arguments of __init__ when
# translating to a real backend.
@@ -66,10 +109,12 @@
self.large_objects_collect_trigger = self.space_size
if DEBUG_PRINT:
self._initial_trigger = self.large_objects_collect_trigger
- self.pending_external_object_list = self.AddressDeque()
+ self.rawmalloced_objects_to_trace = self.AddressStack()
+ self.count_semispaceonly_collects = 0
def setup(self):
- self.large_objects_list = self.AddressDeque()
+ self.gen2_rawmalloced_objects = self.AddressStack()
+ self.gen3_rawmalloced_objects = self.AddressStack()
GenerationGC.setup(self)
def set_max_heap_size(self, size):
@@ -184,7 +229,7 @@
# need to follow suit.
llmemory.raw_memclear(result, totalsize)
size_gc_header = self.gcheaderbuilder.size_gc_header
- self.large_objects_list.append(result + size_gc_header)
+ self.gen2_rawmalloced_objects.append(result + size_gc_header)
return result
def allocate_external_object(self, totalsize):
@@ -192,19 +237,62 @@
# If so, we'd also use arena_reset() in malloc_varsize_marknsweep().
return llmemory.raw_malloc(totalsize)
+ def init_gc_object_immortal(self, addr, typeid,
+ flags=(GCFLAG_NO_YOUNG_PTRS |
+ GCFLAG_NO_HEAP_PTRS |
+ GCFLAG_AGE_MAX)):
+ GenerationGC.init_gc_object_immortal(self, addr, typeid, flags)
+
+ # ___________________________________________________________________
+ # collect() and semispace_collect() are not synonyms in this GC: the
+ # former is a complete collect, while the latter is only collecting
+ # the semispaces and not always doing the mark-n-sweep pass over the
+ # external objects of 3rd generation.
+
+ def collect(self):
+ self.count_semispaceonly_collects = GENERATION3_COLLECT_THRESHOLD
+ GenerationGC.collect(self)
+
+ def is_collecting_gen3(self):
+ count = self.count_semispaceonly_collects
+ return count >= GENERATION3_COLLECT_THRESHOLD
+
# ___________________________________________________________________
# the following methods are hook into SemiSpaceGC.semispace_collect()
def starting_full_collect(self):
- # At the start of a collection, all raw_malloc'ed objects should
- # have the GCFLAG_UNVISITED bit set. No other object ever has
- # this bit set.
- ll_assert(not self.pending_external_object_list.non_empty(),
- "pending_external_object_list should be empty at start")
+ # At the start of a collection, the GCFLAG_UNVISITED bit is set
+ # exactly on the objects in gen2_rawmalloced_objects. Only
+ # raw_malloc'ed objects can ever have this bit set.
+ self.count_semispaceonly_collects += 1
+ if self.is_collecting_gen3():
+ # set the GCFLAG_UNVISITED on all rawmalloced generation-3 objects
+ # as well, to let them be recorded by visit_external_object()
+ self.gen3_rawmalloced_objects.foreach(self._set_gcflag_unvisited,
+ None)
+ ll_assert(not self.rawmalloced_objects_to_trace.non_empty(),
+ "rawmalloced_objects_to_trace should be empty at start")
if DEBUG_PRINT:
self._nonmoving_copy_count = 0
self._nonmoving_copy_size = 0
+ def _set_gcflag_unvisited(self, obj, ignored):
+ ll_assert(not (self.header(obj).tid & GCFLAG_UNVISITED),
+ "bogus GCFLAG_UNVISITED on gen3 obj")
+ self.header(obj).tid |= GCFLAG_UNVISITED
+
+ def collect_roots(self):
+ if not self.is_collecting_gen3():
+ GenerationGC.collect_roots(self)
+ else:
+ # as we don't record which prebuilt gc objects point to
+ # rawmalloced generation 3 objects, we have to trace all
+ # the prebuilt gc objects.
+ self.root_walker.walk_roots(
+ SemiSpaceGC._collect_root, # stack roots
+ SemiSpaceGC._collect_root, # static in prebuilt non-gc structs
+ SemiSpaceGC._collect_root) # static in prebuilt gc objects
+
def surviving(self, obj):
# To use during a collection. The objects that survive are the
# ones with GCFLAG_FORWARDED set and GCFLAG_UNVISITED not set.
@@ -213,12 +301,16 @@
flags = self.header(obj).tid & (GCFLAG_FORWARDED|GCFLAG_UNVISITED)
return flags == GCFLAG_FORWARDED
+ def is_last_generation(self, obj):
+ return ((self.header(obj).tid & (GCFLAG_EXTERNAL|GCFLAG_AGE_MASK)) ==
+ (GCFLAG_EXTERNAL|GCFLAG_AGE_MAX))
+
def visit_external_object(self, obj):
hdr = self.header(obj)
if hdr.tid & GCFLAG_UNVISITED:
# This is a not-visited-yet raw_malloced object.
hdr.tid -= GCFLAG_UNVISITED
- self.pending_external_object_list.append(obj)
+ self.rawmalloced_objects_to_trace.append(obj)
def make_a_copy(self, obj, objsize):
# During a full collect, all copied objects might implicitly come
@@ -258,8 +350,14 @@
hdr = self.header(newobj)
hdr.tid |= self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS
# GCFLAG_UNVISITED is not set
- self.large_objects_list.append(newobj)
- self.pending_external_object_list.append(newobj)
+ # GCFLAG_NO_HEAP_PTRS is not set either, conservatively. It may be
+ # set by the next collection's collect_last_generation_roots().
+ # This old object is immediately put at generation 3.
+ ll_assert(self.is_last_generation(newobj),
+ "make_a_nonmoving_copy: object too young")
+ self.gen3_rawmalloced_objects.append(newobj)
+ self.last_generation_root_objects.append(newobj)
+ self.rawmalloced_objects_to_trace.append(newobj) # visit me
return newobj
def scan_copied(self, scan):
@@ -270,23 +368,62 @@
newscan = GenerationGC.scan_copied(self, scan)
progress = newscan != scan
scan = newscan
- while self.pending_external_object_list.non_empty():
- obj = self.pending_external_object_list.popleft()
+ while self.rawmalloced_objects_to_trace.non_empty():
+ obj = self.rawmalloced_objects_to_trace.pop()
self.trace_and_copy(obj)
progress = True
return scan
def finished_full_collect(self):
- ll_assert(not self.pending_external_object_list.non_empty(),
- "pending_external_object_list should be empty at end")
- # free all mark-n-sweep-managed objects that have not been marked
- large_objects = self.large_objects_list
- remaining_large_objects = self.AddressDeque()
+ ll_assert(not self.rawmalloced_objects_to_trace.non_empty(),
+ "rawmalloced_objects_to_trace should be empty at end")
+ if DEBUG_PRINT:
+ llop.debug_print(lltype.Void,
+ "| [hybrid] made nonmoving: ",
+ self._nonmoving_copy_size, "bytes in",
+ self._nonmoving_copy_count, "objs")
+ # sweep the nonmarked rawmalloced objects
+ if self.is_collecting_gen3():
+ self.sweep_rawmalloced_objects(generation=3)
+ self.sweep_rawmalloced_objects(generation=2)
+ # As we just collected, it's fine to raw_malloc'ate up to space_size
+ # bytes again before we should force another collect.
+ self.large_objects_collect_trigger = self.space_size
+ if self.is_collecting_gen3():
+ self.count_semispaceonly_collects = 0
+ if DEBUG_PRINT:
+ self._initial_trigger = self.large_objects_collect_trigger
+
+ def sweep_rawmalloced_objects(self, generation):
+ # free all the rawmalloced objects of the specified generation
+ # that have not been marked
+ if generation == 2:
+ objects = self.gen2_rawmalloced_objects
+ # generation 2 sweep: if A points to an object object B that
+ # moves from gen2 to gen3, it's possible that A no longer points
+ # to any gen2 object. In this case, A remains a bit too long in
+ # last_generation_root_objects, but this will be fixed by the
+ # next collect_last_generation_roots().
+ else:
+ objects = self.gen3_rawmalloced_objects
+ # generation 3 sweep: remove from last_generation_root_objects
+ # all the objects that we are about to free
+ gen3roots = self.last_generation_root_objects
+ newgen3roots = self.AddressStack()
+ while gen3roots.non_empty():
+ obj = gen3roots.pop()
+ if not (self.header(obj).tid & GCFLAG_UNVISITED):
+ newgen3roots.append(obj)
+ gen3roots.delete()
+ self.last_generation_root_objects = newgen3roots
+
+ surviving_objects = self.AddressStack()
if DEBUG_PRINT: alive_count = alive_size = 0
if DEBUG_PRINT: dead_count = dead_size = 0
- while large_objects.non_empty():
- obj = large_objects.popleft()
- if self.header(obj).tid & GCFLAG_UNVISITED:
+ while objects.non_empty():
+ obj = objects.pop()
+ tid = self.header(obj).tid
+ if tid & GCFLAG_UNVISITED:
if DEBUG_PRINT:dead_count+=1
if DEBUG_PRINT:dead_size+=raw_malloc_usage(self.get_size(obj))
addr = obj - self.gcheaderbuilder.size_gc_header
@@ -294,25 +431,35 @@
else:
if DEBUG_PRINT:alive_count+=1
if DEBUG_PRINT:alive_size+=raw_malloc_usage(self.get_size(obj))
- self.header(obj).tid |= GCFLAG_UNVISITED
- remaining_large_objects.append(obj)
- large_objects.delete()
- self.large_objects_list = remaining_large_objects
- # As we just collected, it's fine to raw_malloc'ate up to space_size
- # bytes again before we should force another collect.
- self.large_objects_collect_trigger = self.space_size
-
+ if generation == 3:
+ surviving_objects.append(obj)
+ else:
+ ll_assert((tid & GCFLAG_AGE_MASK) < GCFLAG_AGE_MAX,
+ "wrong age for generation 2 object")
+ tid += GCFLAG_AGE_ONE
+ if (tid & GCFLAG_AGE_MASK) == GCFLAG_AGE_MAX:
+ # the object becomes part of generation 3
+ self.gen3_rawmalloced_objects.append(obj)
+ # GCFLAG_NO_HEAP_PTRS not set yet, conservatively
+ self.last_generation_root_objects.append(obj)
+ else:
+ # the object stays in generation 2
+ tid |= GCFLAG_UNVISITED
+ surviving_objects.append(obj)
+ self.header(obj).tid = tid
+ objects.delete()
+ if generation == 2:
+ self.gen2_rawmalloced_objects = surviving_objects
+ else:
+ self.gen3_rawmalloced_objects = surviving_objects
if DEBUG_PRINT:
- self._initial_trigger = self.large_objects_collect_trigger
- llop.debug_print(lltype.Void,
- "| [hybrid] made nonmoving: ",
- self._nonmoving_copy_size, "bytes in",
- self._nonmoving_copy_count, "objs")
llop.debug_print(lltype.Void,
- "| [hybrid] nonmoving now alive: ",
+ "| [hyb] gen", generation,
+ "nonmoving now alive: ",
alive_size, "bytes in",
alive_count, "objs")
llop.debug_print(lltype.Void,
- "| [hybrid] nonmoving freed: ",
+ "| [hyb] gen", generation,
+ "nonmoving freed: ",
dead_size, "bytes in",
dead_count, "objs")
Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py (original)
+++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py Mon May 5 21:56:10 2008
@@ -21,7 +21,7 @@
GCFLAG_EXTERNAL = first_gcflag << 1
GCFLAG_FINALIZATION_ORDERING = first_gcflag << 2
-DEBUG_PRINT = False
+DEBUG_PRINT = True
memoryError = MemoryError()
class SemiSpaceGC(MovingGCBase):
@@ -205,6 +205,7 @@
self.semispace_collect()
# the indirection is required by the fact that collect() is referred
# to by the gc transformer, and the default argument would crash
+ # (this is also a hook for the HybridGC)
def semispace_collect(self, size_changing=False):
if DEBUG_PRINT:
Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/gc-tweak/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/branch/gc-tweak/pypy/rpython/memory/gctransform/framework.py Mon May 5 21:56:10 2008
@@ -391,11 +391,8 @@
self.layoutbuilder.addresses_of_static_ptrs_in_nongc +
self.layoutbuilder.addresses_of_static_ptrs)
log.info("found %s static roots" % (len(addresses_of_static_ptrs), ))
- additional_ptrs = self.layoutbuilder.additional_roots_sources
- log.info("additional %d potential static roots" % additional_ptrs)
ll_static_roots_inside = lltype.malloc(lltype.Array(llmemory.Address),
- len(addresses_of_static_ptrs) +
- additional_ptrs,
+ len(addresses_of_static_ptrs),
immortal=True)
for i in range(len(addresses_of_static_ptrs)):
ll_static_roots_inside[i] = addresses_of_static_ptrs[i]
@@ -788,10 +785,6 @@
def setup_root_walker(self):
pass
- def append_static_root(self, adr):
- self.gcdata.static_root_end.address[0] = adr
- self.gcdata.static_root_end += sizeofaddr
-
def walk_roots(self, collect_stack_root,
collect_static_in_prebuilt_nongc,
collect_static_in_prebuilt_gc):
Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py (original)
+++ pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py Mon May 5 21:56:10 2008
@@ -193,10 +193,6 @@
self.addresses_of_static_ptrs = []
# this lists contains pointers in raw Structs and Arrays
self.addresses_of_static_ptrs_in_nongc = []
- # if not gc.prebuilt_gc_objects_are_static_roots, then
- # additional_roots_sources counts the number of locations
- # within prebuilt GC objects that are of type Ptr(Gc)
- self.additional_roots_sources = 0
self.finalizer_funcptrs = {}
self.offsettable_cache = {}
self.next_typeid_cache = {}
@@ -292,8 +288,6 @@
adr = llmemory.cast_ptr_to_adr(value._as_ptr())
if TYPE._gckind == "gc":
if not gc.prebuilt_gc_objects_are_static_roots:
- for a in gc_pointers_inside(value, adr):
- self.additional_roots_sources += 1
return
else:
appendto = self.addresses_of_static_ptrs
Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py (original)
+++ pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py Mon May 5 21:56:10 2008
@@ -114,9 +114,6 @@
def __init__(self, gcheap):
self.gcheap = gcheap
- def append_static_root(self, pointer):
- self.gcheap.constantroots.append(pointer)
-
def walk_roots(self, collect_stack_root,
collect_static_in_prebuilt_nongc,
collect_static_in_prebuilt_gc):
More information about the Pypy-commit
mailing list