Commit a81ec92d authored by Kevin Modzelewski's avatar Kevin Modzelewski

Refactor and rewrite a bunch of the unwinding code

The first change is to move to a PIMPL strategy so that
we can provide a more extensive unwinding API to other modules.
In particular, you can get access to a python frame iterator
and make repeated calls on it.  This is in preparation of the
sys._getframe implementation.

This also exposed an issue with our usage of libunwind -- basically
you have to do all of your unwinding in one function, but we were
doing it in several different functions and happening to get away
with it.  So, switch from a C++11 range-for loop which is nicer, to
a callback approach which is less nice in my opinion, but safer.
parent 62794865
...@@ -54,6 +54,12 @@ const int dwarf_to_gp[] = { ...@@ -54,6 +54,12 @@ const int dwarf_to_gp[] = {
// 17-32: xmm0-xmm15 // 17-32: xmm0-xmm15
}; };
Register Register::fromDwarf(int dwarf_regnum) {
assert(dwarf_regnum >= 0 && dwarf_regnum <= 16);
return Register(dwarf_to_gp[dwarf_regnum]);
}
GenericRegister GenericRegister::fromDwarf(int dwarf_regnum) { GenericRegister GenericRegister::fromDwarf(int dwarf_regnum) {
assert(dwarf_regnum >= 0); assert(dwarf_regnum >= 0);
......
...@@ -45,6 +45,8 @@ struct Register { ...@@ -45,6 +45,8 @@ struct Register {
bool operator!=(const Register& rhs) const { return !(*this == rhs); } bool operator!=(const Register& rhs) const { return !(*this == rhs); }
void dump() const; void dump() const;
static Register fromDwarf(int dwarf_regnum);
}; };
const Register RAX(0); const Register RAX(0);
......
This diff is collapsed.
...@@ -33,19 +33,47 @@ Box* getGlobalsDict(); // always returns a dict-like object ...@@ -33,19 +33,47 @@ Box* getGlobalsDict(); // always returns a dict-like object
BoxedTraceback* getTraceback(); BoxedTraceback* getTraceback();
struct ExecutionPoint {
CompiledFunction* cf;
AST_stmt* current_stmt;
};
ExecutionPoint getExecutionPoint();
// Adds stack locals and closure locals into the locals dict, and returns it. // Adds stack locals and closure locals into the locals dict, and returns it.
Box* fastLocalsToBoxedLocals(); Box* fastLocalsToBoxedLocals();
class PythonFrameIteratorImpl;
class PythonFrameIterator {
private:
std::unique_ptr<PythonFrameIteratorImpl> impl;
public:
CompiledFunction* getCF();
FrameInfo* getFrameInfo();
bool exists() { return impl.get() != NULL; }
std::unique_ptr<ExecutionPoint> getExecutionPoint();
Box* fastLocalsToBoxedLocals();
// Gets the "current version" of this frame: if the frame has executed since
// 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.
// This function can only be called from the thread that created this object.
PythonFrameIterator getCurrentVersion();
PythonFrameIterator(PythonFrameIterator&& rhs);
void operator=(PythonFrameIterator&& rhs);
PythonFrameIterator(std::unique_ptr<PythonFrameIteratorImpl>&& impl);
~PythonFrameIterator();
};
PythonFrameIterator getPythonFrame(int depth);
// Fetches a writeable pointer to the frame-local excinfo object, // Fetches a writeable pointer to the frame-local excinfo object,
// calculating it if necessary (from previous frames). // calculating it if necessary (from previous frames).
ExcInfo* getFrameExcInfo(); ExcInfo* getFrameExcInfo();
struct ExecutionPoint {
CompiledFunction* cf;
AST_stmt* current_stmt;
};
ExecutionPoint getExecutionPoint();
struct FrameStackState { struct FrameStackState {
// This includes all # variables (but not the ! ones). // This includes all # variables (but not the ! ones).
// Therefore, it's not the same as the BoxedLocals. // Therefore, it's not the same as the BoxedLocals.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment