Author: Armin Rigo <ar...@tunes.org> Branch: stacklet Changeset: r46686:b02950d06234 Date: 2011-08-21 14:09 +0000 http://bitbucket.org/pypy/pypy/changeset/b02950d06234/
Log: Fixes, and also copies most of the last checkin done in the custom- trace branch. 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 @@ -373,85 +373,85 @@ # rlib/_stacklet_shadowstack. That's why it is written as # an iterator that can also be used with a custom_trace. # - def iterator_setup(): - self._iter_frame_addr = llmemory.NULL - self._iter_callshape = llmemory.NULL - self._iter_saved_prev = llmemory.NULL - # - def iterator_next(gc, prev, range_lowest): - # Return the "next" valid GC object' address. "prev" is the - # previous result (or the highest end of the shadowstack to start - # with), and "range_lowest" is the lowest end of the shadowstack. - # We enumerating backwards, starting from the higher addresses. - # - while True: + class RootIterator: + _alloc_flavor_ = "raw" + frame_addr = 0 + + def next(iself, gc, prev, range_lowest): + # Return the "next" valid GC object' address. We enumerating + # backwards, starting from the high addresses, until we reach + # the 'range_lowest'. The 'prev' argument is the previous + # result (or the high end of the shadowstack to start with). # - # If we are not iterating right now in a JIT frame - if self._iter_frame_addr == llmemory.NULL: + while True: # - # Look for the previous shadowstack address that contains - # a valid pointer - while prev != range_lowest: - prev -= llmemory.sizeof(llmemory.Address) - if gc.points_to_valid_gc_object(prev): - break + # If we are not iterating right now in a JIT frame + if iself.frame_addr == 0: + # + # Look for the previous shadowstack address that + # contains a valid pointer + while prev != range_lowest: + prev -= llmemory.sizeof(llmemory.Address) + if gc.points_to_valid_gc_object(prev): + break + else: + return llmemory.NULL + # + # Now a "valid" pointer can be either really valid, or + # it can be a pointer to a JIT frame in the stack. The + # important part here is that points_to_valid_gc_object + # above returns True even for a pointer to a MARKER + # (which is word-aligned). + if prev.address[0].signed[0] != self.MARKER: + return prev + # + # It's a JIT frame. Save away 'prev' for later, and + # go into JIT-frame-exploring mode. + iself.saved_prev = prev + frame_addr = prev.signed[0] - self.marker_ofs + iself.frame_addr = frame_addr + addr = llmemory.cast_int_to_adr(frame_addr + + self.force_index_ofs) + 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: - return llmemory.NULL + # Continuing to explore this JIT frame + callshape = iself.callshape # - # Now a "valid" pointer can be either really valid, or it - # can be a pointer to a JIT frame in the stack. The - # important part here is that 'points_to_valid_gc_object' - # above returns True even for a pointer to a MARKER - # (which is word-aligned). - if prev.address[0].signed[0] != self.MARKER: - return prev + # 'callshape' points to the next INT of the callshape. + # If it's zero we are done with the JIT frame. + while callshape[0] != 0: + # + # Non-zero: it's an offset inside the JIT frame. + # Read it and increment 'callshape'. + offset = callshape[0] + callshape = lltype.direct_ptradd(callshape, 1) + addr = llmemory.cast_int_to_adr(iself.frame_addr + + offset) + 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 # - # It's a JIT frame. Save away 'prev' for later, and - # go into JIT-frame-exploring mode. - self._iter_saved_prev = prev - frame_addr = prev.signed[0] - self.marker_ofs - self._iter_frame_addr = frame_addr - addr = llmemory.cast_int_to_adr(frame_addr + - self.force_index_ofs) - 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 = self._iter_callshape - # - # 'callshape' points to the next INT of the callshape. - # If it's zero we are done with the JIT frame. - while callshape[0] != 0: - # - # Non-zero: it's an offset inside the JIT frame. - # Read it and increment 'callshape'. - offset = callshape[0] - callshape = lltype.direct_ptradd(callshape, 1) - addr = llmemory.cast_int_to_adr(self._iter_frame_addr + - offset) - if gc.points_to_valid_gc_object(addr): - # - # The JIT frame contains a valid GC pointer at - # this address (and not e.g. NULL). Save 'callshape' - # for the next call, and return it. - self._iter_callshape = callshape - return addr - # - # Restore 'prev' and loop back to the start. - prev = self._iter_saved_prev - self._iter_frame_addr = llmemory.NULL + # Restore 'prev' and loop back to the start. + prev = iself.saved_prev + iself.frame_addr = 0 # --------------- # jit2gc.update({ - 'root_iterator_setup': iterator_setup, - 'root_iterator_next': iterator_next, + 'root_iterator': RootIterator(), }) def initialize(self): diff --git a/pypy/rpython/memory/gctransform/shadowstack.py b/pypy/rpython/memory/gctransform/shadowstack.py --- a/pypy/rpython/memory/gctransform/shadowstack.py +++ b/pypy/rpython/memory/gctransform/shadowstack.py @@ -28,13 +28,11 @@ translator = gctransformer.translator if hasattr(translator, '_jit2gc'): - iterator_setup = translator._jit2gc['root_iterator_setup'] - iterator_next = translator._jit2gc['root_iterator_next'] + root_iterator = translator._jit2gc['root_iterator'] def jit_walk_stack_root(callback, addr, end): gc = self.gc - iterator_setup() while True: - end = iterator_next(end, addr) + end = root_iterator.next(gc, end, addr) if end == llmemory.NULL: return callback(gc, end) @@ -262,14 +260,13 @@ translator = gctransformer.translator if hasattr(translator, '_jit2gc'): - iterator_setup = translator._jit2gc['root_iterator_setup'] - iterator_next = translator._jit2gc['root_iterator_next'] + gc = gctransformer.gcdata.gc + root_iterator = translator._jit2gc['root_iterator'] def customtrace(obj, prev): if not prev: - iterator_setup() prev = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR).top base = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR).base - return iterator_next(prev, base) + return root_iterator.next(gc, prev, base) else: def customtrace(obj, prev): # a simple but not JIT-ready version _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit