[pypy-commit] pypy gc-incminimark-pinning: renaming, rewriting, etc. for handling movable objects (i.e. ConstPtrs that have a pointer which isn't really constant) inside the JIT
groggi
noreply at buildbot.pypy.org
Sat Aug 16 18:47:29 CEST 2014
Author: Gregor Wegberg <code at gregorwegberg.com>
Branch: gc-incminimark-pinning
Changeset: r72826:ed703b3e1311
Date: 2014-08-16 18:46 +0200
http://bitbucket.org/pypy/pypy/changeset/ed703b3e1311/
Log: renaming, rewriting, etc. for handling movable objects (i.e.
ConstPtrs that have a pointer which isn't really constant) inside
the JIT
diff --git a/rpython/jit/backend/llsupport/gc.py b/rpython/jit/backend/llsupport/gc.py
--- a/rpython/jit/backend/llsupport/gc.py
+++ b/rpython/jit/backend/llsupport/gc.py
@@ -20,32 +20,36 @@
from rpython.memory.gctransform import asmgcroot
from rpython.rtyper.lltypesystem import llmemory
-class PinnedObjectTracker(object):
- """Simple helper class to keep informations regarding the 'GcArray'
- in one place that is used to double load pinned objects.
- """
+class MovableObjectTracker(object):
- _ref_array_type = lltype.GcArray(llmemory.GCREF)
+ ptr_array_type = lltype.GcArray(llmemory.GCREF)
- def __init__(self, cpu, pointers):
- # prepare GC array to hold the pointers
- size = len(pointers)
- self._ref_array = lltype.malloc(PinnedObjectTracker._ref_array_type, size)
- self.ref_array_descr = cpu.arraydescrof(PinnedObjectTracker._ref_array_type)
- self.ref_array_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, self._ref_array)
- self.const_ptr_gcref_array = ConstPtr(self.ref_array_gcref)
+ def __init__(self, cpu, const_pointers):
+ size = len(const_pointers)
+ # check that there are any moving object (i.e. chaning pointers).
+ # Otherwise there is no reason for an instance of this class.
+ assert size > 0
#
- # assign each pointer an index and put the pointer into the GC array
+ # prepare GC array to hold the pointers that may change
+ self.ptr_array = lltype.malloc(MovableObjectTracker.ptr_array_type, size)
+ self.ptr_array_descr = cpu.arraydescrof(MovableObjectTracker.ptr_array_type)
+ self.ptr_array_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, self.ptr_array)
+ # use always the same ConstPtr to access the array
+ # (easer to read JIT trace)
+ self.const_ptr_gcref_array = ConstPtr(self.ptr_array_gcref)
+ #
+ # assign each pointer an index and put the pointer into the GC array.
+ # as pointers and addresses are not a good key to use before translation
+ # ConstPtrs are used as the key for the dict.
self._indexes = {}
- for index in range(len(pointers)):
- ptr = pointers[index]
- self._indexes[llmemory.cast_ptr_to_adr(ptr)] = llmemory.cast_int_to_adr(index)
- self._ref_array[index] = ptr
+ for index in range(size):
+ ptr = const_pointers[index]
+ self._indexes[ptr] = index
+ self.ptr_array[index] = ptr.value
- def add_ref(self, ptr):
- assert llmemory.cast_ptr_to_adr(ptr) in self._indexes
- index = llmemory.cast_adr_to_int(self._indexes[llmemory.cast_ptr_to_adr(ptr)])
- assert ptr == self._ref_array[index]
+ def get_array_index(self, const_ptr):
+ index = self._indexes[const_ptr]
+ assert const_ptr.value == self.ptr_array[index]
return index
# ____________________________________________________________
@@ -120,9 +124,9 @@
def gc_malloc_unicode(self, num_elem):
return self._bh_malloc_array(num_elem, self.unicode_descr)
- def _record_constptrs(self, op, gcrefs_output_list, moving_output_list,
- known_pointers):
- moving_output_list[op] = []
+ def _record_constptrs(self, op, gcrefs_output_list, ops_with_movable_const_ptr,
+ changeable_const_pointers):
+ ops_with_movable_const_ptr[op] = []
for i in range(op.numargs()):
v = op.getarg(i)
if isinstance(v, ConstPtr) and bool(v.value):
@@ -130,33 +134,31 @@
if rgc._make_sure_does_not_move(p):
gcrefs_output_list.append(p)
else:
- moving_output_list[op].append(i)
- if p not in known_pointers:
- known_pointers.append(p)
+ ops_with_movable_const_ptr[op].append(i)
+ if v not in changeable_const_pointers:
+ changeable_const_pointers.append(v)
#
if op.is_guard() or op.getopnum() == rop.FINISH:
llref = cast_instance_to_gcref(op.getdescr())
assert rgc._make_sure_does_not_move(llref)
gcrefs_output_list.append(llref)
#
- if len(moving_output_list[op]) == 0:
- del moving_output_list[op]
+ if len(ops_with_movable_const_ptr[op]) == 0:
+ del ops_with_movable_const_ptr[op]
- def _rewrite_constptrs(self, op, moving_output_list, pinned_obj_tracker):
+ def _rewrite_changeable_constptrs(self, op, ops_with_movable_const_ptr, moving_obj_tracker):
newops = []
- for arg_i in moving_output_list[op]:
+ for arg_i in ops_with_movable_const_ptr[op]:
v = op.getarg(arg_i)
# assert to make sure we got what we expected
assert isinstance(v, ConstPtr)
- assert bool(v.value)
- p = v.value
result_ptr = BoxPtr()
- array_index = pinned_obj_tracker.add_ref(p)
+ array_index = moving_obj_tracker.get_array_index(v)
load_op = ResOperation(rop.GETARRAYITEM_GC,
- [pinned_obj_tracker.const_ptr_gcref_array,
+ [moving_obj_tracker.const_ptr_gcref_array,
ConstInt(array_index)],
result_ptr,
- descr=pinned_obj_tracker.ref_array_descr)
+ descr=moving_obj_tracker.ptr_array_descr)
newops.append(load_op)
op.setarg(arg_i, result_ptr)
#
@@ -166,37 +168,48 @@
def rewrite_assembler(self, cpu, operations, gcrefs_output_list):
rewriter = GcRewriterAssembler(self, cpu)
newops = rewriter.rewrite(operations)
- # record all GCREFs, because the GC (or Boehm) cannot see them and
- # keep them alive if they end up as constants in the assembler
-
- # XXX add comment (groggi)
-
- newnewops = [] # XXX better name... (groggi)
- moving_output_list = {}
- known_pointers = []
+ # the key is an operation that contains a ConstPtr as an argument and
+ # this ConstPtrs pointer might change as it points to an object that
+ # can't be made non-moving (e.g. the object is pinned).
+ ops_with_movable_const_ptr = {}
+ #
+ # a list of such not really constant ConstPtrs.
+ changeable_const_pointers = []
for op in newops:
- self._record_constptrs(op, gcrefs_output_list, moving_output_list,
- known_pointers)
+ # record all GCREFs, because the GC (or Boehm) cannot see them and
+ # keep them alive if they end up as constants in the assembler.
+ # If such a GCREF can change and we can't make the object it points
+ # to non-movable, we have to handle it seperatly. Such GCREF's are
+ # returned as ConstPtrs in 'changeable_const_pointers' and the
+ # affected operation is returned in 'op_with_movable_const_ptr'.
+ # For this special case see 'rewrite_changeable_constptrs'.
+ self._record_constptrs(op, gcrefs_output_list,
+ ops_with_movable_const_ptr, changeable_const_pointers)
#
- if len(moving_output_list) > 0:
- pinned_obj_tracker = PinnedObjectTracker(cpu, known_pointers)
+ # handle pointers that are not guaranteed to stay the same
+ if len(ops_with_movable_const_ptr) > 0:
+ moving_obj_tracker = MovableObjectTracker(cpu, changeable_const_pointers)
+ #
if not we_are_translated():
- self.last_pinned_object_tracker = pinned_obj_tracker
- gcrefs_output_list.append(pinned_obj_tracker.ref_array_gcref)
- rgc._make_sure_does_not_move(pinned_obj_tracker.ref_array_gcref)
+ # used for testing
+ self.last_moving_obj_tracker = moving_obj_tracker
+ # make sure the array containing the pointers is not collected by
+ # the GC (or Boehm)
+ gcrefs_output_list.append(moving_obj_tracker.ptr_array_gcref)
+ rgc._make_sure_does_not_move(moving_obj_tracker.ptr_array_gcref)
- for op in newops:
- if op in moving_output_list:
- reops = self._rewrite_constptrs(op, moving_output_list,
- pinned_obj_tracker)
- newnewops.extend(reops)
+ ops = newops
+ newops = []
+ for op in ops:
+ if op in ops_with_movable_const_ptr:
+ rewritten_ops = self._rewrite_changeable_constptrs(op,
+ ops_with_movable_const_ptr, moving_obj_tracker)
+ newops.extend(rewritten_ops)
else:
- newnewops.append(op)
- #
- return newnewops
- else:
- return newops
+ newops.append(op)
+ #
+ return newops
@specialize.memo()
def getframedescrs(self, cpu):
diff --git a/rpython/jit/backend/llsupport/test/test_pinned_object_rewrite.py b/rpython/jit/backend/llsupport/test/test_pinned_object_rewrite.py
--- a/rpython/jit/backend/llsupport/test/test_pinned_object_rewrite.py
+++ b/rpython/jit/backend/llsupport/test/test_pinned_object_rewrite.py
@@ -3,7 +3,7 @@
get_field_descr, get_array_descr, ArrayDescr, FieldDescr,\
SizeDescrWithVTable, get_interiorfield_descr
from rpython.jit.backend.llsupport.gc import GcLLDescr_boehm,\
- GcLLDescr_framework, PinnedObjectTracker
+ GcLLDescr_framework, MovableObjectTracker
from rpython.jit.backend.llsupport import jitframe, gc
from rpython.jit.metainterp.gc import get_description
from rpython.jit.tool.oparser import parse
@@ -45,7 +45,7 @@
notpinned_obj_ptr = lltype.malloc(notpinned_obj_type)
notpinned_obj_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, notpinned_obj_ptr)
#
- ref_array_descr = self.cpu.arraydescrof(PinnedObjectTracker._ref_array_type)
+ ptr_array_descr = self.cpu.arraydescrof(MovableObjectTracker.ptr_array_type)
#
vtable_descr = self.gc_ll_descr.fielddescr_vtable
O = lltype.GcStruct('O', ('parent', rclass.OBJECT),
@@ -92,9 +92,9 @@
[])
# make the array containing the GCREF's accessible inside the tests.
# This must be done after we call 'rewrite_assembler'. Before that
- # call 'last_pinned_object_tracker' is None or filled with some old
+ # call 'last_moving_obj_tracker' is None or filled with some old
# value.
- namespace['ref_array_gcref'] = self.gc_ll_descr.last_pinned_object_tracker.ref_array_gcref
+ namespace['ptr_array_gcref'] = self.gc_ll_descr.last_moving_obj_tracker.ptr_array_gcref
expected = parse(to_operations % Evaluator(namespace),
namespace=namespace)
equaloplists(operations, expected.operations)
@@ -127,7 +127,7 @@
i0 = getfield_gc(ConstPtr(pinned_obj_gcref), descr=pinned_obj_my_int_descr)
""", """
[]
- p1 = getarrayitem_gc(ConstPtr(ref_array_gcref), 0, descr=ref_array_descr)
+ p1 = getarrayitem_gc(ConstPtr(ptr_array_gcref), 0, descr=ptr_array_descr)
i0 = getfield_gc(p1, descr=pinned_obj_my_int_descr)
""")
@@ -139,9 +139,9 @@
i2 = getfield_gc(ConstPtr(pinned_obj_gcref), descr=pinned_obj_my_int_descr)
""", """
[]
- p1 = getarrayitem_gc(ConstPtr(ref_array_gcref), 0, descr=ref_array_descr)
+ p1 = getarrayitem_gc(ConstPtr(ptr_array_gcref), 0, descr=ptr_array_descr)
i0 = getfield_gc(p1, descr=pinned_obj_my_int_descr)
i1 = getfield_gc(ConstPtr(notpinned_obj_gcref), descr=notpinned_obj_my_int_descr)
- p2 = getarrayitem_gc(ConstPtr(ref_array_gcref), 1, descr=ref_array_descr)
+ p2 = getarrayitem_gc(ConstPtr(ptr_array_gcref), 1, descr=ptr_array_descr)
i2 = getfield_gc(p2, descr=pinned_obj_my_int_descr)
""")
More information about the pypy-commit
mailing list