Skip to content

Commit

Permalink
WIP: switch to cpython traceback
Browse files Browse the repository at this point in the history
  • Loading branch information
undingen committed Feb 10, 2016
1 parent d634f5a commit 9d22da2
Show file tree
Hide file tree
Showing 17 changed files with 72 additions and 232 deletions.
1 change: 1 addition & 0 deletions from_cpython/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ file(GLOB_RECURSE STDOBJECT_SRCS Objects
memoryobject.c
stringobject.c
structseq.c
traceback.c
unicodectype.c
unicodeobject.c
weakrefobject.c
Expand Down
2 changes: 2 additions & 0 deletions from_cpython/Include/code.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ PyAPI_FUNC(int) PyCode_Addr2Line(PyCodeObject *, int) PYSTON_NOEXCEPT;

// Pyston addition:
PyAPI_FUNC(int) PyCode_GetArgCount(PyCodeObject *) PYSTON_NOEXCEPT;
PyAPI_FUNC(PyObject*) PyCode_GetFilename(PyCodeObject *) PYSTON_NOEXCEPT;
PyAPI_FUNC(PyObject*) PyCode_GetName(PyCodeObject *) PYSTON_NOEXCEPT;

/* for internal use only */
#define _PyCode_GETCODEPTR(co, pp) \
Expand Down
8 changes: 7 additions & 1 deletion from_cpython/Include/frameobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,18 @@ PyAPI_FUNC(void) PyFrame_FastToLocals(PyFrameObject *);
PyAPI_FUNC(int) PyFrame_ClearFreeList(void);
#endif

typedef struct _PyFrameObject PyFrameObject;
typedef struct _frame PyFrameObject;

PyAPI_DATA(PyTypeObject*) frame_cls;
#define PyFrame_Type (*frame_cls)
#define PyFrame_Check(op) (((PyObject*)op)->ob_type == &PyFrame_Type)

/* Return the line of code the frame is currently executing. */
PyAPI_FUNC(int) PyFrame_GetLineNumber(PyFrameObject *) PYSTON_NOEXCEPT;
// Pyston changes: add a function to get globals
PyAPI_FUNC(PyObject *) PyFrame_GetGlobals(PyFrameObject *) PYSTON_NOEXCEPT;
// Pyston changes: add a function to get the code object
PyAPI_FUNC(PyObject *) PyFrame_GetCode(PyFrameObject *) PYSTON_NOEXCEPT;
// Pyston changes: add a function to get frame object by level
PyAPI_FUNC(PyFrameObject *) PyFrame_ForStackLevel(int stack_level) PYSTON_NOEXCEPT;

Expand Down
9 changes: 1 addition & 8 deletions from_cpython/Include/traceback.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,20 @@ struct _frame;

/* Traceback interface */

// Pyston change: not necessarily our object format
#if 0
typedef struct _traceback {
PyObject_HEAD
struct _traceback *tb_next;
struct _frame *tb_frame;
int tb_lasti;
int tb_lineno;
} PyTracebackObject;
#endif
typedef struct _PyTracebackObject PyTracebackObject;

PyAPI_FUNC(int) PyTraceBack_Here(struct _frame *) PYSTON_NOEXCEPT;
PyAPI_FUNC(int) PyTraceBack_Print(PyObject *, PyObject *) PYSTON_NOEXCEPT;
PyAPI_FUNC(int) _Py_DisplaySourceLine(PyObject *, const char *, int, int) PYSTON_NOEXCEPT;

/* Reveal traceback type so we can typecheck traceback objects */
// Pyston change: not a static type any more
PyAPI_DATA(PyTypeObject*) traceback_cls;
#define PyTraceBack_Type (*traceback_cls)
// PyAPI_DATA(PyTypeObject) PyTraceBack_Type;
PyAPI_DATA(PyTypeObject) PyTraceBack_Type;
#define PyTraceBack_Check(v) (Py_TYPE(v) == &PyTraceBack_Type)

#ifdef __cplusplus
Expand Down
19 changes: 16 additions & 3 deletions from_cpython/Python/traceback.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// This file is originally from CPython 2.7, with modifications for Pyston

/* Traceback implementation */

Expand Down Expand Up @@ -46,7 +47,9 @@ tb_clear(PyTracebackObject *tb)
}

PyTypeObject PyTraceBack_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
// Pyston change:
// PyVarObject_HEAD_INIT(&PyType_Type, 0)
PyVarObject_HEAD_INIT(NULL, 0)
"traceback",
sizeof(PyTracebackObject),
0,
Expand Down Expand Up @@ -94,8 +97,10 @@ newtracebackobject(PyTracebackObject *next, PyFrameObject *frame)
Py_XINCREF(next);
tb->tb_next = next;
Py_XINCREF(frame);
tb->tb_frame = frame;
tb->tb_lasti = frame->f_lasti;
tb->tb_frame = (struct _frame *)frame;
// Pyston change: we don't have tb_lasti
// tb->tb_lasti = frame->f_lasti;
tb->tb_lasti = -1;
tb->tb_lineno = PyFrame_GetLineNumber(frame);
PyObject_GC_Track(tb);
}
Expand Down Expand Up @@ -244,11 +249,19 @@ tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
}
while (tb != NULL && err == 0) {
if (depth <= limit) {
/*
// Pyston change: we can't directly access the fields
err = tb_displayline(f,
PyString_AsString(
tb->tb_frame->f_code->co_filename),
tb->tb_lineno,
PyString_AsString(tb->tb_frame->f_code->co_name));
*/
PyCodeObject* code = (PyCodeObject*)PyFrame_GetCode(tb->tb_frame);
err = tb_displayline(f,
PyString_AsString(PyCode_GetFilename(code)),
tb->tb_lineno,
PyString_AsString(PyCode_GetName(code)));
}
depth--;
tb = tb->tb_next;
Expand Down
1 change: 0 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ add_library(PYSTON_OBJECTS OBJECT ${OPTIONAL_SRCS}
runtime/set.cpp
runtime/str.cpp
runtime/super.cpp
runtime/traceback.cpp
runtime/tuple.cpp
runtime/types.cpp
runtime/util.cpp
Expand Down
39 changes: 18 additions & 21 deletions src/codegen/unwinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
#include "runtime/ctxswitching.h"
#include "runtime/objmodel.h"
#include "runtime/generator.h"
#include "runtime/traceback.h"
#include "runtime/types.h"


Expand Down Expand Up @@ -698,6 +697,7 @@ template <typename Func> void unwindPythonStack(Func func) {
//
// 4. Unless we've hit the end of the stack, go to 2 and keep unwinding.
//
/*
static StatCounter us_gettraceback("us_gettraceback");
Box* getTraceback() {
STAT_TIMER(t0, "us_timer_gettraceback", 20);
Expand Down Expand Up @@ -730,7 +730,7 @@ Box* getTraceback() {
us_gettraceback.log(us);
return static_cast<BoxedTraceback*>(tb);
}
}*/

ExcInfo* getFrameExcInfo() {
std::vector<ExcInfo*> to_update;
Expand Down Expand Up @@ -1061,7 +1061,7 @@ void _printStacktrace() {
}

recursive = true;
printTraceback(getTraceback());
// printTraceback(getTraceback());
recursive = false;
}

Expand All @@ -1076,26 +1076,23 @@ extern "C" void abort() {
Stats::dump();
fprintf(stderr, "Someone called abort!\n");

// If traceback_cls is NULL, then we somehow died early on, and won't be able to display a traceback.
if (traceback_cls) {

// If we call abort(), things may be seriously wrong. Set an alarm() to
// try to handle cases that we would just hang.
// (Ex if we abort() from a static constructor, and _printStackTrace uses
// that object, _printStackTrace will hang waiting for the first construction
// to finish.)
alarm(1);
try {
_printStacktrace();
} catch (ExcInfo) {
fprintf(stderr, "error printing stack trace during abort()");
}

// Cancel the alarm.
// This is helpful for when running in a debugger, since otherwise the debugger will catch the
// abort and let you investigate, but the alarm will still come back to kill the program.
alarm(0);
// If we call abort(), things may be seriously wrong. Set an alarm() to
// try to handle cases that we would just hang.
// (Ex if we abort() from a static constructor, and _printStackTrace uses
// that object, _printStackTrace will hang waiting for the first construction
// to finish.)
alarm(1);
try {
_printStacktrace();
} catch (ExcInfo) {
fprintf(stderr, "error printing stack trace during abort()");
}

// Cancel the alarm.
// This is helpful for when running in a debugger, since otherwise the debugger will catch the
// abort and let you investigate, but the alarm will still come back to kill the program.
alarm(0);
}

if (PAUSE_AT_ABORT) {
Expand Down
3 changes: 0 additions & 3 deletions src/codegen/unwinding.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ namespace pyston {
class Box;
class BoxedDict;
class BoxedModule;
class BoxedTraceback;
struct FrameInfo;

void registerDynamicEhFrame(uint64_t code_addr, size_t code_size, uint64_t eh_frame_addr, size_t eh_frame_size);
Expand All @@ -39,8 +38,6 @@ Box* getGlobals(); // returns either the module or a globals dict
Box* getGlobalsDict(); // always returns a dict-like object
CompiledFunction* getCFForAddress(uint64_t addr);

Box* getTraceback();

class PythonUnwindSession;
PythonUnwindSession* beginPythonUnwindSession();
PythonUnwindSession* getActivePythonUnwindSession();
Expand Down
8 changes: 0 additions & 8 deletions src/runtime/capi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
#include "runtime/import.h"
#include "runtime/objmodel.h"
#include "runtime/rewrite_args.h"
#include "runtime/traceback.h"
#include "runtime/types.h"

namespace pyston {
Expand Down Expand Up @@ -931,13 +930,6 @@ extern "C" PyObject* PyExceptionInstance_Class(PyObject* o) noexcept {
return PyInstance_Check(o) ? (Box*)static_cast<BoxedInstance*>(o)->inst_cls : o->cls;
}

extern "C" int PyTraceBack_Print(PyObject* v, PyObject* f) noexcept {
RELEASE_ASSERT(f->cls == &PyFile_Type && ((PyFileObject*)f)->f_fp == stderr,
"sorry will only print tracebacks to stderr right now");
printTraceback(v);
return 0;
}

#define Py_DEFAULT_RECURSION_LIMIT 1000
static int recursion_limit = Py_DEFAULT_RECURSION_LIMIT;
extern "C" {
Expand Down
9 changes: 9 additions & 0 deletions src/runtime/code.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ extern "C" int PyCode_GetArgCount(PyCodeObject* op) noexcept {
return unboxInt(BoxedCode::argcount((Box*)op, NULL));
}

extern "C" PyObject* PyCode_GetFilename(PyCodeObject* op) noexcept {
RELEASE_ASSERT(PyCode_Check((Box*)op), "");
return BoxedCode::filename((Box*)op, NULL);
}
extern "C" PyObject* PyCode_GetName(PyCodeObject* op) noexcept {
RELEASE_ASSERT(PyCode_Check((Box*)op), "");
return BoxedCode::name((Box*)op, NULL);
}

void setupCode() {
code_cls = BoxedClass::create(type_cls, object_cls, &BoxedCode::gcHandler, 0, 0, sizeof(BoxedCode), false, "code",
false);
Expand Down
1 change: 0 additions & 1 deletion src/runtime/cxx_unwind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
#include "core/types.h" // for ExcInfo
#include "core/util.h" // Timer
#include "runtime/generator.h" // generatorEntry
#include "runtime/traceback.h" // BoxedTraceback::addLine

#define UNW_LOCAL_ONLY
#include <libunwind.h>
Expand Down
15 changes: 11 additions & 4 deletions src/runtime/exceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include "core/ast.h"
#include "core/options.h"
#include "runtime/objmodel.h"
#include "runtime/traceback.h"
#include "runtime/types.h"
#include "runtime/util.h"

Expand Down Expand Up @@ -51,7 +50,8 @@ void raiseSyntaxError(const char* msg, int lineno, int col_offset, llvm::StringR
} else {
// This is more like how the parser handles it:
exc = runtimeCall(SyntaxError, ArgPassSpec(1), boxString(msg), NULL, NULL, NULL, NULL);
tb = new BoxedTraceback(LineInfo(lineno, col_offset, boxString(file), boxString(func)), None, getFrame(0));
// tb = new BoxedTraceback(LineInfo(lineno, col_offset, boxString(file), boxString(func)), None, getFrame(0));
// tb = PyTraceBack_Here();
}

assert(!PyErr_Occurred());
Expand Down Expand Up @@ -298,8 +298,15 @@ bool exceptionAtLineCheck() {
}

void exceptionAtLine(LineInfo line_info, Box** traceback) {
if (exceptionAtLineCheck())
BoxedTraceback::here(line_info, traceback, getFrame((FrameInfo*)cur_thread_state.frame_info));
if (exceptionAtLineCheck()) {
PyObject* old = cur_thread_state.curexc_traceback;
if (*traceback == None)
*traceback = NULL;
cur_thread_state.curexc_traceback = *traceback;
PyTraceBack_Here((struct _frame*)getFrame((FrameInfo*)cur_thread_state.frame_info));
*traceback = cur_thread_state.curexc_traceback;
cur_thread_state.curexc_traceback = old;
}
}

void startReraise() {
Expand Down
5 changes: 5 additions & 0 deletions src/runtime/frame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@

namespace pyston {

extern "C" {
BoxedClass* frame_cls;
}

// Issues:
// - breaks gdb backtraces
Expand Down Expand Up @@ -197,6 +199,9 @@ extern "C" int PyFrame_GetLineNumber(PyFrameObject* _f) noexcept {
extern "C" PyObject* PyFrame_GetGlobals(PyFrameObject* f) noexcept {
return BoxedFrame::globals((Box*)f, NULL);
}
extern "C" PyObject* PyFrame_GetCode(PyFrameObject* f) noexcept {
return BoxedFrame::code((Box*)f, NULL);
}

extern "C" PyFrameObject* PyFrame_ForStackLevel(int stack_level) noexcept {
return (PyFrameObject*)getFrame(stack_level);
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/objmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2639,7 +2639,7 @@ extern "C" bool nonzero(Box* obj) {
}
ASSERT(obj->cls->is_user_defined || obj->cls->instances_are_nonzero || obj->cls == classobj_cls
|| obj->cls == type_cls || isSubclass(obj->cls, Exception) || obj->cls == &PyFile_Type
|| obj->cls == traceback_cls || obj->cls == instancemethod_cls || obj->cls == module_cls
|| obj->cls == &PyTraceBack_Type || obj->cls == instancemethod_cls || obj->cls == module_cls
|| obj->cls == capifunc_cls || obj->cls == builtin_function_or_method_cls
|| obj->cls == method_cls || obj->cls == frame_cls || obj->cls == generator_cls
|| obj->cls == capi_getset_cls || obj->cls == pyston_getset_cls || obj->cls == wrapperdescr_cls
Expand Down
Loading

0 comments on commit 9d22da2

Please sign in to comment.