[pypy-svn] r77142 - in pypy/trunk/pypy: module/gc module/gc/test rlib rlib/test rpython rpython/memory rpython/memory/gc rpython/memory/gctransform translator/c/test
arigo at codespeak.net
arigo at codespeak.net
Fri Sep 17 15:15:52 CEST 2010
Author: arigo
Date: Fri Sep 17 15:15:50 2010
New Revision: 77142
Added:
pypy/trunk/pypy/module/gc/referents.py
- copied unchanged from r77139, pypy/branch/gc-module/pypy/module/gc/referents.py
pypy/trunk/pypy/module/gc/test/test_referents.py
- copied unchanged from r77139, pypy/branch/gc-module/pypy/module/gc/test/test_referents.py
pypy/trunk/pypy/rpython/memory/gc/inspect.py
- copied unchanged from r77139, pypy/branch/gc-module/pypy/rpython/memory/gc/inspect.py
Modified:
pypy/trunk/pypy/module/gc/__init__.py
pypy/trunk/pypy/module/gc/interp_gc.py
pypy/trunk/pypy/module/gc/test/test_gc.py
pypy/trunk/pypy/rlib/rgc.py
pypy/trunk/pypy/rlib/test/test_rgc.py
pypy/trunk/pypy/rpython/memory/gc/base.py
pypy/trunk/pypy/rpython/memory/gc/markcompact.py
pypy/trunk/pypy/rpython/memory/gctransform/framework.py
pypy/trunk/pypy/rpython/memory/gctypelayout.py
pypy/trunk/pypy/rpython/rptr.py
pypy/trunk/pypy/translator/c/test/test_newgc.py
Log:
Merge branch/gc-module. Adds some standard gc functions like
gc.get_referrers(), and some custom ones too.
Modified: pypy/trunk/pypy/module/gc/__init__.py
==============================================================================
--- pypy/trunk/pypy/module/gc/__init__.py (original)
+++ pypy/trunk/pypy/module/gc/__init__.py Fri Sep 17 15:15:50 2010
@@ -10,13 +10,22 @@
'collect': 'interp_gc.collect',
'enable_finalizers': 'interp_gc.enable_finalizers',
'disable_finalizers': 'interp_gc.disable_finalizers',
- 'estimate_heap_size': 'interp_gc.estimate_heap_size',
'garbage' : 'space.newlist([])',
#'dump_heap_stats': 'interp_gc.dump_heap_stats',
}
def __init__(self, space, w_name):
- ts = space.config.translation.type_system
- if ts == 'ootype':
- del self.interpleveldefs['dump_heap_stats']
+ if (not space.config.translating or
+ space.config.translation.gctransformer == "framework"):
+ self.interpleveldefs.update({
+ 'get_rpy_roots': 'referents.get_rpy_roots',
+ 'get_rpy_referents': 'referents.get_rpy_referents',
+ 'get_rpy_memory_usage': 'referents.get_rpy_memory_usage',
+ 'get_rpy_type_index': 'referents.get_rpy_type_index',
+ 'get_objects': 'referents.get_objects',
+ 'get_referents': 'referents.get_referents',
+ 'get_referrers': 'referents.get_referrers',
+ 'dump_rpy_heap': 'referents.dump_rpy_heap',
+ 'GcRef': 'referents.W_GcRef',
+ })
MixedModule.__init__(self, space, w_name)
Modified: pypy/trunk/pypy/module/gc/interp_gc.py
==============================================================================
--- pypy/trunk/pypy/module/gc/interp_gc.py (original)
+++ pypy/trunk/pypy/module/gc/interp_gc.py Fri Sep 17 15:15:50 2010
@@ -24,36 +24,6 @@
# ____________________________________________________________
-import sys
-platform = sys.platform
-
-def estimate_heap_size(space):
- # XXX should be done with the help of the GCs
- if platform == "linux2":
- import os
- pid = os.getpid()
- try:
- fd = os.open("/proc/" + str(pid) + "/status", os.O_RDONLY, 0777)
- except OSError:
- pass
- else:
- try:
- content = os.read(fd, 1000000)
- finally:
- os.close(fd)
- lines = content.split("\n")
- for line in lines:
- if line.startswith("VmSize:"):
- start = line.find(" ") # try to ignore tabs
- assert start > 0
- stop = len(line) - 3
- assert stop > 0
- result = int(line[start:stop].strip(" ")) * 1024
- return space.wrap(result)
- raise OperationError(space.w_RuntimeError,
- space.wrap("can't estimate the heap size"))
-estimate_heap_size.unwrap_spec = [ObjSpace]
-
def dump_heap_stats(space, filename):
tb = rgc._heap_stats()
if not tb:
Modified: pypy/trunk/pypy/module/gc/test/test_gc.py
==============================================================================
--- pypy/trunk/pypy/module/gc/test/test_gc.py (original)
+++ pypy/trunk/pypy/module/gc/test/test_gc.py Fri Sep 17 15:15:50 2010
@@ -59,13 +59,6 @@
raises(ValueError, gc.enable_finalizers)
runtest(True)
- def test_estimate_heap_size(self):
- import sys, gc
- if sys.platform == "linux2":
- assert gc.estimate_heap_size() > 1024
- else:
- raises(RuntimeError, gc.estimate_heap_size)
-
def test_enable(self):
import gc
assert gc.isenabled()
Modified: pypy/trunk/pypy/rlib/rgc.py
==============================================================================
--- pypy/trunk/pypy/rlib/rgc.py (original)
+++ pypy/trunk/pypy/rlib/rgc.py Fri Sep 17 15:15:50 2010
@@ -1,6 +1,7 @@
-import gc
+import gc, types
from pypy.rpython.extregistry import ExtRegistryEntry
from pypy.rlib.objectmodel import we_are_translated
+from pypy.rpython.lltypesystem import lltype, llmemory
# ____________________________________________________________
# General GC features
@@ -93,7 +94,7 @@
def specialize_call(self, hop):
from pypy.rpython.error import TyperError
- from pypy.rpython.lltypesystem import lltype, llmemory, rtuple
+ from pypy.rpython.lltypesystem import rtuple
from pypy.annotation import model as annmodel
from pypy.rpython.memory.gc.marksweep import X_CLONE, X_CLONE_PTR
@@ -150,7 +151,6 @@
return annmodel.s_None
def specialize_call(self, hop):
- from pypy.rpython.lltypesystem import lltype
hop.exception_cannot_occur()
args_v = []
if len(hop.args_s) == 1:
@@ -165,7 +165,6 @@
return annmodel.s_None
def specialize_call(self, hop):
- from pypy.rpython.lltypesystem import lltype
[v_nbytes] = hop.inputargs(lltype.Signed)
hop.exception_cannot_occur()
return hop.genop('gc_set_max_heap_size', [v_nbytes],
@@ -182,7 +181,6 @@
return annmodel.SomeBool()
def specialize_call(self, hop):
- from pypy.rpython.lltypesystem import lltype
hop.exception_cannot_occur()
return hop.genop('gc_can_move', hop.args_v, resulttype=hop.r_result)
@@ -195,11 +193,9 @@
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
hop.exception_is_here()
return hop.genop('gc_heap_stats', [], resulttype=hop.r_result)
@@ -209,7 +205,6 @@
When running directly, will pretend that gc is always
moving (might be configurable in a future)
"""
- from pypy.rpython.lltypesystem import lltype
return lltype.nullptr(TP)
class MallocNonMovingEntry(ExtRegistryEntry):
@@ -221,7 +216,6 @@
return malloc(s_TP, s_n, s_zero=s_zero)
def specialize_call(self, hop, i_zero=None):
- from pypy.rpython.lltypesystem import lltype
# XXX assume flavor and zero to be None by now
assert hop.args_s[0].is_constant()
vlist = [hop.inputarg(lltype.Void, arg=0)]
@@ -243,7 +237,6 @@
def ll_arraycopy(source, dest, source_start, dest_start, length):
from pypy.rpython.lltypesystem.lloperation import llop
- from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rlib.objectmodel import keepalive_until_here
# supports non-overlapping copies only
@@ -279,7 +272,6 @@
def ll_shrink_array(p, smallerlength):
from pypy.rpython.lltypesystem.lloperation import llop
- from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rlib.objectmodel import keepalive_until_here
if llop.shrink_array(lltype.Bool, p, smallerlength):
@@ -313,3 +305,221 @@
func._dont_inline_ = True
func._gc_no_collect_ = True
return func
+
+# ____________________________________________________________
+
+def get_rpy_roots():
+ "NOT_RPYTHON"
+ # Return the 'roots' from the GC.
+ # This stub is not usable on top of CPython.
+ # The gc typically returns a list that ends with a few NULL_GCREFs.
+ raise NotImplementedError
+
+def get_rpy_referents(gcref):
+ "NOT_RPYTHON"
+ x = gcref._x
+ if isinstance(x, list):
+ d = x
+ elif isinstance(x, dict):
+ d = x.keys() + x.values()
+ else:
+ d = []
+ if hasattr(x, '__dict__'):
+ d = x.__dict__.values()
+ if hasattr(type(x), '__slots__'):
+ for slot in type(x).__slots__:
+ try:
+ d.append(getattr(x, slot))
+ except AttributeError:
+ pass
+ # discard objects that are too random or that are _freeze_=True
+ return [_GcRef(x) for x in d if _keep_object(x)]
+
+def _keep_object(x):
+ if isinstance(x, type) or type(x) is types.ClassType:
+ return False # don't keep any type
+ if isinstance(x, (list, dict, str)):
+ return True # keep lists and dicts and strings
+ try:
+ return not x._freeze_() # don't keep any frozen object
+ except AttributeError:
+ return type(x).__module__ != '__builtin__' # keep non-builtins
+ except Exception:
+ return False # don't keep objects whose _freeze_() method explodes
+
+def get_rpy_memory_usage(gcref):
+ "NOT_RPYTHON"
+ # approximate implementation using CPython's type info
+ Class = type(gcref._x)
+ size = Class.__basicsize__
+ if Class.__itemsize__ > 0:
+ size += Class.__itemsize__ * len(gcref._x)
+ return size
+
+def get_rpy_type_index(gcref):
+ "NOT_RPYTHON"
+ from pypy.rlib.rarithmetic import intmask
+ Class = gcref._x.__class__
+ return intmask(id(Class))
+
+def cast_gcref_to_int(gcref):
+ if we_are_translated():
+ return lltype.cast_ptr_to_int(gcref)
+ else:
+ return id(gcref._x)
+
+def dump_rpy_heap(fd):
+ "NOT_RPYTHON"
+ raise NotImplementedError
+
+NULL_GCREF = lltype.nullptr(llmemory.GCREF.TO)
+
+class _GcRef(object):
+ # implementation-specific: there should not be any after translation
+ __slots__ = ['_x']
+ def __init__(self, x):
+ self._x = x
+ def __hash__(self):
+ return object.__hash__(self._x)
+ def __eq__(self, other):
+ if isinstance(other, lltype._ptr):
+ assert other == NULL_GCREF, (
+ "comparing a _GcRef with a non-NULL lltype ptr")
+ return False
+ assert isinstance(other, _GcRef)
+ return self._x is other._x
+ def __ne__(self, other):
+ return not self.__eq__(other)
+ def __repr__(self):
+ return "_GcRef(%r)" % (self._x, )
+ def _freeze_(self):
+ raise Exception("instances of rlib.rgc._GcRef cannot be translated")
+
+def cast_instance_to_gcref(x):
+ # Before translation, casts an RPython instance into a _GcRef.
+ # After translation, it is a variant of cast_object_to_ptr(GCREF).
+ if we_are_translated():
+ from pypy.rpython import annlowlevel
+ x = annlowlevel.cast_instance_to_base_ptr(x)
+ return lltype.cast_opaque_ptr(llmemory.GCREF, x)
+ else:
+ return _GcRef(x)
+cast_instance_to_gcref._annspecialcase_ = 'specialize:argtype(0)'
+
+def try_cast_gcref_to_instance(Class, gcref):
+ # Before translation, unwraps the RPython instance contained in a _GcRef.
+ # After translation, it is a type-check performed by the GC.
+ if we_are_translated():
+ from pypy.rpython.annlowlevel import base_ptr_lltype
+ from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
+ from pypy.rpython.lltypesystem import rclass
+ if _is_rpy_instance(gcref):
+ objptr = lltype.cast_opaque_ptr(base_ptr_lltype(), gcref)
+ if objptr.typeptr: # may be NULL, e.g. in rdict's dummykeyobj
+ clsptr = _get_llcls_from_cls(Class)
+ if rclass.ll_isinstance(objptr, clsptr):
+ return cast_base_ptr_to_instance(Class, objptr)
+ return None
+ else:
+ if isinstance(gcref._x, Class):
+ return gcref._x
+ return None
+try_cast_gcref_to_instance._annspecialcase_ = 'specialize:arg(0)'
+
+# ------------------- implementation -------------------
+
+_cache_s_list_of_gcrefs = None
+
+def s_list_of_gcrefs():
+ global _cache_s_list_of_gcrefs
+ if _cache_s_list_of_gcrefs is None:
+ from pypy.annotation import model as annmodel
+ from pypy.annotation.listdef import ListDef
+ s_gcref = annmodel.SomePtr(llmemory.GCREF)
+ _cache_s_list_of_gcrefs = annmodel.SomeList(
+ ListDef(None, s_gcref, mutated=True, resized=False))
+ return _cache_s_list_of_gcrefs
+
+class Entry(ExtRegistryEntry):
+ _about_ = get_rpy_roots
+ def compute_result_annotation(self):
+ return s_list_of_gcrefs()
+ def specialize_call(self, hop):
+ return hop.genop('gc_get_rpy_roots', [], resulttype = hop.r_result)
+
+class Entry(ExtRegistryEntry):
+ _about_ = get_rpy_referents
+ def compute_result_annotation(self, s_gcref):
+ from pypy.annotation import model as annmodel
+ assert annmodel.SomePtr(llmemory.GCREF).contains(s_gcref)
+ return s_list_of_gcrefs()
+ def specialize_call(self, hop):
+ vlist = hop.inputargs(hop.args_r[0])
+ return hop.genop('gc_get_rpy_referents', vlist,
+ resulttype = hop.r_result)
+
+class Entry(ExtRegistryEntry):
+ _about_ = get_rpy_memory_usage
+ def compute_result_annotation(self, s_gcref):
+ from pypy.annotation import model as annmodel
+ return annmodel.SomeInteger()
+ def specialize_call(self, hop):
+ vlist = hop.inputargs(hop.args_r[0])
+ return hop.genop('gc_get_rpy_memory_usage', vlist,
+ resulttype = hop.r_result)
+
+class Entry(ExtRegistryEntry):
+ _about_ = get_rpy_type_index
+ def compute_result_annotation(self, s_gcref):
+ from pypy.annotation import model as annmodel
+ return annmodel.SomeInteger()
+ def specialize_call(self, hop):
+ vlist = hop.inputargs(hop.args_r[0])
+ return hop.genop('gc_get_rpy_type_index', vlist,
+ resulttype = hop.r_result)
+
+def _is_rpy_instance(gcref):
+ "NOT_RPYTHON"
+ raise NotImplementedError
+
+def _get_llcls_from_cls(Class):
+ "NOT_RPYTHON"
+ raise NotImplementedError
+
+class Entry(ExtRegistryEntry):
+ _about_ = _is_rpy_instance
+ def compute_result_annotation(self, s_gcref):
+ from pypy.annotation import model as annmodel
+ return annmodel.SomeBool()
+ def specialize_call(self, hop):
+ vlist = hop.inputargs(hop.args_r[0])
+ return hop.genop('gc_is_rpy_instance', vlist,
+ resulttype = hop.r_result)
+
+class Entry(ExtRegistryEntry):
+ _about_ = _get_llcls_from_cls
+ def compute_result_annotation(self, s_Class):
+ from pypy.annotation import model as annmodel
+ from pypy.rpython.lltypesystem import rclass
+ assert s_Class.is_constant()
+ return annmodel.SomePtr(rclass.CLASSTYPE)
+ def specialize_call(self, hop):
+ from pypy.rpython.rclass import getclassrepr
+ from pypy.objspace.flow.model import Constant
+ from pypy.rpython.lltypesystem import rclass
+ Class = hop.args_s[0].const
+ classdef = hop.rtyper.annotator.bookkeeper.getuniqueclassdef(Class)
+ classrepr = getclassrepr(hop.rtyper, classdef)
+ vtable = classrepr.getvtable()
+ assert lltype.typeOf(vtable) == rclass.CLASSTYPE
+ return Constant(vtable, concretetype=rclass.CLASSTYPE)
+
+class Entry(ExtRegistryEntry):
+ _about_ = dump_rpy_heap
+ def compute_result_annotation(self, s_fd):
+ from pypy.annotation.model import s_None
+ return s_None
+ def specialize_call(self, hop):
+ vlist = hop.inputargs(lltype.Signed)
+ hop.exception_is_here()
+ return hop.genop('gc_dump_rpy_heap', vlist, resulttype = hop.r_result)
Modified: pypy/trunk/pypy/rlib/test/test_rgc.py
==============================================================================
--- pypy/trunk/pypy/rlib/test/test_rgc.py (original)
+++ pypy/trunk/pypy/rlib/test/test_rgc.py Fri Sep 17 15:15:50 2010
@@ -153,3 +153,29 @@
assert len(s2.vars) == 3
for i in range(3):
assert s2.vars[i] == 50 + i
+
+
+def test_get_objects():
+ class X(object):
+ pass
+ x1 = X()
+ lst = rgc._get_objects()
+ assert rgc.cast_instance_to_gcref(x1) in lst
+
+def test_get_referents():
+ class X(object):
+ __slots__ = ['stuff']
+ x1 = X()
+ x1.stuff = X()
+ x2 = X()
+ lst = rgc._get_referents(rgc.cast_instance_to_gcref(x1))
+ lst2 = [rgc.try_cast_gcref_to_instance(X, x) for x in lst]
+ assert x1.stuff in lst2
+ assert x2 not in lst2
+
+def test_get_memory_usage():
+ class X(object):
+ pass
+ x1 = X()
+ n = rgc._get_memory_usage(rgc.cast_instance_to_gcref(x1))
+ assert n >= 8 and n <= 64
Modified: pypy/trunk/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gc/base.py (original)
+++ pypy/trunk/pypy/rpython/memory/gc/base.py Fri Sep 17 15:15:50 2010
@@ -53,7 +53,8 @@
varsize_offset_to_length,
varsize_offsets_to_gcpointers_in_var_part,
weakpointer_offset,
- member_index):
+ member_index,
+ is_rpython_class):
self.getfinalizer = getfinalizer
self.is_varsize = is_varsize
self.has_gcptr_in_varsize = has_gcptr_in_varsize
@@ -66,6 +67,7 @@
self.varsize_offsets_to_gcpointers_in_var_part = varsize_offsets_to_gcpointers_in_var_part
self.weakpointer_offset = weakpointer_offset
self.member_index = member_index
+ self.is_rpython_class = is_rpython_class
def get_member_index(self, type_id):
return self.member_index(type_id)
@@ -101,6 +103,9 @@
def get_size(self, obj):
return self._get_size_for_typeid(obj, self.get_type_id(obj))
+ def get_size_incl_hash(self, obj):
+ return self.get_size(obj)
+
def malloc(self, typeid, length=0, zero=False):
"""For testing. The interface used by the gctransformer is
the four malloc_[fixed,var]size[_clear]() functions.
Modified: pypy/trunk/pypy/rpython/memory/gc/markcompact.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gc/markcompact.py (original)
+++ pypy/trunk/pypy/rpython/memory/gc/markcompact.py Fri Sep 17 15:15:50 2010
@@ -674,6 +674,13 @@
return llmemory.cast_adr_to_int(obj) # not in an arena...
return adr - self.space
+ def get_size_incl_hash(self, obj):
+ size = self.get_size(obj)
+ hdr = self.header(obj)
+ if hdr.tid & GCFLAG_HASHFIELD:
+ size += llmemory.sizeof(lltype.Signed)
+ return size
+
# ____________________________________________________________
class CannotAllocateGCArena(Exception):
Modified: pypy/trunk/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/trunk/pypy/rpython/memory/gctransform/framework.py Fri Sep 17 15:15:50 2010
@@ -7,7 +7,7 @@
from pypy.rpython.memory.gc import marksweep
from pypy.rpython.memory.gcheader import GCHeaderBuilder
from pypy.rlib.rarithmetic import ovfcheck
-from pypy.rlib import rstack
+from pypy.rlib import rstack, rgc
from pypy.rlib.debug import ll_assert
from pypy.translator.backendopt import graphanalyze
from pypy.translator.backendopt.support import var_needsgc
@@ -139,6 +139,8 @@
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
+ from pypy.rpython.memory.gc import inspect
+
super(FrameworkGCTransformer, self).__init__(translator, inline=True)
if hasattr(self, 'GC_PARAMS'):
# for tests: the GC choice can be specified as class attributes
@@ -388,6 +390,31 @@
else:
self.id_ptr = None
+ self.get_rpy_roots_ptr = getfn(inspect.get_rpy_roots,
+ [s_gc],
+ rgc.s_list_of_gcrefs(),
+ minimal_transform=False)
+ self.get_rpy_referents_ptr = getfn(inspect.get_rpy_referents,
+ [s_gc, s_gcref],
+ rgc.s_list_of_gcrefs(),
+ minimal_transform=False)
+ self.get_rpy_memory_usage_ptr = getfn(inspect.get_rpy_memory_usage,
+ [s_gc, s_gcref],
+ annmodel.SomeInteger(),
+ minimal_transform=False)
+ self.get_rpy_type_index_ptr = getfn(inspect.get_rpy_type_index,
+ [s_gc, s_gcref],
+ annmodel.SomeInteger(),
+ minimal_transform=False)
+ self.is_rpy_instance_ptr = getfn(inspect.is_rpy_instance,
+ [s_gc, s_gcref],
+ annmodel.SomeBool(),
+ minimal_transform=False)
+ self.dump_rpy_heap_ptr = getfn(inspect.dump_rpy_heap,
+ [s_gc, annmodel.SomeInteger()],
+ annmodel.s_None,
+ minimal_transform=False)
+
self.set_max_heap_size_ptr = getfn(GCClass.set_max_heap_size.im_func,
[s_gc,
annmodel.SomeInteger(nonneg=True)],
@@ -883,6 +910,53 @@
def gct_gc_get_type_info_group(self, hop):
return hop.cast_result(self.c_type_info_group)
+ def gct_gc_get_rpy_roots(self, hop):
+ livevars = self.push_roots(hop)
+ hop.genop("direct_call",
+ [self.get_rpy_roots_ptr, self.c_const_gc],
+ resultvar=hop.spaceop.result)
+ self.pop_roots(hop, livevars)
+
+ def gct_gc_get_rpy_referents(self, hop):
+ livevars = self.push_roots(hop)
+ [v_ptr] = hop.spaceop.args
+ hop.genop("direct_call",
+ [self.get_rpy_referents_ptr, self.c_const_gc, v_ptr],
+ resultvar=hop.spaceop.result)
+ self.pop_roots(hop, livevars)
+
+ def gct_gc_get_rpy_memory_usage(self, hop):
+ livevars = self.push_roots(hop)
+ [v_ptr] = hop.spaceop.args
+ hop.genop("direct_call",
+ [self.get_rpy_memory_usage_ptr, self.c_const_gc, v_ptr],
+ resultvar=hop.spaceop.result)
+ self.pop_roots(hop, livevars)
+
+ def gct_gc_get_rpy_type_index(self, hop):
+ livevars = self.push_roots(hop)
+ [v_ptr] = hop.spaceop.args
+ hop.genop("direct_call",
+ [self.get_rpy_type_index_ptr, self.c_const_gc, v_ptr],
+ resultvar=hop.spaceop.result)
+ self.pop_roots(hop, livevars)
+
+ def gct_gc_is_rpy_instance(self, hop):
+ livevars = self.push_roots(hop)
+ [v_ptr] = hop.spaceop.args
+ hop.genop("direct_call",
+ [self.is_rpy_instance_ptr, self.c_const_gc, v_ptr],
+ resultvar=hop.spaceop.result)
+ self.pop_roots(hop, livevars)
+
+ def gct_gc_dump_rpy_heap(self, hop):
+ livevars = self.push_roots(hop)
+ [v_fd] = hop.spaceop.args
+ hop.genop("direct_call",
+ [self.dump_rpy_heap_ptr, self.c_const_gc, v_fd],
+ resultvar=hop.spaceop.result)
+ self.pop_roots(hop, livevars)
+
def gct_malloc_nonmovable_varsize(self, hop):
TYPE = hop.spaceop.result.concretetype
if self.gcdata.gc.can_malloc_nonmovable():
Modified: pypy/trunk/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gctypelayout.py (original)
+++ pypy/trunk/pypy/rpython/memory/gctypelayout.py Fri Sep 17 15:15:50 2010
@@ -101,6 +101,10 @@
infobits = self.get(typeid).infobits
return infobits & T_MEMBER_INDEX
+ def q_is_rpython_class(self, typeid):
+ infobits = self.get(typeid).infobits
+ return infobits & T_IS_RPYTHON_INSTANCE != 0
+
def set_query_functions(self, gc):
gc.set_query_functions(
self.q_is_varsize,
@@ -114,7 +118,8 @@
self.q_varsize_offset_to_length,
self.q_varsize_offsets_to_gcpointers_in_var_part,
self.q_weakpointer_offset,
- self.q_member_index)
+ self.q_member_index,
+ self.q_is_rpython_class)
# the lowest 16bits are used to store group member index
@@ -123,6 +128,7 @@
T_HAS_GCPTR_IN_VARSIZE = 0x20000
T_IS_GCARRAY_OF_GCPTR = 0x40000
T_IS_WEAKREF = 0x80000
+T_IS_RPYTHON_INSTANCE = 0x100000 # the type is a subclass of OBJECT
T_KEY_MASK = intmask(0xFF000000)
T_KEY_VALUE = intmask(0x7A000000) # bug detection only
@@ -181,6 +187,8 @@
varinfo.varitemsize = llmemory.sizeof(ARRAY.OF)
if builder.is_weakref_type(TYPE):
infobits |= T_IS_WEAKREF
+ if is_subclass_of_object(TYPE):
+ infobits |= T_IS_RPYTHON_INSTANCE
info.infobits = infobits | T_KEY_VALUE
# ____________________________________________________________
@@ -259,9 +267,7 @@
else:
# no vtable from lltype2vtable -- double-check to be sure
# that it's not a subclass of OBJECT.
- while isinstance(TYPE, lltype.GcStruct):
- assert TYPE is not rclass.OBJECT
- _, TYPE = TYPE._first_struct()
+ assert not is_subclass_of_object(TYPE)
def get_info(self, type_id):
res = llop.get_group_member(GCData.TYPE_INFO_PTR,
@@ -437,6 +443,13 @@
for i in range(p._obj.getlength()):
zero_gc_pointers_inside(p[i], ITEM)
+def is_subclass_of_object(TYPE):
+ while isinstance(TYPE, lltype.GcStruct):
+ if TYPE is rclass.OBJECT:
+ return True
+ _, TYPE = TYPE._first_struct()
+ return False
+
########## weakrefs ##########
# framework: weakref objects are small structures containing only an address
Modified: pypy/trunk/pypy/rpython/rptr.py
==============================================================================
--- pypy/trunk/pypy/rpython/rptr.py (original)
+++ pypy/trunk/pypy/rpython/rptr.py Fri Sep 17 15:15:50 2010
@@ -35,6 +35,9 @@
id = lltype.cast_ptr_to_int(p)
return ll_str.ll_int2hex(r_uint(id), True)
+ def get_ll_eq_function(self):
+ return None
+
def rtype_getattr(self, hop):
attr = hop.args_s[1].const
if isinstance(hop.s_result, annmodel.SomeLLADTMeth):
Modified: pypy/trunk/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/trunk/pypy/translator/c/test/test_newgc.py (original)
+++ pypy/trunk/pypy/translator/c/test/test_newgc.py Fri Sep 17 15:15:50 2010
@@ -2,7 +2,7 @@
import sys, os, inspect
from pypy.objspace.flow.model import summary
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rpython.memory.test import snippet
from pypy.rlib import rgc
@@ -23,6 +23,7 @@
GC_CAN_SHRINK_ARRAY = False
_isolated_func = None
+ c_allfuncs = None
@classmethod
def _makefunc_str_int(cls, f):
@@ -891,6 +892,202 @@
def test_arraycopy_writebarrier_ptr(self):
self.run("arraycopy_writebarrier_ptr")
+ def define_get_rpy_roots(self):
+ U = lltype.GcStruct('U', ('x', lltype.Signed))
+ S = lltype.GcStruct('S', ('u', lltype.Ptr(U)))
+
+ def g(s):
+ lst = rgc.get_rpy_roots()
+ found = False
+ for x in lst:
+ if x == lltype.cast_opaque_ptr(llmemory.GCREF, s):
+ found = True
+ if x == lltype.cast_opaque_ptr(llmemory.GCREF, s.u):
+ os.write(2, "s.u should not be found!\n")
+ assert False
+ return found == 1
+
+ def fn():
+ s = lltype.malloc(S)
+ s.u = lltype.malloc(U)
+ found = g(s)
+ if not found:
+ os.write(2, "not found!\n")
+ assert False
+ s.u.x = 42
+ return 0
+
+ return fn
+
+ def test_get_rpy_roots(self):
+ self.run("get_rpy_roots")
+
+ def define_get_rpy_referents(self):
+ U = lltype.GcStruct('U', ('x', lltype.Signed))
+ S = lltype.GcStruct('S', ('u', lltype.Ptr(U)))
+
+ def fn():
+ s = lltype.malloc(S)
+ s.u = lltype.malloc(U)
+ gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+ gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, s.u)
+ lst = rgc.get_rpy_referents(gcref1)
+ assert gcref2 in lst
+ assert gcref1 not in lst
+ s.u.x = 42
+ return 0
+
+ return fn
+
+ def test_get_rpy_referents(self):
+ self.run("get_rpy_referents")
+
+ def define_is_rpy_instance(self):
+ class Foo:
+ pass
+ S = lltype.GcStruct('S', ('x', lltype.Signed))
+
+ def check(gcref, expected):
+ result = rgc._is_rpy_instance(gcref)
+ assert result == expected
+
+ def fn():
+ s = lltype.malloc(S)
+ gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+ check(gcref1, False)
+
+ f = Foo()
+ gcref3 = rgc.cast_instance_to_gcref(f)
+ check(gcref3, True)
+
+ return 0
+
+ return fn
+
+ def test_is_rpy_instance(self):
+ self.run("is_rpy_instance")
+
+ def define_try_cast_gcref_to_instance(self):
+ class Foo:
+ pass
+ class FooBar(Foo):
+ pass
+ class Biz(object):
+ pass
+ S = lltype.GcStruct('S', ('x', lltype.Signed))
+
+ def fn():
+ foo = Foo()
+ gcref1 = rgc.cast_instance_to_gcref(foo)
+ assert rgc.try_cast_gcref_to_instance(Foo, gcref1) is foo
+ assert rgc.try_cast_gcref_to_instance(FooBar, gcref1) is None
+ assert rgc.try_cast_gcref_to_instance(Biz, gcref1) is None
+
+ foobar = FooBar()
+ gcref2 = rgc.cast_instance_to_gcref(foobar)
+ assert rgc.try_cast_gcref_to_instance(Foo, gcref2) is foobar
+ assert rgc.try_cast_gcref_to_instance(FooBar, gcref2) is foobar
+ assert rgc.try_cast_gcref_to_instance(Biz, gcref2) is None
+
+ s = lltype.malloc(S)
+ gcref3 = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+ assert rgc.try_cast_gcref_to_instance(Foo, gcref3) is None
+ assert rgc.try_cast_gcref_to_instance(FooBar, gcref3) is None
+ assert rgc.try_cast_gcref_to_instance(Biz, gcref3) is None
+
+ return 0
+
+ return fn
+
+ def test_try_cast_gcref_to_instance(self):
+ self.run("try_cast_gcref_to_instance")
+
+ def define_get_rpy_memory_usage(self):
+ U = lltype.GcStruct('U', ('x1', lltype.Signed),
+ ('x2', lltype.Signed),
+ ('x3', lltype.Signed),
+ ('x4', lltype.Signed),
+ ('x5', lltype.Signed),
+ ('x6', lltype.Signed),
+ ('x7', lltype.Signed),
+ ('x8', lltype.Signed))
+ S = lltype.GcStruct('S', ('u', lltype.Ptr(U)))
+ A = lltype.GcArray(lltype.Ptr(S))
+
+ def fn():
+ s = lltype.malloc(S)
+ s.u = lltype.malloc(U)
+ a = lltype.malloc(A, 1000)
+ gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+ int1 = rgc.get_rpy_memory_usage(gcref1)
+ assert 8 <= int1 <= 32
+ gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, s.u)
+ int2 = rgc.get_rpy_memory_usage(gcref2)
+ assert 4*9 <= int2 <= 8*12
+ gcref3 = lltype.cast_opaque_ptr(llmemory.GCREF, a)
+ int3 = rgc.get_rpy_memory_usage(gcref3)
+ assert 4*1001 <= int3 <= 8*1010
+ return 0
+
+ return fn
+
+ def test_get_rpy_memory_usage(self):
+ self.run("get_rpy_memory_usage")
+
+ def define_get_rpy_type_index(self):
+ U = lltype.GcStruct('U', ('x', lltype.Signed))
+ S = lltype.GcStruct('S', ('u', lltype.Ptr(U)))
+ A = lltype.GcArray(lltype.Ptr(S))
+
+ def fn():
+ s = lltype.malloc(S)
+ s.u = lltype.malloc(U)
+ a = lltype.malloc(A, 1000)
+ s2 = lltype.malloc(S)
+ gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+ int1 = rgc.get_rpy_type_index(gcref1)
+ gcref2 = lltype.cast_opaque_ptr(llmemory.GCREF, s.u)
+ int2 = rgc.get_rpy_type_index(gcref2)
+ gcref3 = lltype.cast_opaque_ptr(llmemory.GCREF, a)
+ int3 = rgc.get_rpy_type_index(gcref3)
+ gcref4 = lltype.cast_opaque_ptr(llmemory.GCREF, s2)
+ int4 = rgc.get_rpy_type_index(gcref4)
+ assert int1 != int2
+ assert int1 != int3
+ assert int2 != int3
+ assert int1 == int4
+ return 0
+
+ return fn
+
+ def test_get_rpy_type_index(self):
+ self.run("get_rpy_type_index")
+
+ filename_dump = str(udir.join('test_dump_rpy_heap'))
+ def define_dump_rpy_heap(self):
+ U = lltype.GcStruct('U', ('x', lltype.Signed))
+ S = lltype.GcStruct('S', ('u', lltype.Ptr(U)))
+ A = lltype.GcArray(lltype.Ptr(S))
+ filename = self.filename_dump
+
+ def fn():
+ s = lltype.malloc(S)
+ s.u = lltype.malloc(U)
+ a = lltype.malloc(A, 1000)
+ s2 = lltype.malloc(S)
+ #
+ fd = os.open(filename, os.O_WRONLY | os.O_CREAT, 0666)
+ rgc.dump_rpy_heap(fd)
+ os.close(fd)
+ return 0
+
+ return fn
+
+ def test_dump_rpy_heap(self):
+ self.run("dump_rpy_heap")
+ assert os.path.exists(self.filename_dump)
+ assert os.path.getsize(self.filename_dump) > 0 # minimal test
+
class TestSemiSpaceGC(TestUsingFramework, snippet.SemiSpaceGCTestDefines):
gcpolicy = "semispace"
More information about the Pypy-commit
mailing list