[pypy-svn] r47434 - in pypy/dist/pypy: rpython rpython/lltypesystem rpython/memory rpython/memory/gc rpython/memory/gctransform rpython/memory/test translator/c translator/c/src translator/c/test
arigo at codespeak.net
arigo at codespeak.net
Sat Oct 13 22:35:00 CEST 2007
Author: arigo
Date: Sat Oct 13 22:34:59 2007
New Revision: 47434
Modified:
pypy/dist/pypy/rpython/llinterp.py
pypy/dist/pypy/rpython/lltypesystem/llheap.py
pypy/dist/pypy/rpython/lltypesystem/llmemory.py
pypy/dist/pypy/rpython/lltypesystem/lloperation.py
pypy/dist/pypy/rpython/lltypesystem/lltype.py
pypy/dist/pypy/rpython/memory/gc/base.py
pypy/dist/pypy/rpython/memory/gc/semispace.py
pypy/dist/pypy/rpython/memory/gctransform/boehm.py
pypy/dist/pypy/rpython/memory/gctransform/framework.py
pypy/dist/pypy/rpython/memory/gctransform/transform.py
pypy/dist/pypy/rpython/memory/gcwrapper.py
pypy/dist/pypy/rpython/memory/test/test_gc.py
pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
pypy/dist/pypy/rpython/rmodel.py
pypy/dist/pypy/translator/c/gc.py
pypy/dist/pypy/translator/c/src/address.h
pypy/dist/pypy/translator/c/test/test_boehm.py
Log:
Fix the id() in the presence of a moving GC. This first attempt is
based on a veeeery slow implementation.
M pypy/translator/c/test/test_boehm.py
In Boehm the RPython-level id() no longer keeps
the object alive
M pypy/translator/c/gc.py
M pypy/translator/c/src/address.h
Delete old code
M pypy/rpython/memory/test/test_gc.py
M pypy/rpython/memory/test/test_transformed_gc.py
Add tests for id()
M pypy/rpython/lltypesystem/lloperation.py
M pypy/rpython/lltypesystem/llheap.py
M pypy/rpython/memory/gcwrapper.py
M pypy/rpython/llinterp.py
M pypy/rpython/rmodel.py
Add 'gc_id' as an lloperation
M pypy/rpython/memory/gctransform/transform.py
M pypy/rpython/memory/gctransform/framework.py
M pypy/rpython/memory/gctransform/boehm.py
Transform this 'gc_id' in the gctransformer
M pypy/rpython/memory/gc/semispace.py
M pypy/rpython/memory/gc/base.py
Generic but inefficient implementation of id()
for all moving GCs
M pypy/rpython/lltypesystem/llmemory.py
M pypy/rpython/lltypesystem/lltype.py
Add more pointer casts when required.
Check for freed objects in _wref.
Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py (original)
+++ pypy/dist/pypy/rpython/llinterp.py Sat Oct 13 22:34:59 2007
@@ -778,6 +778,9 @@
self.setvar(v_ptr, p)
op_gc_reload_possibly_moved.specialform = True
+ def op_gc_id(self, v_ptr):
+ return self.heap.gc_id(v_ptr)
+
def op_gc_set_max_heap_size(self, maxsize):
raise NotImplementedError("gc_set_max_heap_size")
Modified: pypy/dist/pypy/rpython/lltypesystem/llheap.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llheap.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/llheap.py Sat Oct 13 22:34:59 2007
@@ -14,3 +14,5 @@
assert typeOf(newvalue) == INNERTYPE
# xxx access the address object's ref() directly for performance
inneraddr.ref()[0] = newvalue
+
+from pypy.rpython.lltypesystem.lltype import cast_ptr_to_int as gc_id
Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Sat Oct 13 22:34:59 2007
@@ -366,45 +366,12 @@
raise NullAddressError
return self.ptr
-## def get(self):
-## return self.ref().get()
-
-## def set(self, value):
-## self.ref().set(value)
-
def _cast_to_ptr(self, EXPECTED_TYPE):
if self:
- PTRTYPE = lltype.typeOf(self.ptr)
- if (isinstance(EXPECTED_TYPE.TO, lltype.OpaqueType) or
- isinstance(PTRTYPE.TO, lltype.OpaqueType)):
- return lltype.cast_opaque_ptr(EXPECTED_TYPE, self.ptr)
- else:
- # regular case
- return lltype.cast_pointer(EXPECTED_TYPE, self.ptr)
+ return cast_any_ptr(EXPECTED_TYPE, self.ptr)
else:
return lltype.nullptr(EXPECTED_TYPE.TO)
-## if (isinstance(ref, _arrayitemref) and
-## isinstance(EXPECTED_TYPE.TO, lltype.FixedSizeArray) and
-## ref.type() == EXPECTED_TYPE.TO.OF):
-## # special case that requires direct_arrayitems
-## p_items = lltype.direct_arrayitems(ref.array)
-## return lltype.direct_ptradd(p_items, ref.index)
-## elif (isinstance(ref, _structfieldref) and
-## isinstance(EXPECTED_TYPE.TO, lltype.FixedSizeArray) and
-## ref.type() == EXPECTED_TYPE.TO.OF):
-## # special case that requires direct_fieldptr
-## return lltype.direct_fieldptr(ref.struct,
-## ref.fieldname)
-## else:
-## result = ref.get()
-## if (isinstance(EXPECTED_TYPE.TO, lltype.OpaqueType) or
-## isinstance(lltype.typeOf(result).TO, lltype.OpaqueType)):
-## return lltype.cast_opaque_ptr(EXPECTED_TYPE, result)
-## else:
-## # regular case
-## return lltype.cast_pointer(EXPECTED_TYPE, result)
-
def _cast_to_int(self):
if self:
return self.ptr._cast_to_int()
@@ -538,7 +505,7 @@
if p is None:
return lltype.nullptr(PTRTYPE.TO)
else:
- return lltype.cast_pointer(PTRTYPE, p)
+ return cast_any_ptr(PTRTYPE, p)
class _wref(lltype._container):
_gckind = 'gc'
@@ -553,7 +520,9 @@
def _dereference(self):
obj = self._obref()
- if obj is None:
+ # in combination with a GC like the SemiSpace, the 'obj' can be
+ # still alive in the CPython sense but freed by the arena logic.
+ if obj is None or obj._was_freed():
return None
else:
return obj._as_ptr()
@@ -584,7 +553,8 @@
assert lltype.typeOf(pwref) == WeakRefPtr
if pwref:
assert isinstance(pwref._obj, _gctransformed_wref)
- assert PTRTYPE == lltype.typeOf(pwref._obj._ptr)
+ if PTRTYPE is not None:
+ assert PTRTYPE == lltype.typeOf(pwref._obj._ptr)
return pwref._obj._ptr
else:
return lltype.nullptr(PTRTYPE.TO)
@@ -636,3 +606,20 @@
assert lltype.typeOf(source) == Address
assert lltype.typeOf(dest) == Address
size.raw_memcopy(source, dest)
+
+def cast_any_ptr(EXPECTED_TYPE, ptr):
+ # this is a generalization of the various cast_xxx_ptr() functions.
+ PTRTYPE = lltype.typeOf(ptr)
+ if PTRTYPE == EXPECTED_TYPE:
+ return ptr
+ elif EXPECTED_TYPE == WeakRefPtr:
+ return cast_ptr_to_weakrefptr(ptr)
+ elif PTRTYPE == WeakRefPtr:
+ ptr = cast_weakrefptr_to_ptr(None, ptr)
+ return cast_any_ptr(EXPECTED_TYPE, ptr)
+ elif (isinstance(EXPECTED_TYPE.TO, lltype.OpaqueType) or
+ isinstance(PTRTYPE.TO, lltype.OpaqueType)):
+ return lltype.cast_opaque_ptr(EXPECTED_TYPE, ptr)
+ else:
+ # regular case
+ return lltype.cast_pointer(EXPECTED_TYPE, ptr)
Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Sat Oct 13 22:34:59 2007
@@ -389,6 +389,7 @@
'gc_protect': LLOp(),
'gc_unprotect': LLOp(),
'gc_reload_possibly_moved': LLOp(),
+ 'gc_id': LLOp(canraise=(MemoryError,), sideeffects=False),
'gc_set_max_heap_size': LLOp(),
# experimental operations in support of thread cloning, only
# implemented by the Mark&Sweep GC
Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Sat Oct 13 22:34:59 2007
@@ -1278,6 +1278,8 @@
return self
def _getid(self):
return id(self)
+ def _was_freed(self):
+ return False
class _parentable(_container):
_kind = "?"
@@ -1300,6 +1302,9 @@
self._check() # no double-frees
self._storage = None
+ def _was_freed(self):
+ return self._storage is None
+
def _setparentstructure(self, parent, parentindex):
self._wrparent = weakref.ref(parent)
self._parent_type = typeOf(parent)
Modified: pypy/dist/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/base.py (original)
+++ pypy/dist/pypy/rpython/memory/gc/base.py Sat Oct 13 22:34:59 2007
@@ -68,6 +68,9 @@
# lots of cast and reverse-cast around...
return llmemory.cast_ptr_to_adr(ref)
+ def id(self, ptr):
+ return lltype.cast_ptr_to_int(ptr)
+
def x_swap_pool(self, newpool):
return newpool
@@ -78,6 +81,38 @@
raise RuntimeError("no support for x_become in the GC")
+class MovingGCBase(GCBase):
+ moving_gc = True
+
+ def __init__(self):
+ self.wr_to_objects_with_id = []
+
+ def id(self, ptr):
+ # XXX linear search! this is probably too slow to be reasonable :-(
+ # On the other hand, it punishes you for using 'id', so that's good :-)
+ # XXX this may explode if --no-translation-rweakref is specified
+ lst = self.wr_to_objects_with_id
+ i = len(lst)
+ freeentry = -1
+ while i > 0:
+ i -= 1
+ target = llmemory.weakref_deref(llmemory.GCREF, lst[i])
+ if not target:
+ freeentry = i
+ elif target == ptr:
+ break # found
+ else:
+ # not found
+ wr = llmemory.weakref_create(ptr)
+ if freeentry == -1:
+ i = len(lst)
+ lst.append(wr)
+ else:
+ i = freeentry # reuse the id() of a dead object
+ lst[i] = wr
+ return i + 1 # this produces id() values 1, 2, 3, 4...
+
+
def choose_gc_from_config(config):
"""Return a (GCClass, GC_PARAMS) from the given config object.
"""
@@ -88,7 +123,7 @@
return MarkSweepGC, GC_PARAMS
elif config.translation.frameworkgc == "semispace":
GC_PARAMS = {'space_size': 8*1024*1024} # XXX adjust
- from pypy.rpython.memory.gc.marksweep import SemiSpaceGC
+ from pypy.rpython.memory.gc.semispace import SemiSpaceGC
return SemiSpaceGC, GC_PARAMS
else:
raise ValueError("unknown value for frameworkgc: %r" % (
Modified: pypy/dist/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/semispace.py (original)
+++ pypy/dist/pypy/rpython/memory/gc/semispace.py Sat Oct 13 22:34:59 2007
@@ -7,16 +7,15 @@
from pypy.rlib.objectmodel import free_non_gc_object, debug_assert
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rlib.rarithmetic import ovfcheck
-from pypy.rpython.memory.gc.base import GCBase
+from pypy.rpython.memory.gc.base import MovingGCBase
import sys, os
memoryError = MemoryError()
-class SemiSpaceGC(GCBase):
+class SemiSpaceGC(MovingGCBase):
_alloc_flavor_ = "raw"
- moving_gc = True
inline_simple_malloc = True
HDR = lltype.Struct('header', ('forw', llmemory.Address),
@@ -25,6 +24,7 @@
def __init__(self, AddressLinkedList, space_size=4096,
max_space_size=sys.maxint//2+1,
get_roots=None):
+ MovingGCBase.__init__(self)
self.space_size = space_size
self.max_space_size = max_space_size
self.get_roots = get_roots
Modified: pypy/dist/pypy/rpython/memory/gctransform/boehm.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/boehm.py (original)
+++ pypy/dist/pypy/rpython/memory/gctransform/boehm.py Sat Oct 13 22:34:59 2007
@@ -147,6 +147,12 @@
resulttype=llmemory.Address)
hop.cast_result(v_addr)
+ def gct_gc_id(self, hop):
+ # this is the logic from the HIDE_POINTER macro in <gc/gc.h>
+ v_int = hop.genop('cast_ptr_to_int', [hop.spaceop.args[0]],
+ resulttype = lltype.Signed)
+ hop.genop('int_invert', [v_int], resultvar=hop.spaceop.result)
+
########## weakrefs ##########
# Boehm: weakref objects are small structures containing only a Boehm
Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/dist/pypy/rpython/memory/gctransform/framework.py Sat Oct 13 22:34:59 2007
@@ -238,6 +238,14 @@
else:
self.malloc_fast_ptr = self.malloc_fixedsize_ptr
+ if GCClass.moving_gc:
+ self.id_ptr = getfn(GCClass.id.im_func,
+ [s_gc, s_gcref], annmodel.SomeInteger(),
+ inline = False,
+ minimal_transform = False)
+ else:
+ self.id_ptr = None
+
self.statistics_ptr = getfn(GCClass.statistics.im_func,
[s_gc, annmodel.SomeInteger()],
annmodel.SomeInteger())
@@ -523,6 +531,18 @@
resulttype=llmemory.Address)
hop.cast_result(v_addr)
+ def gct_gc_id(self, hop):
+ if self.id_ptr is not None:
+ self.push_roots(hop)
+ [v_ptr] = hop.spaceop.args
+ v_ptr = hop.genop("cast_opaque_ptr", [v_ptr],
+ resulttype=llmemory.GCREF)
+ hop.genop("direct_call", [self.id_ptr, self.c_const_gc, v_ptr],
+ resultvar=hop.spaceop.result)
+ self.pop_roots(hop)
+ else:
+ hop.rename('cast_ptr_to_int') # works nicely for non-moving GCs
+
def push_alive_nopyobj(self, var, llops):
pass
Modified: pypy/dist/pypy/rpython/memory/gctransform/transform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/transform.py (original)
+++ pypy/dist/pypy/rpython/memory/gctransform/transform.py Sat Oct 13 22:34:59 2007
@@ -325,6 +325,10 @@
def gct_zero_gc_pointers_inside(self, hop):
pass
+ def gct_gc_id(self, hop):
+ # this assumes a non-moving GC. Moving GCs need to override this
+ hop.rename('cast_ptr_to_int')
+
class MinimalGCTransformer(BaseGCTransformer):
def __init__(self, parenttransformer):
Modified: pypy/dist/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gcwrapper.py (original)
+++ pypy/dist/pypy/rpython/memory/gcwrapper.py Sat Oct 13 22:34:59 2007
@@ -85,6 +85,10 @@
addr = gctypelayout.ll_weakref_deref(obj)
return llmemory.cast_adr_to_ptr(addr, PTRTYPE)
+ def gc_id(self, ptr):
+ ptr = lltype.cast_opaque_ptr(llmemory.GCREF, ptr)
+ return self.gc.id(ptr)
+
# ____________________________________________________________
class RootLinkedList(object):
Modified: pypy/dist/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_gc.py (original)
+++ pypy/dist/pypy/rpython/memory/test/test_gc.py Sat Oct 13 22:34:59 2007
@@ -251,6 +251,25 @@
res = self.interpret(f, [])
assert res
+ def test_id(self):
+ class A(object):
+ pass
+ a1 = A()
+ def f():
+ a2 = A()
+ a3 = A()
+ id1 = id(a1)
+ id2 = id(a2)
+ id3 = id(a3)
+ llop.gc__collect(lltype.Void)
+ error = 0
+ if id1 != id(a1): error += 1
+ if id2 != id(a2): error += 2
+ if id3 != id(a3): error += 4
+ return error
+ res = self.interpret(f, [])
+ assert res == 0
+
class TestMarkSweepGC(GCTest):
from pypy.rpython.memory.gc.marksweep import MarkSweepGC as GCClass
Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original)
+++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Sat Oct 13 22:34:59 2007
@@ -376,6 +376,26 @@
res = run([])
assert res == 111111
+ def test_id(self):
+ class A(object):
+ pass
+ a1 = A()
+ def func():
+ a2 = A()
+ a3 = A()
+ id1 = id(a1)
+ id2 = id(a2)
+ id3 = id(a3)
+ llop.gc__collect(lltype.Void)
+ error = 0
+ if id1 != id(a1): error += 1
+ if id2 != id(a2): error += 2
+ if id3 != id(a3): error += 4
+ return error
+ run = self.runner(func)
+ res = run([])
+ assert res == 0
+
class TestMarkSweepGC(GenericGCTests):
class gcpolicy(gc.FrameworkGcPolicy):
class transformerclass(framework.FrameworkGCTransformer):
Modified: pypy/dist/pypy/rpython/rmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/rmodel.py (original)
+++ pypy/dist/pypy/rpython/rmodel.py Sat Oct 13 22:34:59 2007
@@ -220,9 +220,7 @@
raise TyperError('id() of an instance of the non-pointer %r' % (
self,))
vobj, = hop.inputargs(self)
- # XXX I am still not sure whether this is the right thing to do,
- # since the int might keep things alive with boehm
- return hop.genop('cast_ptr_to_int', [vobj], resulttype=Signed)
+ return hop.genop('gc_id', [vobj], resulttype=Signed)
def rtype_hash(self, hop):
ll_hash = self.get_ll_hash_function()
Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py (original)
+++ pypy/dist/pypy/translator/c/gc.py Sat Oct 13 22:34:59 2007
@@ -199,7 +199,6 @@
if sys.platform != "win32":
# GC_REDIRECT_TO_LOCAL is not supported on Win32 by gc6.8
yield "#define GC_REDIRECT_TO_LOCAL 1"
- yield "#define GC_I_HIDE_POINTERS 1"
yield '#include <gc/gc.h>'
yield '#define USING_BOEHM_GC'
Modified: pypy/dist/pypy/translator/c/src/address.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/address.h (original)
+++ pypy/dist/pypy/translator/c/src/address.h Sat Oct 13 22:34:59 2007
@@ -18,11 +18,3 @@
#define OP_CAST_ADR_TO_INT(x, r) r = ((long)x)
#define OP_CAST_INT_TO_ADR(x, r) r = ((void *)(x))
-
-#ifndef HIDE_POINTER
-#define HIDE_POINTER(p) (p)
-#ifdef REVEAL_POINTER
-#error HIDE_POINTER but not REVEAL_POINTER?
-#endif
-#define REVEAL_POINTER(p) (p)
-#endif
Modified: pypy/dist/pypy/translator/c/test/test_boehm.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_boehm.py (original)
+++ pypy/dist/pypy/translator/c/test/test_boehm.py Sat Oct 13 22:34:59 2007
@@ -102,7 +102,6 @@
def test_id_is_weak(self):
# test that id(obj) does not keep obj alive
- py.test.skip("fails")
from pypy.rpython.lltypesystem.lloperation import llop
class State:
pass
More information about the Pypy-commit
mailing list