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