[pypy-svn] r76902 - in pypy/branch/gc-module/pypy: annotation module/gc module/gc/test rlib rpython rpython/memory/gc rpython/memory/gctransform translator/c/test
arigo at codespeak.net
arigo at codespeak.net
Mon Sep 6 19:06:54 CEST 2010
Author: arigo
Date: Mon Sep 6 19:06:52 2010
New Revision: 76902
Modified:
pypy/branch/gc-module/pypy/annotation/binaryop.py
pypy/branch/gc-module/pypy/module/gc/__init__.py
pypy/branch/gc-module/pypy/module/gc/referents.py
pypy/branch/gc-module/pypy/module/gc/test/test_referents.py
pypy/branch/gc-module/pypy/rlib/rgc.py
pypy/branch/gc-module/pypy/rpython/memory/gc/base.py
pypy/branch/gc-module/pypy/rpython/memory/gctransform/framework.py
pypy/branch/gc-module/pypy/rpython/rptr.py
pypy/branch/gc-module/pypy/translator/c/test/test_newgc.py
Log:
Implement get_rpy_roots() and get_rpy_referents() in the GC.
Modified: pypy/branch/gc-module/pypy/annotation/binaryop.py
==============================================================================
--- pypy/branch/gc-module/pypy/annotation/binaryop.py (original)
+++ pypy/branch/gc-module/pypy/annotation/binaryop.py Mon Sep 6 19:06:52 2010
@@ -594,7 +594,9 @@
getitem_idx_key = getitem_idx
def setitem((lst1, int2), s_value):
- getbookkeeper().count("list_setitem", int2)
+ if lst1.listdef.listitem.s_value.contains(s_value):
+ return # already up-to-date
+ getbookkeeper().count("list_setitem", int2)
lst1.listdef.mutate()
lst1.listdef.generalize(s_value)
setitem.can_only_throw = [IndexError]
Modified: pypy/branch/gc-module/pypy/module/gc/__init__.py
==============================================================================
--- pypy/branch/gc-module/pypy/module/gc/__init__.py (original)
+++ pypy/branch/gc-module/pypy/module/gc/__init__.py Mon Sep 6 19:06:52 2010
@@ -18,6 +18,7 @@
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_objects': 'referents.get_objects',
Modified: pypy/branch/gc-module/pypy/module/gc/referents.py
==============================================================================
--- pypy/branch/gc-module/pypy/module/gc/referents.py (original)
+++ pypy/branch/gc-module/pypy/module/gc/referents.py Mon Sep 6 19:06:52 2010
@@ -32,6 +32,10 @@
gcref = rgc.cast_instance_to_gcref(w_obj)
return gcref
+def get_rpy_roots(space):
+ lst = rgc.get_rpy_roots()
+ return space.newlist([wrap(space, gcref) for gcref in lst if gcref])
+
def get_rpy_referents(space, w_obj):
"""Return a list of all the referents, as reported by the GC.
This is likely to contain a lot of GcRefs."""
@@ -74,11 +78,12 @@
# be W_Roots
pending_w = [] # <- list of W_Roots
for gcref in roots:
- w_obj = try_cast_gcref_to_w_root(gcref)
- if w_obj is not None:
- pending_w.append(w_obj)
- else:
- _list_w_obj_referents(gcref, pending_w)
+ if gcref:
+ w_obj = try_cast_gcref_to_w_root(gcref)
+ if w_obj is not None:
+ pending_w.append(w_obj)
+ else:
+ _list_w_obj_referents(gcref, pending_w)
# continue by following every W_Root. Note that this will force a hash
# on every W_Root, which is kind of bad, but not on every RPython object,
# which is really good.
Modified: pypy/branch/gc-module/pypy/module/gc/test/test_referents.py
==============================================================================
--- pypy/branch/gc-module/pypy/module/gc/test/test_referents.py (original)
+++ pypy/branch/gc-module/pypy/module/gc/test/test_referents.py Mon Sep 6 19:06:52 2010
@@ -6,9 +6,12 @@
from pypy.rlib import rgc
cls._backup = [rgc.get_rpy_roots]
w = cls.space.wrap
- cls.ALL_ROOTS = [w(4), w([2, 7])]
+ class RandomRPythonObject(object):
+ pass
+ cls.ALL_ROOTS = [w(4), w([2, 7]), RandomRPythonObject()]
cls.w_ALL_ROOTS = cls.space.newlist(cls.ALL_ROOTS)
- rgc.get_rpy_roots = lambda: map(rgc._GcRef, cls.ALL_ROOTS)
+ rgc.get_rpy_roots = lambda: (
+ map(rgc._GcRef, cls.ALL_ROOTS) + [rgc.NULL_GCREF]*17)
def teardown_class(cls):
from pypy.rlib import rgc
@@ -25,6 +28,14 @@
if type(x) is gc.GcRef:
assert 0, "get_objects() returned a GcRef"
+ def test_get_rpy_roots(self):
+ import gc
+ lst = gc.get_rpy_roots()
+ assert lst[0] == 4
+ assert lst[1] == [2, 7]
+ assert type(lst[2]) is gc.GcRef
+ assert len(lst) == 3
+
def test_get_rpy_referents(self):
import gc
y = 12345
Modified: pypy/branch/gc-module/pypy/rlib/rgc.py
==============================================================================
--- pypy/branch/gc-module/pypy/rlib/rgc.py (original)
+++ pypy/branch/gc-module/pypy/rlib/rgc.py Mon Sep 6 19:06:52 2010
@@ -311,6 +311,7 @@
def get_rpy_roots():
# 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):
@@ -395,11 +396,17 @@
# ------------------- implementation -------------------
+_cache_s_list_of_gcrefs = None
+
def s_list_of_gcrefs():
- from pypy.annotation import model as annmodel
- from pypy.annotation.listdef import ListDef
- s_gcref = annmodel.SomePtr(llmemory.GCREF)
- return annmodel.SomeList(ListDef(None, s_gcref, resized=False))
+ 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, resized=False))
+ return _cache_s_list_of_gcrefs
class Entry(ExtRegistryEntry):
_about_ = get_rpy_roots
@@ -407,3 +414,14 @@
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)
Modified: pypy/branch/gc-module/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/gc-module/pypy/rpython/memory/gc/base.py (original)
+++ pypy/branch/gc-module/pypy/rpython/memory/gc/base.py Mon Sep 6 19:06:52 2010
@@ -255,6 +255,84 @@
finally:
self.finalizer_lock_count -= 1
+ # ---------- implementation of pypy.rlib.rgc.get_rpy_roots() ----------
+
+ def _counting_rpy_root(self, root):
+ self._count_rpy += 1
+
+ def _do_count_rpy_roots(self):
+ self._count_rpy = 0
+ self.root_walker.walk_roots(
+ GCBase._counting_rpy_root,
+ GCBase._counting_rpy_root,
+ GCBase._counting_rpy_root)
+ return self._count_rpy
+
+ def _append_rpy_root(self, root):
+ # Can use the gc list, but should not allocate!
+ # It is essential that the list is not resizable!
+ lst = self._list_rpy
+ index = self._count_rpy
+ if index >= len(lst):
+ raise ValueError
+ self._count_rpy = index + 1
+ lst[index] = llmemory.cast_adr_to_ptr(root.address[0], llmemory.GCREF)
+
+ def _do_append_rpy_roots(self, lst):
+ self._count_rpy = 0
+ self._list_rpy = lst
+ self.root_walker.walk_roots(
+ GCBase._append_rpy_root,
+ GCBase._append_rpy_root,
+ GCBase._append_rpy_root)
+ self._list_rpy = None
+
+ def get_rpy_roots(self):
+ count = self._do_count_rpy_roots()
+ extra = 16
+ while True:
+ result = [lltype.nullptr(llmemory.GCREF.TO)] * (count + extra)
+ try:
+ self._do_append_rpy_roots(result)
+ except ValueError:
+ extra *= 3
+ else:
+ return result
+
+ # ---------- implementation of pypy.rlib.rgc.get_rpy_referents() ----------
+
+ def _count_rpy_referent(self, pointer, _):
+ self._count_rpy += 1
+
+ def _do_count_rpy_referents(self, gcref):
+ self._count_rpy = 0
+ self.trace(llmemory.cast_ptr_to_adr(gcref),
+ self._count_rpy_referent, None)
+ return self._count_rpy
+
+ def _append_rpy_referent(self, pointer, _):
+ # Can use the gc list, but should not allocate!
+ # It is essential that the list is not resizable!
+ lst = self._list_rpy
+ index = self._count_rpy
+ if index >= len(lst):
+ raise ValueError
+ self._count_rpy = index + 1
+ lst[index] = llmemory.cast_adr_to_ptr(pointer.address[0],
+ llmemory.GCREF)
+
+ def _do_append_rpy_referents(self, gcref, lst):
+ self._count_rpy = 0
+ self._list_rpy = lst
+ self.trace(llmemory.cast_ptr_to_adr(gcref),
+ self._append_rpy_referent, None)
+
+ def get_rpy_referents(self, gcref):
+ count = self._do_count_rpy_referents(gcref)
+ result = [lltype.nullptr(llmemory.GCREF.TO)] * count
+ self._do_append_rpy_referents(gcref, result)
+ return result
+
class MovingGCBase(GCBase):
moving_gc = True
Modified: pypy/branch/gc-module/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/gc-module/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/branch/gc-module/pypy/rpython/memory/gctransform/framework.py Mon Sep 6 19:06:52 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
@@ -388,6 +388,15 @@
else:
self.id_ptr = None
+ self.get_rpy_roots_ptr = getfn(GCClass.get_rpy_roots.im_func,
+ [s_gc],
+ rgc.s_list_of_gcrefs(),
+ minimal_transform=False)
+ self.get_rpy_referents_ptr = getfn(GCClass.get_rpy_referents.im_func,
+ [s_gc, s_gcref],
+ rgc.s_list_of_gcrefs(),
+ 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 +892,21 @@
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_malloc_nonmovable_varsize(self, hop):
TYPE = hop.spaceop.result.concretetype
if self.gcdata.gc.can_malloc_nonmovable():
Modified: pypy/branch/gc-module/pypy/rpython/rptr.py
==============================================================================
--- pypy/branch/gc-module/pypy/rpython/rptr.py (original)
+++ pypy/branch/gc-module/pypy/rpython/rptr.py Mon Sep 6 19:06:52 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/branch/gc-module/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/branch/gc-module/pypy/translator/c/test/test_newgc.py (original)
+++ pypy/branch/gc-module/pypy/translator/c/test/test_newgc.py Mon Sep 6 19:06:52 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,56 @@
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")
+
class TestSemiSpaceGC(TestUsingFramework, snippet.SemiSpaceGCTestDefines):
gcpolicy = "semispace"
More information about the Pypy-commit
mailing list