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

Reply via email to