this is messy enough that it really need unit tests, we don't have enough other tests to be sure they check what's going on here.
[email protected] wrote: > Author: cfbolz > Date: Wed Sep 2 17:53:35 2009 > New Revision: 67433 > > Modified: > pypy/branch/spine-of-frames/pypy/interpreter/executioncontext.py > pypy/branch/spine-of-frames/pypy/interpreter/generator.py > pypy/branch/spine-of-frames/pypy/interpreter/pyframe.py > pypy/branch/spine-of-frames/pypy/interpreter/pytraceback.py > pypy/branch/spine-of-frames/pypy/interpreter/test/test_zzpickle_and_slow.py > pypy/branch/spine-of-frames/pypy/module/sys/test/test_sysmodule.py > pypy/branch/spine-of-frames/pypy/module/sys/vm.py > Log: > try to have frames not escape via the f_backs of the next "real" frame. > > > Modified: pypy/branch/spine-of-frames/pypy/interpreter/executioncontext.py > ============================================================================== > --- pypy/branch/spine-of-frames/pypy/interpreter/executioncontext.py > (original) > +++ pypy/branch/spine-of-frames/pypy/interpreter/executioncontext.py Wed Sep > 2 17:53:35 2009 > @@ -40,13 +40,13 @@ > def gettopframe_nohidden(self): > frame = self.gettopframe() > while frame and frame.hide(): > - frame = frame.f_back > + frame = frame.f_back() > return frame > > def getnextframe_nohidden(frame): > - frame = frame.f_back > + frame = frame.f_back() > while frame and frame.hide(): > - frame = frame.f_back > + frame = frame.f_back() > return frame > getnextframe_nohidden = staticmethod(getnextframe_nohidden) > > @@ -56,8 +56,8 @@ > self.space.wrap("maximum recursion depth > exceeded")) > self.framestackdepth += 1 > # > + frame.f_back_some = self.some_frame > curtopframe = self.gettopframe() > - frame.f_back = curtopframe > if curtopframe is not None: > curtopframe.f_forward = frame > if not we_are_jitted(): > @@ -68,11 +68,11 @@ > self._trace(frame, 'leaveframe', self.space.w_None) > > #assert frame is self.gettopframe() --- slowish > - f_back = frame.f_back > + f_back = frame.f_back() > if f_back is not None: > f_back.f_forward = None > if not we_are_jitted() or self.some_frame is frame: > - self.some_frame = f_back > + self.some_frame = frame.f_back_some > self.framestackdepth -= 1 > > if self.w_tracefunc is not None and not frame.hide(): > @@ -134,7 +134,7 @@ > while index > 0: > index -= 1 > lst[index] = f > - f = f.f_back > + f = f.f_back() > assert f is None > return lst > # coroutine: I think this is all, folks! > > Modified: pypy/branch/spine-of-frames/pypy/interpreter/generator.py > ============================================================================== > --- pypy/branch/spine-of-frames/pypy/interpreter/generator.py (original) > +++ pypy/branch/spine-of-frames/pypy/interpreter/generator.py Wed Sep 2 > 17:53:35 2009 > @@ -64,7 +64,7 @@ > else: > return w_result # YIELDed > finally: > - self.frame.f_back = None > + self.frame.f_back_some = None > self.running = False > > def descr_throw(self, w_type, w_val=None, w_tb=None): > > Modified: pypy/branch/spine-of-frames/pypy/interpreter/pyframe.py > ============================================================================== > --- pypy/branch/spine-of-frames/pypy/interpreter/pyframe.py (original) > +++ pypy/branch/spine-of-frames/pypy/interpreter/pyframe.py Wed Sep 2 > 17:53:35 2009 > @@ -33,14 +33,49 @@ > * 'builtin' is the attached built-in module > * 'valuestack_w', 'blockstack', control the interpretation > """ > + > + """ > + explanation of the f_back handling: > + ----------------------------------- > + > + in the non-JIT case, the frames simply form a doubly linked list via the > + attributes f_back_some and f_forward. > + > + When the JIT is used, things become more complex, as functions can be > + inlined into each other. In this case a frame chain can look like this: > + > + +---------------+ > + | real_frame | > + +---------------+ > + | ^ > + | f_back_some > + | | > + | | f_forward > + | +--------------+ > + | | virtual frame| > + | +--------------+ > + | ^ > + | | f_forward > + | +--------------+ > + | | virtual frame| > + | +--------------+ > + | ^ > + | | > + v | f_forward > + +---------------+ > + | real_frame | > + +---------------+ > + > + """ > > __metaclass__ = extendabletype > > frame_finished_execution = False > last_instr = -1 > last_exception = None > - f_back = None # these two should be modified > together > - f_forward = None # they make a doubly-linked list > + f_back_some = None # these two should be modified > together > + f_forward = None # they make a sort of doubly-linked > list > + f_back_forced = False > w_f_trace = None > # For tracing > instr_lb = 0 > @@ -286,7 +321,7 @@ > w_tb = w(self.last_exception.application_traceback) > > tup_state = [ > - w(self.f_back), > + w(self.f_back()), > w(self.get_builtin()), > w(self.pycode), > w_valuestack, > @@ -338,7 +373,9 @@ > # do not use the instance's __init__ but the base's, because we set > # everything like cells from here > PyFrame.__init__(self, space, pycode, w_globals, closure) > - new_frame.f_back = space.interp_w(PyFrame, w_f_back, > can_be_None=True) > + new_frame.f_back_some = space.interp_w(PyFrame, w_f_back, > can_be_None=True) > + new_frame.f_back_forced = True > + > new_frame.builtin = space.interp_w(Module, w_builtin) > new_frame.blockstack = [unpickle_block(space, w_blk) > for w_blk in > space.unpackiterable(w_blockstack)] > @@ -407,6 +444,25 @@ > def _setcellvars(self, cellvars): > pass > > + def f_back(self): > + back_some = self.f_back_some > + if self.f_back_forced: > + # don't check back_some.f_forward in this case > + return back_some > + if back_some is None: > + return None > + while back_some.f_forward is not self: > + back_some = back_some.f_forward > + return back_some > + > + def force_f_back(self): > + self.f_back_some = f_back = self.f_back() > + self.f_back_forced = True > + if f_back is not None: > + f_back.force_f_back() > + return f_back > + > + > ### line numbers ### > > # for f*_f_* unwrapping through unwrap_spec in typedef.py > @@ -550,7 +606,7 @@ > return self.get_builtin().getdict() > > def fget_f_back(space, self): > - return self.space.wrap(self.f_back) > + return self.space.wrap(self.f_back()) > > def fget_f_lasti(space, self): > return self.space.wrap(self.last_instr) > @@ -571,27 +627,27 @@ > > def fget_f_exc_type(space, self): > if self.last_exception is not None: > - f = self.f_back > + f = self.f_back() > while f is not None and f.last_exception is None: > - f = f.f_back > + f = f.f_back() > if f is not None: > return f.last_exception.w_type > return space.w_None > > def fget_f_exc_value(space, self): > if self.last_exception is not None: > - f = self.f_back > + f = self.f_back() > while f is not None and f.last_exception is None: > - f = f.f_back > + f = f.f_back() > if f is not None: > return f.last_exception.w_value > return space.w_None > > def fget_f_exc_traceback(space, self): > if self.last_exception is not None: > - f = self.f_back > + f = self.f_back() > while f is not None and f.last_exception is None: > - f = f.f_back > + f = f.f_back() > if f is not None: > return space.wrap(f.last_exception.application_traceback) > return space.w_None > > Modified: pypy/branch/spine-of-frames/pypy/interpreter/pytraceback.py > ============================================================================== > --- pypy/branch/spine-of-frames/pypy/interpreter/pytraceback.py > (original) > +++ pypy/branch/spine-of-frames/pypy/interpreter/pytraceback.py Wed Sep > 2 17:53:35 2009 > @@ -46,6 +46,7 @@ > self.next = space.interp_w(PyTraceback, w_next, can_be_None=True) > > def record_application_traceback(space, operror, frame, last_instruction): > + frame.force_f_back() > if frame.pycode.hidden_applevel: > return > lineno = offset2lineno(frame.pycode, last_instruction) > > Modified: > pypy/branch/spine-of-frames/pypy/interpreter/test/test_zzpickle_and_slow.py > ============================================================================== > --- > pypy/branch/spine-of-frames/pypy/interpreter/test/test_zzpickle_and_slow.py > (original) > +++ > pypy/branch/spine-of-frames/pypy/interpreter/test/test_zzpickle_and_slow.py > Wed Sep 2 17:53:35 2009 > @@ -30,18 +30,23 @@ > from pypy.interpreter import pytraceback > def hide_top_frame(space, w_frame): > w_last = None > - while w_frame.f_back: > + while w_frame.f_back(): > + # should have been forced by traceback capturing > + assert w_frame.f_back_forced > w_last = w_frame > - w_frame = w_frame.f_back > + w_frame = w_frame.f_back() > assert w_last > - w_saved = w_last.f_back > - w_last.f_back = None > + w_saved = w_last.f_back() > + w_last.f_back_some = None > + w_saved.f_forward = None > return w_saved > > def restore_top_frame(space, w_frame, w_saved): > - while w_frame.f_back: > - w_frame = w_frame.f_back > - w_frame.f_back = w_saved > + while w_frame.f_back(): > + assert w_frame.f_back_forced > + w_frame = w_frame.f_back() > + w_frame.f_back_some = w_saved > + w_saved.f_forward = w_frame > > def read_exc_type(space, w_frame): > if w_frame.last_exception is None: > > Modified: pypy/branch/spine-of-frames/pypy/module/sys/test/test_sysmodule.py > ============================================================================== > --- pypy/branch/spine-of-frames/pypy/module/sys/test/test_sysmodule.py > (original) > +++ pypy/branch/spine-of-frames/pypy/module/sys/test/test_sysmodule.py > Wed Sep 2 17:53:35 2009 > @@ -337,6 +337,16 @@ > # is sys._getframe().f_code > #) > > + def test_getframe_in_returned_func(self): > + def f(): > + return g() > + def g(): > + return sys._getframe(0) > + frame = f() > + assert frame.f_code.co_name == 'g' > + assert frame.f_back.f_code.co_name == 'f' > + assert frame.f_back.f_back.f_code.co_name == > 'test_getframe_in_returned_func' > + > def test_attributes(self): > assert sys.__name__ == 'sys' > assert isinstance(sys.modules, dict) > > Modified: pypy/branch/spine-of-frames/pypy/module/sys/vm.py > ============================================================================== > --- pypy/branch/spine-of-frames/pypy/module/sys/vm.py (original) > +++ pypy/branch/spine-of-frames/pypy/module/sys/vm.py Wed Sep 2 17:53:35 2009 > @@ -31,6 +31,7 @@ > space.wrap("frame index must not be negative")) > ec = space.getexecutioncontext() > f = ec.gettopframe_nohidden() > + f.force_f_back() > while True: > if f is None: > raise OperationError(space.w_ValueError, > _______________________________________________ > pypy-svn mailing list > [email protected] > http://codespeak.net/mailman/listinfo/pypy-svn > _______________________________________________ [email protected] http://codespeak.net/mailman/listinfo/pypy-dev
