[pypy-dev] [pypy-svn] r67433 - in pypy/branch/spine-of-frames/pypy: interpreter interpreter/test module/sys module/sys/test

Samuele Pedroni pedronis at openend.se
Wed Sep 2 20:17:36 CEST 2009


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.

cfbolz at codespeak.net 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
> pypy-svn at codespeak.net
> http://codespeak.net/mailman/listinfo/pypy-svn
>   




More information about the Pypy-dev mailing list