Author: Gregor Wegberg <[email protected]>
Branch: gc-incminimark-pinning
Changeset: r72152:841b8277ef3a
Date: 2014-06-11 14:02 +0200
http://bitbucket.org/pypy/pypy/changeset/841b8277ef3a/
Log: wip: adding JIT support in presence of pinned objects
added _is_pinned method and _make_sure_does_not_move can fail now by
returning a boolean
diff --git a/rpython/memory/gc/base.py b/rpython/memory/gc/base.py
--- a/rpython/memory/gc/base.py
+++ b/rpython/memory/gc/base.py
@@ -182,6 +182,9 @@
def unpin(self, addr):
pass
+ def _is_pinned(self, addr):
+ return False
+
def set_max_heap_size(self, size):
raise NotImplementedError
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -960,24 +960,27 @@
# to check if can_move(obj) already returns True in which
# case a call to pin() is unnecessary.
return False
- if self.header(obj).tid & GCFLAG_PINNED:
+ if self._is_pinned(obj):
# Already pinned, we do not allow to pin it again.
# Reason: It would be possible that the first caller unpins
# while the second caller thinks it's still pinned.
return False
-
+ #
self.header(obj).tid |= GCFLAG_PINNED
self.pinned_objects_in_nursery += 1
return True
def unpin(self, obj):
- ll_assert(self.header(obj).tid & GCFLAG_PINNED != 0,
+ ll_assert(self._is_pinned(obj),
"unpin: object is already not pinned")
#
self.header(obj).tid &= ~GCFLAG_PINNED
self.pinned_objects_in_nursery -= 1
+ def _is_pinned(self, obj):
+ return (self.header(obj).tid & GCFLAG_PINNED) != 0
+
def shrink_array(self, obj, smallerlength):
#
# Only objects in the nursery can be "resized". Resizing them
@@ -1148,7 +1151,7 @@
# We are after a minor collection, and possibly after a major
# collection step. No object should be in the nursery (except
# pinned ones)
- if self.header(obj).tid & GCFLAG_PINNED == 0:
+ if not self._is_pinned(obj):
ll_assert(not self.is_in_nursery(obj),
"object in nursery after collection")
ll_assert(self.header(obj).tid & GCFLAG_VISITED_RMY == 0,
@@ -1204,7 +1207,7 @@
# All objects should have this flag, except if they
# don't have any GC pointer
typeid = self.get_type_id(obj)
- if not self.header(obj).tid & GCFLAG_PINNED:
+ if not self._is_pinned(obj):
# XXX do we need checks if the object is actually pinned? (groggi)
if self.has_gcptr(typeid):
ll_assert(self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS != 0,
@@ -1818,7 +1821,7 @@
root.address[0] = self.get_forwarding_address(obj)
return
#
- elif self.header(obj).tid & GCFLAG_PINNED:
+ elif self._is_pinned(obj):
hdr = self.header(obj)
if hdr.tid & GCFLAG_VISITED:
# already visited and keeping track of the object
diff --git a/rpython/memory/gc/test/test_object_pinning.py
b/rpython/memory/gc/test/test_object_pinning.py
--- a/rpython/memory/gc/test/test_object_pinning.py
+++ b/rpython/memory/gc/test/test_object_pinning.py
@@ -31,6 +31,15 @@
py.test.raises(Exception,
self.gc.unpin, llmemory.cast_ptr_to_adr(ptr))
+ def test__is_pinned(self):
+ ptr = self.malloc(S)
+ adr = llmemory.cast_ptr_to_adr(ptr)
+ assert not self.gc._is_pinned(adr)
+ assert self.gc.pin(adr)
+ assert self.gc._is_pinned(adr)
+ self.gc.unpin(adr)
+ assert not self.gc._is_pinned(adr)
+
# XXX test with multiple mallocs, and only part of them is pinned
diff --git a/rpython/memory/gctransform/framework.py
b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -466,6 +466,10 @@
[s_gc, SomeAddress()],
annmodel.s_None)
+ self._is_pinned_ptr = getfn(GCClass._is_pinned,
+ [s_gc, SomeAddress()],
+ annmodel.SomeBool())
+
self.write_barrier_ptr = None
self.write_barrier_from_array_ptr = None
if GCClass.needs_write_barrier:
@@ -986,6 +990,11 @@
op = hop.spaceop
hop.genop("direct_call", [self.unpin_ptr, self.c_const_gc, op.args[0]])
+ def gct_gc__is_pinned(self, hop):
+ op = hop.spaceop
+ hop.genop("direct_call", [self._is_pinned_ptr, self.c_const_gc,
op.args[0]],
+ resultvar=op.result)
+
def gct_gc_thread_run(self, hop):
assert self.translator.config.translation.thread
if hasattr(self.root_walker, 'thread_run_ptr'):
diff --git a/rpython/memory/gctransform/transform.py
b/rpython/memory/gctransform/transform.py
--- a/rpython/memory/gctransform/transform.py
+++ b/rpython/memory/gctransform/transform.py
@@ -356,6 +356,12 @@
def gct_gc_unpin(self, hop):
pass
+ def gct_gc__is_pinned(self, hop):
+ op = hop.spaceop
+ hop.genop("same_as",
+ [rmodel.inputconst(lltype.Bool, False)],
+ resultvar=op.result)
+
def gct_gc_identityhash(self, hop):
# must be implemented in the various GCs
raise NotImplementedError
diff --git a/rpython/memory/gcwrapper.py b/rpython/memory/gcwrapper.py
--- a/rpython/memory/gcwrapper.py
+++ b/rpython/memory/gcwrapper.py
@@ -128,6 +128,9 @@
def unpin(self, addr):
self.gc.unpin(addr)
+ def _is_pinned(self, addr):
+ return self.gc._is_pinned(addr)
+
def weakref_create_getlazy(self, objgetter):
# we have to be lazy in reading the llinterp variable containing
# the 'obj' pointer, because the gc.malloc() call below could
diff --git a/rpython/memory/test/gc_test_base.py
b/rpython/memory/test/gc_test_base.py
--- a/rpython/memory/test/gc_test_base.py
+++ b/rpython/memory/test/gc_test_base.py
@@ -810,6 +810,27 @@
else:
assert res == 0 or res == 13
+ def test__is_pinned(self):
+ def fn(n):
+ from rpython.rlib.debug import debug_print
+ s = str(n)
+ if not rgc.can_move(s):
+ return 13
+ res = int(rgc.pin(s))
+ if res:
+ res += int(rgc._is_pinned(s))
+ rgc.unpin(s)
+ return res
+
+ res = self.interpret(fn, [10])
+ if not self.GCClass.moving_gc:
+ assert res == 13
+ elif self.GCClass.can_usually_pin_objects:
+ assert res == 2
+ else:
+ assert res == 0 or res == 13
+
+
from rpython.rlib.objectmodel import UnboxedValue
class TaggedBase(object):
diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -76,6 +76,24 @@
resulttype=llmemory.Address)
hop.genop('gc_unpin', [v_addr])
+def _is_pinned(obj):
+ """Method to check if 'obj' is pinned."""
+ return False
+
+class IsPinnedEntry(ExtRegistryEntry):
+ _about_ = _is_pinned
+
+ def compute_result_annotation(self, s_arg):
+ from rpython.annotator.model import s_Bool
+ return s_Bool
+
+ def specialize_call(self, hop):
+ hop.exception_cannot_occur()
+ v_obj, = hop.inputargs(hop.args_r[0])
+ v_addr = hop.genop('cast_ptr_to_adr', [v_obj],
+ resulttype=llmemory.Address)
+ return hop.genop('gc__is_pinned', [v_addr], resulttype=lltype.Bool)
+
# ____________________________________________________________
# Annotation and specialization
@@ -136,13 +154,16 @@
on objects that are already a bit old, so have a chance to be
already non-movable."""
if not we_are_translated():
- return
+ return True # XXX: check if True is the right return (groggi)
+ if _is_pinned(p):
+ return False
i = 0
while can_move(p):
if i > 6:
raise NotImplementedError("can't make object non-movable!")
collect(i)
i += 1
+ return True
def _heap_stats():
raise NotImplementedError # can't be run directly
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -865,6 +865,9 @@
def op_gc_unpin(self, obj):
self.heap.unpin(obj)
+ def op_gc__is_pinned(self, obj):
+ return self.heap._is_pinned(obj)
+
def op_gc_detach_callback_pieces(self):
raise NotImplementedError("gc_detach_callback_pieces")
def op_gc_reattach_callback_pieces(self):
diff --git a/rpython/rtyper/lltypesystem/llheap.py
b/rpython/rtyper/lltypesystem/llheap.py
--- a/rpython/rtyper/lltypesystem/llheap.py
+++ b/rpython/rtyper/lltypesystem/llheap.py
@@ -39,3 +39,6 @@
def unpin(obj):
raise AssertionError("pin() always returns False, "
"so unpin() should not be called")
+
+def _is_pinned(obj):
+ return False
diff --git a/rpython/rtyper/lltypesystem/lloperation.py
b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -482,6 +482,7 @@
'gc_heap_stats' : LLOp(canmallocgc=True),
'gc_pin' : LLOp(canrun=True), # XXX understand this, correct?
(groggi)
'gc_unpin' : LLOp(canrun=True), # XXX understand this, correct?
(groggi)
+ 'gc_is__pinned' : LLOp(canrun=True), # XXX understand this,
correct? (groggi)
'gc_get_rpy_roots' : LLOp(),
'gc_get_rpy_referents': LLOp(),
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit