[pypy-svn] r47642 - in pypy/dist/pypy/rpython/memory: . gc gctransform
cfbolz at codespeak.net
cfbolz at codespeak.net
Sat Oct 20 15:17:20 CEST 2007
Author: cfbolz
Date: Sat Oct 20 15:17:18 2007
New Revision: 47642
Modified:
pypy/dist/pypy/rpython/memory/gc/generation.py
pypy/dist/pypy/rpython/memory/gc/semispace.py
pypy/dist/pypy/rpython/memory/gctransform/framework.py
pypy/dist/pypy/rpython/memory/gctypelayout.py
pypy/dist/pypy/rpython/memory/gcwrapper.py
Log:
(cfbolz, arigo review)
In minor collections of the GenerationGC, avoid scanning all static roots.
It is enough to scan the static roots not living inside a GcStruct (there
are only 3 of them in PyPy!) and remember which prebuilt GcStructs have
got a pointer to a young object.
Modified: pypy/dist/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/generation.py (original)
+++ pypy/dist/pypy/rpython/memory/gc/generation.py Sat Oct 20 15:17:18 2007
@@ -1,5 +1,6 @@
import sys
-from pypy.rpython.memory.gc.semispace import SemiSpaceGC
+from pypy.rpython.memory.gc.semispace import SemiSpaceGC, GCFLAGSHIFT, \
+ GCFLAG_IMMORTAL
from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
from pypy.rpython.lltypesystem import lltype, llmemory, llarena
from pypy.rlib.objectmodel import free_non_gc_object, debug_assert
@@ -7,6 +8,7 @@
nonnull_endmarker = llmemory.raw_malloc(llmemory.sizeof(lltype.Char))
llmemory.raw_memclear(nonnull_endmarker, llmemory.sizeof(lltype.Char))
+GCFLAG_REMEMBERED = 2 << GCFLAGSHIFT
class GenerationGC(SemiSpaceGC):
"""A basic generational GC: it's a SemiSpaceGC with an additional
@@ -35,6 +37,7 @@
self.old_objects_pointing_to_young = nonnull_endmarker
# ^^^ the head of a linked list inside the old objects space
self.young_objects_with_weakrefs = self.AddressLinkedList()
+ self.static_to_young_pointer = self.AddressLinkedList()
def reset_nursery(self):
self.nursery = llmemory.NULL
@@ -90,6 +93,7 @@
def semispace_collect(self, size_changing=False):
self.reset_forwarding() # we are doing a full collection anyway
+ self.reset_static()
self.weakrefs_grow_older()
self.reset_nursery()
SemiSpaceGC.semispace_collect(self, size_changing)
@@ -102,6 +106,12 @@
hdr.forw = llmemory.NULL
self.old_objects_pointing_to_young = nonnull_endmarker
+ def reset_static(self):
+ while self.static_to_young_pointer.non_empty():
+ obj = self.static_to_young_pointer.pop()
+ hdr = self.header(obj)
+ hdr.tid &= ~GCFLAG_REMEMBERED
+
def weakrefs_grow_older(self):
while self.young_objects_with_weakrefs.non_empty():
obj = self.young_objects_with_weakrefs.pop()
@@ -117,6 +127,7 @@
# a nursery-only collection
scan = self.free
self.collect_oldrefs_to_nursery()
+ self.collect_static_to_nursery()
self.collect_roots_in_nursery()
self.scan_objects_just_copied_out_of_nursery(scan)
if self.young_objects_with_weakrefs.non_empty():
@@ -149,8 +160,15 @@
hdr.forw = llmemory.NULL
self.old_objects_pointing_to_young = nonnull_endmarker
+ def collect_static_to_nursery(self):
+ while self.static_to_young_pointer.non_empty():
+ obj = self.static_to_young_pointer.pop()
+ hdr = self.header(obj)
+ hdr.tid &= ~GCFLAG_REMEMBERED
+ self.trace_and_drag_out_of_nursery(obj)
+
def collect_roots_in_nursery(self):
- roots = self.get_roots()
+ roots = self.get_roots(with_static=False)
while 1:
root = roots.pop()
if root == NULL:
@@ -217,8 +235,17 @@
def write_barrier(self, addr, addr_to, addr_struct):
if not self.is_in_nursery(addr_struct) and self.is_in_nursery(addr):
- oldhdr = self.header(addr_struct)
- if oldhdr.forw == NULL:
- oldhdr.forw = self.old_objects_pointing_to_young
- self.old_objects_pointing_to_young = addr_struct
+ self.remember_young_pointer(addr_struct, addr)
addr_to.address[0] = addr
+
+ def remember_young_pointer(self, addr_struct, addr):
+ oldhdr = self.header(addr_struct)
+ if oldhdr.forw == NULL:
+ oldhdr.forw = self.old_objects_pointing_to_young
+ self.old_objects_pointing_to_young = addr_struct
+ elif (oldhdr.tid & (GCFLAG_IMMORTAL | GCFLAG_REMEMBERED) ==
+ GCFLAG_IMMORTAL):
+ self.static_to_young_pointer.append(addr_struct)
+ oldhdr.tid |= GCFLAG_REMEMBERED
+ remember_young_pointer.dont_inline = True
+
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 Sat Oct 20 15:17:18 2007
@@ -9,9 +9,12 @@
from pypy.rlib.rarithmetic import ovfcheck
from pypy.rpython.memory.gc.base import MovingGCBase
-
import sys, os
+TYPEID_MASK = 0xffff
+GCFLAGSHIFT = 16
+GCFLAG_IMMORTAL = 1 << GCFLAGSHIFT
+
memoryError = MemoryError()
class SemiSpaceGC(MovingGCBase):
@@ -288,7 +291,7 @@
# immortal objects always have forward to themselves
hdr = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(self.HDR))
hdr.forw = addr + self.gcheaderbuilder.size_gc_header
- hdr.tid = typeid
+ hdr.tid = typeid | GCFLAG_IMMORTAL
def deal_with_objects_with_finalizers(self):
# walk over list of objects with finalizers
Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/dist/pypy/rpython/memory/gctransform/framework.py Sat Oct 20 15:17:18 2007
@@ -112,8 +112,9 @@
# to make the annotator happy. The fields are patched in finish()
# to point to a real array (not 'static_roots', another one).
a_random_address = llmemory.cast_ptr_to_adr(gcdata.type_info_table)
- gcdata.static_root_start = a_random_address # patched in finish()
- gcdata.static_root_end = a_random_address # patched in finish()
+ gcdata.static_root_start = a_random_address # patched in finish()
+ gcdata.static_root_nongcstart = a_random_address # patched in finish()
+ gcdata.static_root_end = a_random_address # patched in finish()
self.gcdata = gcdata
self.malloc_fnptr_cache = {}
@@ -154,6 +155,9 @@
'static_root_start',
annmodel.SomeAddress())
data_classdef.generalize_attr(
+ 'static_root_nongcstart',
+ annmodel.SomeAddress())
+ data_classdef.generalize_attr(
'static_root_end',
annmodel.SomeAddress())
@@ -339,9 +343,12 @@
return top.address[0]
pop_root = staticmethod(pop_root)
- def __init__(self):
+ def __init__(self, with_static=True):
self.stack_current = gcdata.root_stack_top
- self.static_current = gcdata.static_root_start
+ if with_static:
+ self.static_current = gcdata.static_root_start
+ else:
+ self.static_current = gcdata.static_root_nongcstart
def pop(self):
while self.static_current != gcdata.static_root_end:
@@ -400,7 +407,9 @@
ll_instance.inst_type_info_table = table
#self.gcdata.type_info_table = table
- addresses_of_static_ptrs = self.layoutbuilder.addresses_of_static_ptrs
+ addresses_of_static_ptrs = (
+ self.layoutbuilder.addresses_of_static_ptrs +
+ self.layoutbuilder.addresses_of_static_ptrs_in_nongc)
log.info("found %s static roots" % (len(addresses_of_static_ptrs), ))
ll_static_roots_inside = lltype.malloc(lltype.Array(llmemory.Address),
len(addresses_of_static_ptrs),
@@ -408,6 +417,7 @@
for i in range(len(addresses_of_static_ptrs)):
ll_static_roots_inside[i] = addresses_of_static_ptrs[i]
ll_instance.inst_static_root_start = llmemory.cast_ptr_to_adr(ll_static_roots_inside) + llmemory.ArrayItemsOffset(lltype.Array(llmemory.Address))
+ ll_instance.inst_static_root_nongcstart = ll_instance.inst_static_root_start + llmemory.sizeof(llmemory.Address) * len(self.layoutbuilder.addresses_of_static_ptrs)
ll_instance.inst_static_root_end = ll_instance.inst_static_root_start + llmemory.sizeof(llmemory.Address) * len(ll_static_roots_inside)
newgcdependencies = []
Modified: pypy/dist/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctypelayout.py (original)
+++ pypy/dist/pypy/rpython/memory/gctypelayout.py Sat Oct 20 15:17:18 2007
@@ -10,12 +10,13 @@
self.type_info_list = [dummy] # don't use typeid 0, helps debugging
self.id_of_type = {} # {LLTYPE: type_id}
self.seen_roots = {}
- # the following is a list of addresses of gc pointers living inside
- # the prebuilt structures (independently on whether the prebuilt
- # structures are themselves GcStruct or plain Struct). It should
- # list all the locations that could possibly point to a GC heap
- # object.
+ # the following are lists of addresses of gc pointers living inside the
+ # prebuilt structures. It should list all the locations that could
+ # possibly point to a GC heap object.
+ # this lists contains pointers in GcStructs and GcArrays
self.addresses_of_static_ptrs = []
+ # this lists contains pointers in raw Structs and Arrays
+ self.addresses_of_static_ptrs_in_nongc = []
self.finalizer_funcptrs = {}
def get_type_id(self, TYPE):
@@ -27,6 +28,7 @@
# Record the new type_id description as a small dict for now.
# It will be turned into a Struct("type_info") in finish()
type_id = len(self.type_info_list)
+ assert type_id & 0xffff == type_id # make sure it fits into 2 bytes
info = {}
self.type_info_list.append(info)
self.id_of_type[TYPE] = type_id
@@ -151,8 +153,12 @@
# fields are potential roots: unless the structure is immutable,
# they could be changed later to point to GC heap objects.
adr = llmemory.cast_ptr_to_adr(value._as_ptr())
+ if TYPE._gckind == "gc":
+ appendto = self.addresses_of_static_ptrs
+ else:
+ appendto = self.addresses_of_static_ptrs_in_nongc
for a in mutable_gc_pointers_inside(value, adr):
- self.addresses_of_static_ptrs.append(a)
+ appendto.append(a)
# ____________________________________________________________
#
Modified: pypy/dist/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gcwrapper.py (original)
+++ pypy/dist/pypy/rpython/memory/gcwrapper.py Sat Oct 20 15:17:18 2007
@@ -26,11 +26,16 @@
layoutbuilder.consider_constant(TYPE, obj, self.gc)
self.constantroots = layoutbuilder.addresses_of_static_ptrs
+ self.constantrootsnongc = layoutbuilder.addresses_of_static_ptrs_in_nongc
- def get_roots_from_llinterp(self):
+ def get_roots_from_llinterp(self, with_static=True):
sizeofaddr = llmemory.sizeof(llmemory.Address)
ll = [llmemory.NULL] # end marker
- for addrofaddr in self.constantroots:
+ if with_static:
+ for addrofaddr in self.constantroots:
+ if addrofaddr.address[0]:
+ ll.append(addrofaddr)
+ for addrofaddr in self.constantrootsnongc:
if addrofaddr.address[0]:
ll.append(addrofaddr)
for addrofaddr in self.llinterp.find_roots():
More information about the Pypy-commit
mailing list