[pypy-svn] r77095 - in pypy/branch/gen2-gc/pypy/rpython: lltypesystem memory/gc
arigo at codespeak.net
arigo at codespeak.net
Wed Sep 15 17:39:47 CEST 2010
Author: arigo
Date: Wed Sep 15 17:39:45 2010
New Revision: 77095
Modified:
pypy/branch/gen2-gc/pypy/rpython/lltypesystem/llarena.py
pypy/branch/gen2-gc/pypy/rpython/memory/gc/minimark.py
Log:
Implement identityhash().
Modified: pypy/branch/gen2-gc/pypy/rpython/lltypesystem/llarena.py
==============================================================================
--- pypy/branch/gen2-gc/pypy/rpython/lltypesystem/llarena.py (original)
+++ pypy/branch/gen2-gc/pypy/rpython/lltypesystem/llarena.py Wed Sep 15 17:39:45 2010
@@ -303,6 +303,7 @@
assert isinstance(arena_addr, fakearenaaddress)
assert arena_addr.offset == 0
arena_addr.arena.reset(False)
+ assert not arena_addr.arena.objectptrs
arena_addr.arena.freed = True
def arena_reset(arena_addr, size, zero):
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 17:39:45 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 ovfcheck, LONG_BIT
+from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask
from pypy.rlib.debug import ll_assert, debug_print
WORD = LONG_BIT // 8
@@ -25,6 +25,11 @@
# The following flag is set on surviving objects during a major collection.
GCFLAG_VISITED = first_gcflag << 2
+# The following flag is set on objects that have an extra hash field,
+# except on nursery objects, where it means that it *will* grow a hash
+# field when moving.
+GCFLAG_HASHFIELD = first_gcflag << 3
+
# Marker set to 'tid' during a minor collection when an object from
# the nursery was forwarded.
FORWARDED_MARKER = -1
@@ -85,6 +90,7 @@
MovingGCBase.__init__(self, config, chunk_size)
self.nursery_size = nursery_size
self.small_request_threshold = small_request_threshold
+ self.nursery_hash_base = -1
#
# The ArenaCollection() handles the nonmovable objects allocation.
if ArenaCollectionClass is None:
@@ -376,6 +382,7 @@
llarena.arena_reset(self.nursery, self.nursery_size, 2)
self.nursery_next = self.nursery
#
+ self.change_nursery_hash_base()
self.debug_check_consistency() # XXX expensive!
@@ -428,17 +435,26 @@
return
#
# First visit to 'obj': we must move it out of the nursery.
- # Allocate a new nonmovable location for it.
size_gc_header = self.gcheaderbuilder.size_gc_header
size = self.get_size(obj)
totalsize = size_gc_header + size
- newhdr = self.ac.malloc(totalsize)
+ totalsize_incl_hash = totalsize
+ if self.header(obj).tid & GCFLAG_HASHFIELD:
+ totalsize_incl_hash += llmemory.sizeof(lltype.Signed)
+ #
+ # Allocate a new nonmovable location for it.
+ newhdr = self.ac.malloc(totalsize_incl_hash)
newobj = newhdr + size_gc_header
#
# Copy it. Note that references to other objects in the
# nursery are kept unchanged in this step.
llmemory.raw_memcopy(obj - size_gc_header, newhdr, totalsize)
#
+ # Write the hash field too, if necessary.
+ if self.header(obj).tid & GCFLAG_HASHFIELD:
+ hash = self._compute_current_nursery_hash(obj)
+ (newhdr + (size_gc_header + size)).signed[0] = hash
+ #
# Set the old object's tid to FORWARDED_MARKER and replace
# the old object's content with the target address.
# A bit of no-ops to convince llarena that we are changing
@@ -578,9 +594,9 @@
# ----------
# id() support
- def id(self, ptr):
+ def id(self, gcobj):
"""Implement id() of an object, given as a GCREF."""
- obj = llmemory.cast_ptr_to_adr(ptr)
+ obj = llmemory.cast_ptr_to_adr(gcobj)
#
# Is it a tagged pointer? For them, the result is odd-valued.
if not self.is_valid_gc_object(obj):
@@ -630,6 +646,46 @@
self.id_free_list.append(id)
+ # ----------
+ # identityhash() support
+
+ def identityhash(self, gcobj):
+ obj = llmemory.cast_ptr_to_adr(gcobj)
+ if self.is_in_nursery(obj):
+ #
+ # A nursery object's identityhash is never stored with the
+ # object, but returned by _compute_current_nursery_hash().
+ # But we must set the GCFLAG_HASHFIELD to remember that
+ # we will have to store it into the object when it moves.
+ self.header(obj).tid |= GCFLAG_HASHFIELD
+ return self._compute_current_nursery_hash(obj)
+ #
+ if self.header(obj).tid & GCFLAG_HASHFIELD:
+ #
+ # An non-moving object with a hash field.
+ objsize = self.get_size(obj)
+ obj = llarena.getfakearenaaddress(obj)
+ return (obj + objsize).signed[0]
+ #
+ # No hash field needed.
+ return llmemory.cast_adr_to_int(obj)
+
+
+ def change_nursery_hash_base(self):
+ # The following should be enough to ensure that young objects
+ # tend to always get a different hash. It also makes sure that
+ # nursery_hash_base is not a multiple of WORD, to avoid collisions
+ # with the hash of non-young objects.
+ hash_base = self.nursery_hash_base
+ hash_base += self.nursery_size - 1
+ if (hash_base & (WORD-1)) == 0:
+ hash_base -= 1
+ self.nursery_hash_base = intmask(hash_base)
+
+ def _compute_current_nursery_hash(self, obj):
+ return intmask(llmemory.cast_adr_to_int(obj) + self.nursery_hash_base)
+
+
# ____________________________________________________________
# For testing, a simple implementation of ArenaCollection.
@@ -651,7 +707,17 @@
ll_assert(nsize <= self.small_request_threshold,"malloc: size too big")
ll_assert((nsize & (WORD-1)) == 0, "malloc: size is not aligned")
#
- result = llmemory.raw_malloc(size)
+ result = llarena.arena_malloc(nsize, False)
+ #
+ # Custom hack for the hash
+ if (isinstance(size, llmemory.CompositeOffset) and
+ isinstance(size.offsets[-1], llmemory.ItemOffset) and
+ size.offsets[-1].TYPE == lltype.Signed):
+ size_of_int = llmemory.sizeof(lltype.Signed)
+ size = sum(size.offsets[1:-1], size.offsets[0])
+ llarena.arena_reserve(result + size, size_of_int)
+ #
+ llarena.arena_reserve(result, size)
self.all_objects.append(result)
return result
@@ -660,6 +726,6 @@
self.all_objects = []
for rawobj in objs:
if ok_to_free_func(rawobj):
- llmemory.raw_free(rawobj)
+ llarena.arena_free(rawobj)
else:
self.all_objects.append(rawobj)
More information about the Pypy-commit
mailing list