Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
524b9284
Commit
524b9284
authored
May 01, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add frame.f_back support
parent
4870b92b
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
72 additions
and
14 deletions
+72
-14
src/codegen/unwinding.cpp
src/codegen/unwinding.cpp
+23
-0
src/codegen/unwinding.h
src/codegen/unwinding.h
+5
-1
src/runtime/frame.cpp
src/runtime/frame.cpp
+29
-13
test/tests/sys_getframe.py
test/tests/sys_getframe.py
+15
-0
No files found.
src/codegen/unwinding.cpp
View file @
524b9284
...
...
@@ -907,6 +907,29 @@ PythonFrameIterator PythonFrameIterator::getCurrentVersion() {
return
PythonFrameIterator
(
std
::
move
(
rtn
));
}
PythonFrameIterator
PythonFrameIterator
::
back
()
{
// TODO this is ineffecient: the iterator is no longer valid for libunwind iteration, so
// we have to do a full stack crawl again.
// Hopefully examination of f_back is uncommon.
std
::
unique_ptr
<
PythonFrameIteratorImpl
>
rtn
(
nullptr
);
auto
&
impl
=
this
->
impl
;
bool
found
=
false
;
unwindPythonStack
([
&
](
std
::
unique_ptr
<
PythonFrameIteratorImpl
>
frame_iter
)
{
if
(
found
)
{
rtn
=
std
::
move
(
frame_iter
);
return
true
;
}
if
(
frame_iter
->
pointsToTheSameAs
(
*
impl
.
get
()))
found
=
true
;
return
false
;
});
RELEASE_ASSERT
(
found
,
"this wasn't a valid frame?"
);
return
PythonFrameIterator
(
std
::
move
(
rtn
));
}
llvm
::
JITEventListener
*
makeTracebacksListener
()
{
return
new
TracebacksEventListener
();
}
...
...
src/codegen/unwinding.h
View file @
524b9284
...
...
@@ -58,10 +58,14 @@ public:
// the iterator was obtained, the methods may return old values. This returns
// an updated copy that returns the updated values.
// The "current version" will live at the same stack location, but any other
// similarities need to be verified by the caller.
// similarities need to be verified by the caller, ie it is up to the caller
// to determine that we didn't leave and reenter the stack frame.
// This function can only be called from the thread that created this object.
PythonFrameIterator
getCurrentVersion
();
// Assuming this is a valid frame iterator, return the next frame back (ie older).
PythonFrameIterator
back
();
PythonFrameIterator
(
PythonFrameIterator
&&
rhs
);
void
operator
=
(
PythonFrameIterator
&&
rhs
);
PythonFrameIterator
(
std
::
unique_ptr
<
PythonFrameIteratorImpl
>
impl
);
...
...
src/runtime/frame.cpp
View file @
524b9284
...
...
@@ -27,10 +27,12 @@ BoxedClass* frame_cls;
// - breaks c++ exceptions
// - we never free the trampolines
class
BoxedFrame
:
public
Box
{
public:
BoxedFrame
(
PythonFrameIterator
&&
it
)
__attribute__
((
visibility
(
"default"
)))
private:
// Call boxFrame to get a BoxedFrame object.
BoxedFrame
(
PythonFrameIterator
it
)
__attribute__
((
visibility
(
"default"
)))
:
it
(
std
::
move
(
it
)),
thread_id
(
PyThread_get_thread_ident
())
{}
public:
PythonFrameIterator
it
;
long
thread_id
;
...
...
@@ -105,6 +107,16 @@ public:
return
f
->
_globals
;
}
static
Box
*
back
(
Box
*
obj
,
void
*
)
{
auto
f
=
static_cast
<
BoxedFrame
*>
(
obj
);
f
->
update
();
PythonFrameIterator
it
=
f
->
it
.
back
();
if
(
!
it
.
exists
())
return
None
;
return
BoxedFrame
::
boxFrame
(
std
::
move
(
it
));
}
static
Box
*
lineno
(
Box
*
obj
,
void
*
)
{
auto
f
=
static_cast
<
BoxedFrame
*>
(
obj
);
f
->
update
();
...
...
@@ -113,6 +125,19 @@ public:
}
DEFAULT_CLASS
(
frame_cls
);
static
Box
*
boxFrame
(
PythonFrameIterator
it
)
{
FrameInfo
*
fi
=
it
.
getFrameInfo
();
if
(
fi
->
frame_obj
==
NULL
)
{
auto
cf
=
it
.
getCF
();
BoxedFrame
*
f
=
fi
->
frame_obj
=
new
BoxedFrame
(
std
::
move
(
it
));
assert
(
cf
->
clfunc
->
source
->
scoping
->
areGlobalsFromModule
());
f
->
_globals
=
cf
->
clfunc
->
source
->
parent_module
->
getAttrWrapper
();
f
->
_code
=
codeForCLFunction
(
cf
->
clfunc
);
}
return
fi
->
frame_obj
;
}
};
Box
*
getFrame
(
int
depth
)
{
...
...
@@ -120,19 +145,9 @@ Box* getFrame(int depth) {
if
(
!
it
.
exists
())
return
NULL
;
FrameInfo
*
fi
=
it
.
getFrameInfo
();
if
(
fi
->
frame_obj
==
NULL
)
{
auto
cf
=
it
.
getCF
();
BoxedFrame
*
f
=
fi
->
frame_obj
=
new
BoxedFrame
(
std
::
move
(
it
));
assert
(
cf
->
clfunc
->
source
->
scoping
->
areGlobalsFromModule
());
f
->
_globals
=
cf
->
clfunc
->
source
->
parent_module
->
getAttrWrapper
();
f
->
_code
=
codeForCLFunction
(
cf
->
clfunc
);
}
return
fi
->
frame_obj
;
return
BoxedFrame
::
boxFrame
(
std
::
move
(
it
));
}
void
setupFrame
()
{
frame_cls
=
BoxedHeapClass
::
create
(
type_cls
,
object_cls
,
&
BoxedFrame
::
gchandler
,
0
,
0
,
sizeof
(
BoxedFrame
),
false
,
"frame"
);
...
...
@@ -143,6 +158,7 @@ void setupFrame() {
frame_cls
->
giveAttr
(
"f_lineno"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedFrame
::
lineno
,
NULL
,
NULL
));
frame_cls
->
giveAttr
(
"f_globals"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedFrame
::
globals
,
NULL
,
NULL
));
frame_cls
->
giveAttr
(
"f_back"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedFrame
::
back
,
NULL
,
NULL
));
frame_cls
->
freeze
();
}
...
...
test/tests/sys_getframe.py
View file @
524b9284
...
...
@@ -72,3 +72,18 @@ assert sys._getframe(0).f_globals is globals()
def
f5
():
assert
sys
.
_getframe
(
0
).
f_globals
is
globals
()
f5
()
# A number of libraries have functions like this:
def
get_main_module
():
f
=
sys
.
_getframe
(
1
)
while
f
.
f_locals
is
not
globals
():
print
f
.
f_code
.
co_filename
,
f
.
f_lineno
,
sorted
(
f
.
f_locals
.
items
())
f
=
f
.
f_back
print
"Main module currently at:"
,
f
.
f_code
.
co_filename
,
f
.
f_lineno
print
"f_back:"
,
f
.
f_back
def
f6
(
n
):
if
n
:
f6
(
n
-
1
)
else
:
get_main_module
()
f6
(
10
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment