[pypy-svn] r68739 - in pypy/branch/gc-dump-heap/pypy: rlib rpython rpython/lltypesystem rpython/memory/gc rpython/memory/gctransform rpython/memory/test
fijal at codespeak.net
fijal at codespeak.net
Sun Oct 25 21:00:09 CET 2009
Author: fijal
Date: Sun Oct 25 21:00:07 2009
New Revision: 68739
Modified:
pypy/branch/gc-dump-heap/pypy/rlib/rgc.py
pypy/branch/gc-dump-heap/pypy/rpython/llinterp.py
pypy/branch/gc-dump-heap/pypy/rpython/lltypesystem/lloperation.py
pypy/branch/gc-dump-heap/pypy/rpython/lltypesystem/opimpl.py
pypy/branch/gc-dump-heap/pypy/rpython/memory/gc/base.py
pypy/branch/gc-dump-heap/pypy/rpython/memory/gc/semispace.py
pypy/branch/gc-dump-heap/pypy/rpython/memory/gctransform/framework.py
pypy/branch/gc-dump-heap/pypy/rpython/memory/test/test_gc.py
pypy/branch/gc-dump-heap/pypy/rpython/memory/test/test_transformed_gc.py
Log:
Implement heap dumping for a semispace gc. fails with generation and hybrid
for now. Also explodes on C backend.
Introduce a new operation llop.get_member_index which returns an index
in memberoffset
Modified: pypy/branch/gc-dump-heap/pypy/rlib/rgc.py
==============================================================================
--- pypy/branch/gc-dump-heap/pypy/rlib/rgc.py (original)
+++ pypy/branch/gc-dump-heap/pypy/rlib/rgc.py Sun Oct 25 21:00:07 2009
@@ -184,6 +184,41 @@
hop.exception_cannot_occur()
return hop.genop('gc_can_move', hop.args_v, resulttype=hop.r_result)
+def dump_heap(fd):
+ import os
+
+ tb = _dump_heap()
+ for i in range(len(tb)):
+ next = tb[i]
+ os.write(fd, str(next.count) + " " + ",".join([
+ str(next.links[j]) for j in range(len(tb))]) + "\n")
+ _clear_dump_heap(tb)
+
+def _clear_dump_heap(tb):
+ from pypy.rpython.lltypesystem import lltype
+ for i in range(len(tb)):
+ lltype.free(tb[i].links, flavor='raw')
+ lltype.free(tb, flavor='raw')
+
+def _dump_heap():
+ raise NotImplementedError # can't be run directly
+
+class DumpHeapEntry(ExtRegistryEntry):
+ _about_ = _dump_heap
+
+ def compute_result_annotation(self):
+ from pypy.annotation import model as annmodel
+ from pypy.rpython.memory.gc.base import ARRAY_TYPEID_MAP
+ from pypy.rpython.lltypesystem import lltype
+ return annmodel.SomePtr(lltype.Ptr(ARRAY_TYPEID_MAP))
+
+ def specialize_call(self, hop):
+ from pypy.rpython.lltypesystem import lltype
+ from pypy.rpython.memory.gc.base import ARRAY_TYPEID_MAP
+ from pypy.rpython.lltypesystem import lltype
+ hop.exception_cannot_occur()
+ return hop.genop('gc_dump_heap', [], resulttype=hop.r_result)
+
def malloc_nonmovable(TP, n=None, zero=False):
""" Allocate a non-moving buffer or return nullptr.
When running directly, will pretend that gc is always
Modified: pypy/branch/gc-dump-heap/pypy/rpython/llinterp.py
==============================================================================
--- pypy/branch/gc-dump-heap/pypy/rpython/llinterp.py (original)
+++ pypy/branch/gc-dump-heap/pypy/rpython/llinterp.py Sun Oct 25 21:00:07 2009
@@ -824,8 +824,8 @@
def op_gc_assume_young_pointers(self, addr):
raise NotImplementedError
- def op_gc_dump_heap(self, fd):
- raise NotImplementedError # impossible
+ def op_gc_dump_heap(self):
+ raise NotImplementedError
def op_gc_obtain_free_space(self, size):
raise NotImplementedError
Modified: pypy/branch/gc-dump-heap/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/gc-dump-heap/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/branch/gc-dump-heap/pypy/rpython/lltypesystem/lloperation.py Sun Oct 25 21:00:07 2009
@@ -422,6 +422,7 @@
'extract_ushort': LLOp(canfold=True),
'combine_ushort': LLOp(canfold=True),
'gc_gettypeptr_group': LLOp(canfold=True),
+ 'get_member_index': LLOp(canfold=True),
# __________ used by the JIT ________
Modified: pypy/branch/gc-dump-heap/pypy/rpython/lltypesystem/opimpl.py
==============================================================================
--- pypy/branch/gc-dump-heap/pypy/rpython/lltypesystem/opimpl.py (original)
+++ pypy/branch/gc-dump-heap/pypy/rpython/lltypesystem/opimpl.py Sun Oct 25 21:00:07 2009
@@ -429,6 +429,11 @@
return lltype.cast_pointer(TYPE, member)
op_get_group_member.need_result_type = True
+def op_get_member_index(memberoffset):
+ from pypy.rpython.lltypesystem import llgroup
+ assert isinstance(memberoffset, llgroup.GroupMemberOffset)
+ return memberoffset.index
+
def op_get_next_group_member(TYPE, grpptr, memberoffset, skipoffset):
from pypy.rpython.lltypesystem import llgroup
assert isinstance(memberoffset, llgroup.GroupMemberOffset)
Modified: pypy/branch/gc-dump-heap/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/gc-dump-heap/pypy/rpython/memory/gc/base.py (original)
+++ pypy/branch/gc-dump-heap/pypy/rpython/memory/gc/base.py Sun Oct 25 21:00:07 2009
@@ -6,6 +6,10 @@
from pypy.rpython.memory.support import AddressDict
from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
+TYPEID_MAP = lltype.Struct('TYPEID_MAP', ('count', lltype.Signed),
+ ('links', lltype.Array(lltype.Signed)))
+ARRAY_TYPEID_MAP = lltype.Array(lltype.Ptr(TYPEID_MAP))
+
class GCBase(object):
_alloc_flavor_ = "raw"
moving_gc = False
Modified: pypy/branch/gc-dump-heap/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/branch/gc-dump-heap/pypy/rpython/memory/gc/semispace.py (original)
+++ pypy/branch/gc-dump-heap/pypy/rpython/memory/gc/semispace.py Sun Oct 25 21:00:07 2009
@@ -9,7 +9,8 @@
from pypy.rlib.debug import ll_assert
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rlib.rarithmetic import ovfcheck
-from pypy.rpython.memory.gc.base import MovingGCBase
+from pypy.rpython.memory.gc.base import MovingGCBase, ARRAY_TYPEID_MAP,\
+ TYPEID_MAP
import sys, os, time
@@ -24,9 +25,6 @@
memoryError = MemoryError()
-ARRAY_OF_SIGNED = lltype.Array(lltype.Signed)
-
-
class SemiSpaceGC(MovingGCBase):
_alloc_flavor_ = "raw"
inline_simple_malloc = True
@@ -639,24 +637,38 @@
#
return llmemory.cast_adr_to_int(obj) # direct case
- def _dump_heap_extraarg(self, addr, ignored):
+ def _dump_heap_extraarg(self, addr, parent):
+ parent_idx = llop.get_member_index(lltype.Signed,
+ self.get_type_id(parent))
+ idx = llop.get_member_index(lltype.Signed,
+ self.get_type_id(addr.address[0]))
+ self._ll_typeid_map[parent_idx].links[idx] += 1
self._dump_heap(addr)
- def _dump_heap(self, addr):
- os.write(self._fd_dump, "X")
- self.trace(addr, self._dump_heap_extraarg, None)
-
- def dump_heap(self, fd):
- ll_typeid_usage = lltype.nullptr(ARRAY_OF_SIGNED)
- self._fd_dump = fd
- try:
- ll_typeid_usage = lltype.malloc(ARRAY_OF_SIGNED,
- self.root_walker.gcdata.max_type_id, flavor='raw')
- self.root_walker.walk_roots(
- SemiSpaceGC._dump_heap, # stack roots
- SemiSpaceGC._dump_heap, # static in prebuilt non-gc structures
- SemiSpaceGC._dump_heap) # static in prebuilt gc objects
- finally:
- if ll_typeid_usage:
- lltype.free(ll_typeid_usage, flavor='raw')
- self._fd_dump = -1
+ def _dump_heap(self, root):
+ adr = root.address[0]
+ idx = llop.get_member_index(lltype.Signed, self.get_type_id(adr))
+ self._ll_typeid_map[idx].count += 1
+ self.trace(adr, self._dump_heap_extraarg, adr)
+
+ def dump_heap(self):
+ max_tid = self.root_walker.gcdata.max_type_id
+ ll_typeid_map = lltype.malloc(ARRAY_TYPEID_MAP, max_tid,
+ flavor='raw')
+ i = 0
+ while i < max_tid:
+ ll_typeid_map[i] = lltype.malloc(TYPEID_MAP, max_tid,
+ flavor='raw')
+ ll_typeid_map[i].count = 0
+ j = 0
+ while j < max_tid:
+ ll_typeid_map[i].links[j] = 0
+ j += 1
+ i += 1
+ self._ll_typeid_map = ll_typeid_map
+ self.root_walker.walk_roots(
+ SemiSpaceGC._dump_heap, # stack roots
+ SemiSpaceGC._dump_heap, # static in prebuilt non-gc structures
+ SemiSpaceGC._dump_heap) # static in prebuilt gc objects
+ self._ll_typeid_map = lltype.nullptr(ARRAY_TYPEID_MAP)
+ return ll_typeid_map
Modified: pypy/branch/gc-dump-heap/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/gc-dump-heap/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/branch/gc-dump-heap/pypy/rpython/memory/gctransform/framework.py Sun Oct 25 21:00:07 2009
@@ -116,6 +116,7 @@
def __init__(self, translator):
from pypy.rpython.memory.gc.base import choose_gc_from_config
+ from pypy.rpython.memory.gc.base import ARRAY_TYPEID_MAP
super(FrameworkGCTransformer, self).__init__(translator, inline=True)
if hasattr(self, 'GC_PARAMS'):
# for tests: the GC choice can be specified as class attributes
@@ -271,10 +272,8 @@
annmodel.s_None)
if hasattr(GCClass, 'dump_heap'):
- self.dump_heap_ptr = getfn(
- GCClass.dump_heap.im_func,
- [s_gc, annmodel.SomeInteger()],
- annmodel.s_None)
+ self.dump_heap_ptr = getfn(GCClass.dump_heap.im_func,
+ [s_gc], annmodel.SomePtr(lltype.Ptr(ARRAY_TYPEID_MAP)))
# in some GCs we can inline the common case of
# malloc_fixedsize(typeid, size, True, False, False)
@@ -647,9 +646,8 @@
def gct_gc_dump_heap(self, hop):
op = hop.spaceop
- v_fd = op.args[0]
- hop.genop("direct_call", [self.dump_heap_ptr,
- self.c_const_gc, v_fd])
+ hop.genop("direct_call", [self.dump_heap_ptr, self.c_const_gc],
+ resultvar=op.result)
def gct_gc_adr_of_nursery_free(self, hop):
if getattr(self.gcdata.gc, 'nursery_free', None) is None:
Modified: pypy/branch/gc-dump-heap/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/branch/gc-dump-heap/pypy/rpython/memory/test/test_gc.py (original)
+++ pypy/branch/gc-dump-heap/pypy/rpython/memory/test/test_gc.py Sun Oct 25 21:00:07 2009
@@ -552,6 +552,27 @@
assert res == 111
+ def test_gc_dump_heap(self):
+ if getattr(self.GCClass, 'dump_heap', None) is None:
+ py.test.skip("unsupported gc")
+ S = lltype.GcStruct('S', ('x', lltype.Signed))
+
+ def fun(fd):
+ l = []
+ for i in range(10):
+ l.append(lltype.malloc(S))
+ rgc.dump_heap(fd)
+ keepalive_until_here(l)
+ return 0
+
+ from pypy.tool.udir import udir
+ f = udir.join("gcdump_direct.log")
+ handle = open(str(f), "w")
+ run = self.interpret(fun, [handle.fileno()])
+ handle.close()
+ assert f.read() == 'xxx'
+
+
from pypy.rlib.objectmodel import UnboxedValue
class TaggedBase(object):
Modified: pypy/branch/gc-dump-heap/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/branch/gc-dump-heap/pypy/rpython/memory/test/test_transformed_gc.py (original)
+++ pypy/branch/gc-dump-heap/pypy/rpython/memory/test/test_transformed_gc.py Sun Oct 25 21:00:07 2009
@@ -13,6 +13,7 @@
from pypy.rlib import rgc
from pypy import conftest
from pypy.rlib.rstring import StringBuilder
+from pypy.rlib.objectmodel import keepalive_until_here
INT_SIZE = struct.calcsize("i") # only for estimates
@@ -798,23 +799,34 @@
def define_gc_dump_heap(cls):
S = lltype.GcStruct('S', ('x', lltype.Signed))
+ l = []
- def f(fd, ign):
- l = []
+ def f():
for i in range(10):
l.append(lltype.malloc(S))
- rgc.dump_heap(fd)
- return 0
+ # We cheat here and only read the table which we later on
+ # process ourselves, otherwise this test takes ages
+ tb = rgc._dump_heap()
+ a = 0
+ nr = 0
+ b = 0
+ c = 0
+ for i in range(len(tb)):
+ if tb[i].count == 10:
+ a += 1
+ nr = i
+ for i in range(len(tb)):
+ if tb[i].count == 1:
+ b += 1
+ c = tb[i].links[nr]
+ rgc._clear_dump_heap(tb)
+ return c * 100 + b * 10 + a
return f
def test_gc_dump_heap(self):
- from pypy.tool.udir import udir
- f = udir.join("gcdump.log")
- handle = open(str(f), "w")
run = self.runner("gc_dump_heap")
- run([handle.fileno(), 0])
- handle.close()
- assert f.read() == 'xxx'
+ res = run([])
+ assert res == 1011
# ________________________________________________________________
More information about the Pypy-commit
mailing list