Author: Maciej Fijalkowski <[email protected]>
Branch: jitframe-on-heap
Changeset: r60106:e0dbf5f5acd5
Date: 2013-01-16 00:56 +0200
http://bitbucket.org/pypy/pypy/changeset/e0dbf5f5acd5/
Log: this guy dies too
diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -228,186 +228,6 @@
# All code below is for the hybrid or minimark GC
-class GcRootMap_shadowstack(object):
- """Handles locating the stack roots in the assembler.
- This is the class supporting --gcrootfinder=shadowstack.
- """
- is_shadow_stack = True
- MARKER_FRAME = 8 # this marker now *follows* the frame addr
-
- # The "shadowstack" is a portable way in which the GC finds the
- # roots that live in the stack. Normally it is just a list of
- # pointers to GC objects. The pointers may be moved around by a GC
- # collection. But with the JIT, an entry can also be MARKER_FRAME,
- # in which case the previous entry points to an assembler stack frame.
- # During a residual CALL from the assembler (which may indirectly
- # call the GC), we use the force_index stored in the assembler
- # stack frame to identify the call: we can go from the force_index
- # to a list of where the GC pointers are in the frame (this is the
- # purpose of the present class).
- #
- # Note that across CALL_MAY_FORCE or CALL_ASSEMBLER, we can also go
- # from the force_index to a ResumeGuardForcedDescr instance, which
- # is used if the virtualizable or the virtualrefs need to be forced
- # (see pypy.jit.backend.model). The force_index number in the stack
- # frame is initially set to a non-negative value x, but it is
- # occasionally turned into (~x) in case of forcing.
-
- INTARRAYPTR = rffi.CArrayPtr(rffi.INT)
- CALLSHAPES_ARRAY = rffi.CArray(INTARRAYPTR)
-
- def __init__(self, gcdescr):
- self._callshapes = lltype.nullptr(self.CALLSHAPES_ARRAY)
- self._callshapes_maxlength = 0
- self.force_index_ofs = gcdescr.force_index_ofs
-
- def add_jit2gc_hooks(self, jit2gc):
- #
- # ---------------
- # This is used to enumerate the shadowstack in the presence
- # of the JIT. It is also used by the stacklet support in
- # rlib/_stacklet_shadowstack. That's why it is written as
- # an iterator that can also be used with a custom_trace.
- #
- class RootIterator:
- _alloc_flavor_ = "raw"
-
- def setcontext(iself, context):
- iself.context = context
-
- def nextleft(iself, gc, range_lowest, prev):
- # Return the next valid GC object's address, in right-to-left
- # order from the shadowstack array. This usually means just
- # returning "prev - sizeofaddr", until we reach "range_lowest",
- # except that we are skipping NULLs. If "prev - sizeofaddr"
- # contains a MARKER_FRAME instead, then we go into
- # JIT-frame-lookup mode.
- #
- while True:
- #
- # If we are not iterating right now in a JIT frame
- if iself.frame_addr == 0:
- #
- # Look for the next shadowstack address that
- # contains a valid pointer
- while prev != range_lowest:
- prev -= llmemory.sizeof(llmemory.Address)
- if prev.signed[0] == self.MARKER_FRAME:
- break
- if gc.points_to_valid_gc_object(prev):
- return prev
- else:
- return llmemory.NULL # done
- #
- # It's a JIT frame. Save away 'prev' for later, and
- # go into JIT-frame-exploring mode.
- prev -= llmemory.sizeof(llmemory.Address)
- frame_addr = prev.signed[0]
- iself.saved_prev = prev
- iself.frame_addr = frame_addr
- addr = llmemory.cast_int_to_adr(frame_addr +
- self.force_index_ofs)
- addr = iself.translateptr(iself.context, addr)
- force_index = addr.signed[0]
- if force_index < 0:
- force_index = ~force_index
- # NB: the next line reads a still-alive _callshapes,
- # because we ensure that just before we called this
- # piece of assembler, we put on the (same) stack a
- # pointer to a loop_token that keeps the force_index
- # alive.
- callshape = self._callshapes[force_index]
- else:
- # Continuing to explore this JIT frame
- callshape = iself.callshape
- #
- # 'callshape' points to the next INT of the callshape.
- # If it's zero we are done with the JIT frame.
- while rffi.cast(lltype.Signed, callshape[0]) != 0:
- #
- # Non-zero: it's an offset inside the JIT frame.
- # Read it and increment 'callshape'.
- offset = rffi.cast(lltype.Signed, callshape[0])
- callshape = lltype.direct_ptradd(callshape, 1)
- addr = llmemory.cast_int_to_adr(iself.frame_addr +
- offset)
- addr = iself.translateptr(iself.context, addr)
- if gc.points_to_valid_gc_object(addr):
- #
- # The JIT frame contains a valid GC pointer at
- # this address (as opposed to NULL). Save
- # 'callshape' for the next call, and return the
- # address.
- iself.callshape = callshape
- return addr
- #
- # Restore 'prev' and loop back to the start.
- iself.frame_addr = 0
- prev = iself.saved_prev
-
- # ---------------
- #
- root_iterator = RootIterator()
- root_iterator.frame_addr = 0
- root_iterator.context = llmemory.NULL
- root_iterator.translateptr = lambda context, addr: addr
- jit2gc.update({
- 'root_iterator': root_iterator,
- })
-
- def initialize(self):
- pass
-
- def get_basic_shape(self):
- return []
-
- def add_frame_offset(self, shape, offset):
- assert offset != 0
- shape.append(offset)
-
- def add_callee_save_reg(self, shape, register):
- msg = "GC pointer in %s was not spilled" % register
- os.write(2, '[llsupport/gc] %s\n' % msg)
- raise AssertionError(msg)
-
- def compress_callshape(self, shape, datablockwrapper):
- length = len(shape)
- SZINT = rffi.sizeof(rffi.INT)
- rawaddr = datablockwrapper.malloc_aligned((length + 1) * SZINT, SZINT)
- p = rffi.cast(self.INTARRAYPTR, rawaddr)
- for i in range(length):
- p[i] = rffi.cast(rffi.INT, shape[i])
- p[length] = rffi.cast(rffi.INT, 0)
- return p
-
- def write_callshape(self, p, force_index):
- if force_index >= self._callshapes_maxlength:
- self._enlarge_callshape_list(force_index + 1)
- self._callshapes[force_index] = p
-
- def _enlarge_callshape_list(self, minsize):
- newlength = 250 + (self._callshapes_maxlength // 3) * 4
- if newlength < minsize:
- newlength = minsize
- newarray = lltype.malloc(self.CALLSHAPES_ARRAY, newlength,
- flavor='raw', track_allocation=False)
- if self._callshapes:
- i = self._callshapes_maxlength - 1
- while i >= 0:
- newarray[i] = self._callshapes[i]
- i -= 1
- lltype.free(self._callshapes, flavor='raw', track_allocation=False)
- self._callshapes = newarray
- self._callshapes_maxlength = newlength
-
- def freeing_block(self, start, stop):
- pass # nothing needed here
-
- def get_root_stack_top_addr(self):
- rst_addr = llop.gc_adr_of_root_stack_top(llmemory.Address)
- return rffi.cast(lltype.Signed, rst_addr)
-
-
class WriteBarrierDescr(AbstractDescr):
def __init__(self, gc_ll_descr):
self.llop1 = gc_ll_descr.llop1
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit