[pypy-svn] r77091 - pypy/branch/gen2-gc/pypy/rpython/memory/gc
arigo at codespeak.net
arigo at codespeak.net
Wed Sep 15 15:45:58 CEST 2010
Author: arigo
Date: Wed Sep 15 15:45:57 2010
New Revision: 77091
Modified:
pypy/branch/gen2-gc/pypy/rpython/memory/gc/minimark.py
Log:
* malloc_varsize_clear().
* external_malloc().
Modified: pypy/branch/gen2-gc/pypy/rpython/memory/gc/minimark.py
==============================================================================
--- pypy/branch/gen2-gc/pypy/rpython/memory/gc/minimark.py (original)
+++ pypy/branch/gen2-gc/pypy/rpython/memory/gc/minimark.py Wed Sep 15 15:45:57 2010
@@ -2,7 +2,7 @@
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rpython.memory.gc.base import MovingGCBase
from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE
-from pypy.rlib.rarithmetic import LONG_BIT
+from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT
from pypy.rlib.debug import ll_assert, debug_print
WORD = LONG_BIT // 8
@@ -53,8 +53,8 @@
# where the object was moved. This means that all objects in the
# nursery need to be at least 2 words long, but objects outside the
# nursery don't need to.
- minimal_size_in_nursery = (llmemory.sizeof(HDR) +
- llmemory.sizeof(llmemory.Address))
+ minimal_size_in_nursery = llmemory.raw_malloc_usage(
+ llmemory.sizeof(HDR) + llmemory.sizeof(llmemory.Address))
TRANSLATION_PARAMS = {
@@ -93,9 +93,6 @@
self.ac = ArenaCollectionClass(arena_size, page_size,
small_request_threshold)
#
- # A list of all raw_malloced objects (the objects too large)
- self.rawmalloced_objects = self.AddressStack()
- #
# Used by minor collection: a list of non-young objects that
# (may) contain a pointer to a young object. Populated by
# the write barrier.
@@ -112,6 +109,9 @@
#
assert self.nursery_size > 0, "XXX"
#
+ # A list of all raw_malloced objects (the objects too large)
+ self.rawmalloced_objects = self.AddressStack()
+ #
# the start of the nursery: we actually allocate a tiny bit more for
# the nursery than really needed, to simplify pointer arithmetic
# in malloc_fixedsize_clear().
@@ -136,24 +136,66 @@
# If totalsize is greater than small_request_threshold, ask for
# a rawmalloc. The following check should be constant-folded.
if llmemory.raw_malloc_usage(totalsize) > self.small_request_threshold:
- return self.external_malloc(typeid, size)
+ result = self.external_malloc(typeid, totalsize)
+ #
+ else:
+ # If totalsize is smaller than minimal_size_in_nursery, round it
+ # up. The following check should also be constant-folded.
+ if (llmemory.raw_malloc_usage(totalsize) <
+ llmemory.raw_malloc_usage(self.minimal_size_in_nursery)):
+ totalsize = self.minimal_size_in_nursery
+ #
+ # Get the memory from the nursery. If there is not enough space
+ # there, do a collect first.
+ result = self.nursery_next
+ self.nursery_next = result + totalsize
+ if self.nursery_next > self.nursery_top:
+ result = self.collect_and_reserve(totalsize)
+ #
+ # Build the object.
+ llarena.arena_reserve(result, totalsize)
+ self.init_gc_object(result, typeid, flags=0)
+ #
+ return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
+
+
+ def malloc_varsize_clear(self, typeid, length, size, itemsize,
+ offset_to_length, can_collect):
+ ll_assert(can_collect, "!can_collect")
+ size_gc_header = self.gcheaderbuilder.size_gc_header
+ nonvarsize = size_gc_header + size
+ try:
+ varsize = ovfcheck(itemsize * length)
+ totalsize = ovfcheck(nonvarsize + varsize)
+ except OverflowError:
+ raise MemoryError
+ #
+ # If totalsize is greater than small_request_threshold, ask for
+ # a rawmalloc.
+ if llmemory.raw_malloc_usage(totalsize) > self.small_request_threshold:
+ result = self.external_malloc(typeid, totalsize)
+ #
+ else:
+ # 'totalsize' should contain at least the GC header and
+ # the length word, so it should never be smaller than
+ # 'minimal_size_in_nursery' so far
+ ll_assert(llmemory.raw_malloc_usage(totalsize) >=
+ self.minimal_size_in_nursery,
+ "malloc_varsize_clear(): totalsize < minimalsize")
+ #
+ # Get the memory from the nursery. If there is not enough space
+ # there, do a collect first.
+ result = self.nursery_next
+ self.nursery_next = result + totalsize
+ if self.nursery_next > self.nursery_top:
+ result = self.collect_and_reserve(totalsize)
+ #
+ # Build the object.
+ llarena.arena_reserve(result, totalsize)
+ self.init_gc_object(result, typeid, flags=0)
#
- # If totalsize is smaller than minimal_size_in_nursery, round it up.
- # The following check should also be constant-folded.
- if (llmemory.raw_malloc_usage(totalsize) <
- llmemory.raw_malloc_usage(self.minimal_size_in_nursery)):
- totalsize = self.minimal_size_in_nursery
- #
- # Get the memory from the nursery. If there is not enough space
- # there, do a collect first.
- result = self.nursery_next
- self.nursery_next = result + totalsize
- if self.nursery_next > self.nursery_top:
- result = self.collect_and_reserve(totalsize)
- #
- # Build the object.
- llarena.arena_reserve(result, totalsize)
- self.init_gc_object(result, typeid, flags=0)
+ # Set the length and return the object.
+ (result + size_gc_header + offset_to_length).signed[0] = length
return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
@@ -175,22 +217,19 @@
collect_and_reserve._dont_inline_ = True
- def external_malloc(self, typeid, size):
+ def external_malloc(self, typeid, totalsize):
"""Allocate a large object using raw_malloc()."""
#
- # First check if we are called because we wanted to allocate
- # an object that is larger than self.small_request_threshold.
- size_gc_header = self.gcheaderbuilder.size_gc_header
- totalsize = size_gc_header + size
- xxxxxxx
- #
- # Yes: just use a raw_malloc() to get the object.
result = llmemory.raw_malloc(totalsize)
if not result:
- raise MemoryError()
- raw_memclear(result, totalsize)
+ raise MemoryError("cannot allocate large object")
+ llmemory.raw_memclear(result, totalsize)
+ self.init_gc_object(result, typeid, GCFLAG_NO_YOUNG_PTRS)
+ #
+ size_gc_header = self.gcheaderbuilder.size_gc_header
self.rawmalloced_objects.append(result + size_gc_header)
return result
+ external_malloc._dont_inline_ = True
# ----------
@@ -301,8 +340,6 @@
"""Perform a minor collection: find the objects from the nursery
that remain alive and move them out."""
#
- #print "nursery_collect()"
- #
# First, find the roots that point to nursery objects. These
# nursery objects are copied out of the nursery. Note that
# references to further nursery objects are not modified by
@@ -428,6 +465,10 @@
self.collect_roots()
self.visit_all_objects()
#
+ # Walk all rawmalloced objects and free the ones that don't
+ # have the GCFLAG_VISITED flag.
+ self.free_unvisited_rawmalloc_objects()
+ #
# Ask the ArenaCollection to visit all objects. Free the ones
# that have not been visited above, and reset GCFLAG_VISITED on
# the others.
@@ -451,6 +492,21 @@
def _reset_gcflag_visited(self, obj, ignored=None):
self.header(obj).tid &= ~GCFLAG_VISITED
+ def free_unvisited_rawmalloc_objects(self):
+ size_gc_header = self.gcheaderbuilder.size_gc_header
+ list = self.rawmalloced_objects
+ self.rawmalloced_objects = self.AddressStack()
+ #
+ while list.non_empty():
+ obj = list.pop()
+ if self.header(obj).tid & GCFLAG_VISITED:
+ self.header(obj).tid &= ~GCFLAG_VISITED # survives
+ self.rawmalloced_objects.append(obj)
+ else:
+ llmemory.raw_free(obj - size_gc_header)
+ #
+ list.delete()
+
def collect_roots(self):
# Collect all roots. Starts from all the objects
More information about the Pypy-commit
mailing list