Author: Antonio Cuni <[email protected]>
Branch: invalidate-virtualrefs
Changeset: r44481:d866dcaad5cb
Date: 2011-05-25 15:31 +0200
http://bitbucket.org/pypy/pypy/changeset/d866dcaad5cb/

Log:    make sure that the frame vref is forced when we call sys._getframe()

diff --git a/pypy/interpreter/executioncontext.py 
b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -63,9 +63,18 @@
             if self.profilefunc:
                 self._trace(frame, 'leaveframe', w_exitvalue)
         finally:
-            vref = self.topframeref
+            frame_vref = self.topframeref
             self.topframeref = frame.f_backref
-            jit.virtual_ref_finish(vref, frame)
+            if frame.escaped:
+                # if this frame escaped to applevel, we must ensure that also
+                # f_back does
+                f_back = frame.f_backref()
+                if f_back:
+                    f_back.escaped = True
+                # force the frame (from the JIT point of view), so that it can
+                # be accessed also later
+                frame_vref()
+            jit.virtual_ref_finish(frame_vref, frame)
 
         if self.w_tracefunc is not None and not frame.hide():
             self.space.frame_trace_action.fire()
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -49,6 +49,7 @@
     instr_ub                 = 0
     instr_prev_plus_one      = 0
     is_being_profiled        = False
+    escaped                  = False  # see mark_as_escaped()
 
     def __init__(self, space, code, w_globals, closure):
         self = hint(self, access_directly=True, fresh_virtualizable=True)
@@ -67,6 +68,15 @@
         make_sure_not_resized(self.fastlocals_w)
         self.f_lineno = code.co_firstlineno
 
+    def mark_as_escaped(self):
+        """
+        Must be called on frames that are exposed to applevel, e.g. by
+        sys._getframe().  This ensures that the virtualref holding the frame
+        is properly forced by ec.leave(), and thus the frame will be still
+        accessible even after the corresponding C stack is died.
+        """
+        self.escaped = True
+
     def append_block(self, block):
         block.previous = self.lastblock
         self.lastblock = block
diff --git a/pypy/interpreter/test/test_pyframe.py 
b/pypy/interpreter/test/test_pyframe.py
--- a/pypy/interpreter/test/test_pyframe.py
+++ b/pypy/interpreter/test/test_pyframe.py
@@ -98,6 +98,15 @@
             return sys._getframe().f_back.f_code.co_name 
         f()
 
+    def test_f_back_virtualref(self):
+        import sys
+        def f():
+            return g()
+        def g():
+            return sys._getframe()
+        frame = f()
+        assert frame.f_back.f_code.co_name == 'f'
+
     def test_f_exc_xxx(self):
         import sys
 
diff --git a/pypy/module/sys/vm.py b/pypy/module/sys/vm.py
--- a/pypy/module/sys/vm.py
+++ b/pypy/module/sys/vm.py
@@ -40,6 +40,7 @@
             break
         depth -= 1
         f = ec.getnextframe_nohidden(f)
+    f.mark_as_escaped()
     return space.wrap(f)
 
 def setrecursionlimit(space, w_new_limit):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to