Commit 44b63a61 authored by Kevin Modzelewski's avatar Kevin Modzelewski Committed by Kevin Modzelewski

Change from throwing a Box* to an ExcInfo triple

ExcInfo is a triple of exc_type, exc_value, exc_traceback -
analogous to Python's sys.exc_info().  Previously, we were just
throwing exc_value.

I still don't understand all the rules for when type(exc_value)
is not necessarily exc_type.  But this also makes it easier to
pass exc_traceback around, and should make it possible to make
our handling more consistent.

This commit just changes the runtime; the generated code currently
still expects a Box* to be thrown and will crash.
parent 05e14eb3
......@@ -39,8 +39,8 @@ extern "C" PyObject* _PyObject_Str(PyObject* v) noexcept {
try {
return str(v);
} catch (Box* b) {
PyErr_SetObject(b->cls, b);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
......@@ -79,8 +79,8 @@ extern "C" PyObject* PyObject_GetAttrString(PyObject* o, const char* attr) noexc
try {
return getattr(o, attr);
} catch (Box* b) {
PyErr_SetObject(b->cls, b);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
......
......@@ -484,8 +484,8 @@ static PyObject* call_maybe(PyObject* o, const char* name, PyObject** nameobj, c
PyObject* slot_tp_repr(PyObject* self) noexcept {
try {
return repr(self);
} catch (Box* e) {
PyErr_SetObject(e->cls, e);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
......@@ -493,8 +493,8 @@ PyObject* slot_tp_repr(PyObject* self) noexcept {
PyObject* slot_tp_str(PyObject* self) noexcept {
try {
return str(self);
} catch (Box* e) {
PyErr_SetObject(e->cls, e);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
......@@ -542,8 +542,8 @@ PyObject* slot_tp_call(PyObject* self, PyObject* args, PyObject* kwds) noexcept
// TODO: runtime ICs?
return runtimeCall(self, ArgPassSpec(0, 0, true, true), args, kwds, NULL, NULL, NULL);
} catch (Box* e) {
PyErr_SetObject(e->cls, e);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
......@@ -631,8 +631,8 @@ static PyObject* slot_tp_new(PyTypeObject* self, PyObject* args, PyObject* kwds)
new_attr = processDescriptor(new_attr, None, self);
return runtimeCall(new_attr, ArgPassSpec(1, 0, true, true), self, args, kwds, NULL, NULL);
} catch (Box* e) {
PyErr_SetObject(e->cls, e);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
......@@ -660,8 +660,8 @@ static int slot_tp_init(PyObject* self, PyObject* args, PyObject* kwds) noexcept
PyObject* slot_sq_item(PyObject* self, Py_ssize_t i) noexcept {
try {
return getitem(self, boxInt(i));
} catch (Box* e) {
PyErr_SetObject(e->cls, e);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
......@@ -1781,7 +1781,7 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
try {
add_operators(cls);
} catch (Box* b) {
} catch (ExcInfo e) {
abort();
}
......
......@@ -123,7 +123,7 @@ private:
SymMap sym_table;
CFGBlock* next_block, *current_block;
AST_stmt* current_inst;
Box* last_exception;
ExcInfo last_exception;
BoxedClosure* passed_closure, *created_closure;
BoxedGenerator* generator;
unsigned edgecount;
......@@ -224,7 +224,7 @@ void gatherInterpreterRoots(GCVisitor* visitor) {
ASTInterpreter::ASTInterpreter(CompiledFunction* compiled_function)
: compiled_func(compiled_function), source_info(compiled_function->clfunc->source), scope_info(0), next_block(0),
current_block(0), current_inst(0), last_exception(0), passed_closure(0), created_closure(0), generator(0),
current_block(0), current_inst(0), last_exception(NULL, NULL, NULL), passed_closure(0), created_closure(0), generator(0),
edgecount(0) {
CLFunction* f = compiled_function->clfunc;
......@@ -506,9 +506,9 @@ Value ASTInterpreter::visit_invoke(AST_Invoke* node) {
try {
v = visit_stmt(node->stmt);
next_block = node->normal_dest;
} catch (Box* b) {
} catch (ExcInfo e) {
next_block = node->exc_dest;
last_exception = b;
last_exception = e;
}
return v;
......@@ -561,8 +561,10 @@ Value ASTInterpreter::visit_langPrimitive(AST_LangPrimitive* node) {
} else if (node->opcode == AST_LangPrimitive::NONE) {
v = None;
} else if (node->opcode == AST_LangPrimitive::LANDINGPAD) {
v = last_exception;
last_exception = nullptr;
abort();
// Have to figure out how to represent landingpads
//v = last_exception;
//last_exception = nullptr;
} else if (node->opcode == AST_LangPrimitive::ISINSTANCE) {
assert(node->args.size() == 3);
Value obj = visit_expr(node->args[0]);
......
......@@ -469,6 +469,14 @@ public:
LineInfo(int line, int column, const std::string& file, const std::string& func)
: line(line), column(column), file(file), func(func) {}
};
struct ExcInfo {
Box* type, *value, *traceback;
ExcInfo(Box* type, Box* value, Box* traceback) : type(type), value(value), traceback(traceback) {}
bool matches(BoxedClass* cls) const;
};
}
#endif
......@@ -42,6 +42,7 @@ public:
void operator=(Box* b) { value = b; }
operator Box*() { return value; }
Box* operator->() { return value; }
};
void runCollection();
......
......@@ -150,12 +150,12 @@ int main(int argc, char** argv) {
try {
main_module = createAndRunModule("__main__", fn);
} catch (Box* b) {
if (isInstance(b, SystemExit)) {
} catch (ExcInfo e) {
if (e.matches(SystemExit)) {
printf("Warning: ignoring SystemExit code\n");
return 1;
} else {
std::string msg = formatException(b);
std::string msg = formatException(e.value);
printLastTraceback();
fprintf(stderr, "%s\n", msg.c_str());
return 1;
......@@ -222,12 +222,12 @@ int main(int argc, char** argv) {
try {
compileAndRunModule(m, main_module);
} catch (Box* b) {
if (isInstance(b, SystemExit)) {
} catch (ExcInfo e) {
if (e.matches(SystemExit)) {
printf("Warning: ignoring SystemExit code\n");
return 1;
} else {
std::string msg = formatException(b);
std::string msg = formatException(e.value);
printLastTraceback();
fprintf(stderr, "%s\n", msg.c_str());
}
......
......@@ -446,8 +446,8 @@ Box* hasattr(Box* obj, Box* _str) {
Box* attr;
try {
attr = getattrInternal(obj, str->s, NULL);
} catch (Box* e) {
if (isSubclass(e->cls, Exception))
} catch (ExcInfo e) {
if (e.matches(Exception))
return False;
throw;
}
......@@ -623,7 +623,7 @@ extern "C" PyObject* PyErr_NewException(char* name, PyObject* _base, PyObject* d
// TODO Not sure if this should be called here
fixup_slot_dispatchers(cls);
return cls;
} catch (Box* e) {
} catch (ExcInfo e) {
abort();
}
}
......
......@@ -82,7 +82,7 @@ extern "C" int PySys_SetObject(const char* name, PyObject* v) noexcept {
sys_module->delattr(name, NULL);
} else
sys_module->setattr(name, v, NULL);
} catch (Box* b) {
} catch (ExcInfo e) {
abort();
}
return 0;
......
......@@ -31,8 +31,8 @@ static void* thread_start(Box* target, Box* varargs, Box* kwargs) {
try {
runtimeCall(target, ArgPassSpec(0, 0, true, kwargs != NULL), varargs, kwargs, NULL, NULL, NULL);
} catch (Box* b) {
std::string msg = formatException(b);
} catch (ExcInfo e) {
std::string msg = formatException(e.value);
printLastTraceback();
fprintf(stderr, "%s\n", msg.c_str());
}
......
......@@ -158,7 +158,7 @@ extern "C" PyObject* PyObject_CallObject(PyObject* obj, PyObject* args) noexcept
try {
Box* r = runtimeCall(obj, ArgPassSpec(0, 0, true, false), args, NULL, NULL, NULL, NULL);
return r;
} catch (Box* b) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......@@ -174,8 +174,8 @@ extern "C" PyObject* _PyObject_CallMethod_SizeT(PyObject* o, char* name, char* f
extern "C" Py_ssize_t PyObject_Size(PyObject* o) noexcept {
try {
return len(o)->n;
} catch (Box* b) {
PyErr_SetObject(b->cls, b);
} catch (ExcInfo e) {
setCAPIException(e);
return -1;
}
}
......@@ -183,8 +183,8 @@ extern "C" Py_ssize_t PyObject_Size(PyObject* o) noexcept {
extern "C" PyObject* PyObject_GetIter(PyObject* o) noexcept {
try {
return getiter(o);
} catch (Box* b) {
PyErr_SetObject(b->cls, b);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
......@@ -192,8 +192,8 @@ extern "C" PyObject* PyObject_GetIter(PyObject* o) noexcept {
extern "C" PyObject* PyObject_Repr(PyObject* obj) noexcept {
try {
return repr(obj);
} catch (Box* b) {
PyErr_SetObject(b->cls, b);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
......@@ -352,7 +352,7 @@ extern "C" PyObject* PyObject_GetAttr(PyObject* o, PyObject* attr_name) noexcept
try {
return getattr(o, static_cast<BoxedString*>(attr_name)->s.c_str());
} catch (Box* b) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......@@ -364,8 +364,8 @@ extern "C" PyObject* PyObject_GenericGetAttr(PyObject* o, PyObject* name) noexce
extern "C" PyObject* PyObject_GetItem(PyObject* o, PyObject* key) noexcept {
try {
return getitem(o, key);
} catch (Box* b) {
PyErr_SetObject(b->cls, b);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
......@@ -389,7 +389,7 @@ int _Py_SwappedOp[] = { Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE };
extern "C" long PyObject_Hash(PyObject* o) noexcept {
try {
return hash(o)->n;
} catch (Box* b) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......@@ -419,7 +419,7 @@ extern "C" long _Py_HashPointer(void* p) noexcept {
extern "C" int PyObject_IsTrue(PyObject* o) noexcept {
try {
return nonzero(o);
} catch (Box* b) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......@@ -459,7 +459,7 @@ extern "C" PyObject* PyObject_Call(PyObject* callable_object, PyObject* args, Py
return runtimeCall(callable_object, ArgPassSpec(0, 0, true, true), args, kw, NULL, NULL, NULL);
else
return runtimeCall(callable_object, ArgPassSpec(0, 0, true, false), args, NULL, NULL, NULL, NULL);
} catch (Box* b) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......@@ -496,7 +496,7 @@ extern "C" PyObject* PySequence_GetItem(PyObject* o, Py_ssize_t i) noexcept {
try {
// Not sure if this is really the same:
return getitem(o, boxInt(i));
} catch (Box* b) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......@@ -505,7 +505,7 @@ extern "C" PyObject* PySequence_GetSlice(PyObject* o, Py_ssize_t i1, Py_ssize_t
try {
// Not sure if this is really the same:
return getitem(o, new BoxedSlice(boxInt(i1), boxInt(i2), None));
} catch (Box* b) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......@@ -551,8 +551,8 @@ extern "C" PyObject* PyIter_Next(PyObject* iter) noexcept {
try {
return callattr(iter, &next_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = false }),
ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
} catch (Box* b) {
PyErr_SetObject(b->cls, b);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
......@@ -672,6 +672,12 @@ finally:
--tstate->recursion_depth;
}
void setCAPIException(const ExcInfo& e) {
cur_thread_state.curexc_type = e.type;
cur_thread_state.curexc_value = e.value;
cur_thread_state.curexc_traceback = e.traceback;
}
void checkAndThrowCAPIException() {
Box* _type = cur_thread_state.curexc_type;
if (!_type)
......@@ -859,7 +865,7 @@ extern "C" PyObject* PyImport_Import(PyObject* module_name) noexcept {
try {
return import(-1, None, &static_cast<BoxedString*>(module_name)->s);
} catch (Box* e) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......@@ -895,7 +901,7 @@ extern "C" int PyNumber_Check(PyObject* obj) noexcept {
extern "C" PyObject* PyNumber_Add(PyObject* lhs, PyObject* rhs) noexcept {
try {
return binop(lhs, rhs, AST_TYPE::Add);
} catch (Box* b) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......@@ -903,7 +909,7 @@ extern "C" PyObject* PyNumber_Add(PyObject* lhs, PyObject* rhs) noexcept {
extern "C" PyObject* PyNumber_Subtract(PyObject* lhs, PyObject* rhs) noexcept {
try {
return binop(lhs, rhs, AST_TYPE::Sub);
} catch (Box* b) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......@@ -911,7 +917,7 @@ extern "C" PyObject* PyNumber_Subtract(PyObject* lhs, PyObject* rhs) noexcept {
extern "C" PyObject* PyNumber_Multiply(PyObject* lhs, PyObject* rhs) noexcept {
try {
return binop(lhs, rhs, AST_TYPE::Mult);
} catch (Box* b) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......@@ -919,7 +925,7 @@ extern "C" PyObject* PyNumber_Multiply(PyObject* lhs, PyObject* rhs) noexcept {
extern "C" PyObject* PyNumber_Divide(PyObject* lhs, PyObject* rhs) noexcept {
try {
return binop(lhs, rhs, AST_TYPE::Div);
} catch (Box* b) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......@@ -935,7 +941,7 @@ extern "C" PyObject* PyNumber_TrueDivide(PyObject*, PyObject*) noexcept {
extern "C" PyObject* PyNumber_Remainder(PyObject* lhs, PyObject* rhs) noexcept {
try {
return binop(lhs, rhs, AST_TYPE::Mod);
} catch (Box* b) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......@@ -959,7 +965,7 @@ extern "C" PyObject* PyNumber_Positive(PyObject* o) noexcept {
extern "C" PyObject* PyNumber_Absolute(PyObject* o) noexcept {
try {
return abs_(o);
} catch (Box* b) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......@@ -975,7 +981,7 @@ extern "C" PyObject* PyNumber_Lshift(PyObject*, PyObject*) noexcept {
extern "C" PyObject* PyNumber_Rshift(PyObject* lhs, PyObject* rhs) noexcept {
try {
return binop(lhs, rhs, AST_TYPE::RShift);
} catch (Box* b) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......@@ -983,7 +989,7 @@ extern "C" PyObject* PyNumber_Rshift(PyObject* lhs, PyObject* rhs) noexcept {
extern "C" PyObject* PyNumber_And(PyObject* lhs, PyObject* rhs) noexcept {
try {
return binop(lhs, rhs, AST_TYPE::BitAnd);
} catch (Box* b) {
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
}
......
......@@ -23,6 +23,8 @@ class BoxedModule;
BoxedModule* importTestExtension(const std::string&);
void checkAndThrowCAPIException();
struct ExcInfo;
void setCAPIException(const ExcInfo& e);
}
#endif
......@@ -224,17 +224,17 @@ Box* instanceNonzero(Box* _inst) {
Box* nonzero_func = NULL;
try {
nonzero_func = _instanceGetattribute(inst, boxStrConstant("__nonzero__"), false);
} catch (Box* b) {
if (!isInstance(b, AttributeError))
throw;
} catch (ExcInfo e) {
if (!e.matches(AttributeError))
throw e;
}
if (nonzero_func == NULL) {
try {
nonzero_func = _instanceGetattribute(inst, boxStrConstant("__len__"), false);
} catch (Box* b) {
if (!isInstance(b, AttributeError))
throw;
} catch (ExcInfo e) {
if (!e.matches(AttributeError))
throw e;
}
}
......
......@@ -14,6 +14,7 @@
#include "runtime/dict.h"
#include "capi/types.h"
#include "core/common.h"
#include "core/stats.h"
#include "core/types.h"
......@@ -136,8 +137,8 @@ extern "C" PyObject* PyDict_Copy(PyObject* o) noexcept {
RELEASE_ASSERT(PyDict_Check(o), "");
try {
return dictCopy(static_cast<BoxedDict*>(o));
} catch (Box* e) {
PyErr_SetObject(e->cls, e);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
......@@ -179,7 +180,7 @@ extern "C" int PyDict_SetItem(PyObject* mp, PyObject* _key, PyObject* _item) noe
try {
// TODO should demote GIL?
setitem(b, key, item);
} catch (Box* b) {
} catch (ExcInfo e) {
abort();
}
return 0;
......@@ -189,7 +190,7 @@ extern "C" int PyDict_SetItemString(PyObject* mp, const char* key, PyObject* ite
Box* key_s;
try {
key_s = boxStrConstant(key);
} catch (Box* b) {
} catch (ExcInfo e) {
abort();
}
......@@ -200,8 +201,8 @@ extern "C" PyObject* PyDict_GetItem(PyObject* dict, PyObject* key) noexcept {
ASSERT(dict->cls == dict_cls || dict->cls == attrwrapper_cls, "%s", getTypeName(dict)->c_str());
try {
return getitem(dict, key);
} catch (Box* b) {
if (isSubclass(b->cls, KeyError))
} catch (ExcInfo e) {
if (e.matches(KeyError))
return NULL;
abort();
}
......@@ -215,7 +216,7 @@ extern "C" PyObject* PyDict_GetItemString(PyObject* dict, const char* key) noexc
Box* key_s;
try {
key_s = boxStrConstant(key);
} catch (Box* b) {
} catch (ExcInfo e) {
abort();
}
return PyDict_GetItem(dict, key_s);
......@@ -404,8 +405,8 @@ extern "C" int PyDict_Merge(PyObject* a, PyObject* b, int override_) noexcept {
try {
dictMerge(static_cast<BoxedDict*>(a), b);
return 0;
} catch (Box* e) {
PyErr_SetObject(e->cls, e);
} catch (ExcInfo e) {
setCAPIException(e);
return -1;
}
}
......
......@@ -16,6 +16,7 @@
#include <cstring>
#include <sstream>
#include "capi/types.h"
#include "core/common.h"
#include "core/stats.h"
#include "core/types.h"
......@@ -205,8 +206,8 @@ extern "C" int PyFile_WriteObject(PyObject* v, PyObject* f, int flags) noexcept
Box* r = fileWrite(static_cast<BoxedFile*>(f), v);
assert(r == None);
return 0;
} catch (Box* b) {
PyErr_SetObject(b->cls, b);
} catch (ExcInfo e) {
setCAPIException(e);
return -1;
}
}
......@@ -271,7 +272,7 @@ extern "C" int PyObject_AsFileDescriptor(PyObject* o) noexcept {
extern "C" int PyFile_SoftSpace(PyObject* f, int newflag) noexcept {
try {
return softspace(f, newflag);
} catch (Box* b) {
} catch (ExcInfo e) {
abort();
}
}
......
......@@ -53,7 +53,7 @@ static void generatorEntry(BoxedGenerator* g) {
Box** args = g->args ? &g->args->elts[0] : nullptr;
callCLFunc(func->f, nullptr, func->f->numReceivedArgs(), func->closure, g, g->arg1, g->arg2, g->arg3, args);
} catch (Box* e) {
} catch (ExcInfo e) {
// unhandled exception: propagate the exception to the caller
g->exception = e;
}
......@@ -85,8 +85,8 @@ Box* generatorSend(Box* s, Box* v) {
self->running = false;
// propagate exception to the caller
if (self->exception)
raiseExc(self->exception);
if (self->exception.type)
raiseRaw(self->exception);
// throw StopIteration if the generator exited
if (self->entryExited)
......@@ -99,7 +99,8 @@ Box* generatorThrow(Box* s, BoxedClass* e) {
assert(s->cls == generator_cls);
assert(isSubclass(e, Exception));
BoxedGenerator* self = static_cast<BoxedGenerator*>(s);
self->exception = exceptionNew1(e);
Box* ex = exceptionNew1(e);
self->exception = ExcInfo(ex->cls, ex, NULL);
return generatorSend(self, None);
}
......@@ -128,10 +129,10 @@ extern "C" Box* yield(BoxedGenerator* obj, Box* value) {
threading::pushGenerator(obj, obj->stack_begin, (void*)obj->returnContext.uc_mcontext.gregs[REG_RSP]);
// if the generator receives a exception from the caller we have to throw it
if (self->exception) {
Box* exception = self->exception;
self->exception = nullptr;
raiseExc(exception);
if (self->exception.type) {
ExcInfo e = self->exception;
self->exception = ExcInfo(NULL, NULL, NULL);
raiseRaw(e);
}
return self->returnValue;
}
......@@ -146,7 +147,7 @@ extern "C" BoxedGenerator* createGenerator(BoxedFunction* function, Box* arg1, B
extern "C" BoxedGenerator::BoxedGenerator(BoxedFunction* function, Box* arg1, Box* arg2, Box* arg3, Box** args)
: function(function), arg1(arg1), arg2(arg2), arg3(arg3), args(nullptr), entryExited(false), running(false),
returnValue(nullptr), exception(nullptr) {
returnValue(nullptr), exception(nullptr, nullptr, nullptr) {
giveAttr("__name__", boxString(function->f->source->getName()));
......@@ -214,8 +215,12 @@ extern "C" void generatorGCHandler(GCVisitor* v, Box* b) {
reinterpret_cast<void* const*>(&g->args->elts[num_args - 3]));
if (g->returnValue)
v->visit(g->returnValue);
if (g->exception)
v->visit(g->exception);
if (g->exception.type)
v->visit(g->exception.type);
if (g->exception.value)
v->visit(g->exception.value);
if (g->exception.traceback)
v->visit(g->exception.traceback);
if (g->running) {
v->visitPotentialRange((void**)&g->returnContext,
......
......@@ -17,6 +17,7 @@
#include <cmath>
#include <sstream>
#include "capi/types.h"
#include "core/common.h"
#include "core/options.h"
#include "core/stats.h"
......@@ -39,7 +40,7 @@ Box* seqiterHasnext(Box* s) {
Box* next;
try {
next = getitem(self->b, boxInt(self->idx));
} catch (Box* b) {
} catch (ExcInfo e) {
return False;
}
self->idx++;
......@@ -75,12 +76,12 @@ Box* iterwrapperHasnext(Box* s) {
try {
next = callattr(self->iter, &next_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = false }),
ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
} catch (Box* b) {
if (isSubclass(b->cls, StopIteration)) {
} catch (ExcInfo e) {
if (e.matches(StopIteration)) {
self->next = NULL;
return False;
}
throw;
throw e;
}
self->next = next;
return True;
......@@ -99,8 +100,8 @@ Box* iterwrapperNext(Box* s) {
extern "C" PyObject* PySeqIter_New(PyObject* seq) noexcept {
try {
return new BoxedSeqIter(seq);
} catch (Box* e) {
PyErr_SetObject(e->cls, e);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
......
......@@ -18,6 +18,7 @@
#include <cstring>
#include <sstream>
#include "capi/types.h"
#include "core/ast.h"
#include "core/common.h"
#include "core/stats.h"
......@@ -32,7 +33,7 @@ namespace pyston {
extern "C" int PyList_Append(PyObject* op, PyObject* newitem) noexcept {
try {
listAppend(op, newitem);
} catch (Box* b) {
} catch (ExcInfo e) {
abort();
}
return 0;
......@@ -149,7 +150,7 @@ extern "C" PyObject* PyList_GetItem(PyObject* op, Py_ssize_t i) noexcept {
RELEASE_ASSERT(i >= 0, ""); // unlike list.__getitem__, PyList_GetItem doesn't do index wrapping
try {
return listGetitemUnboxed(static_cast<BoxedList*>(op), i);
} catch (Box* b) {
} catch (ExcInfo e) {
abort();
}
}
......@@ -539,7 +540,7 @@ extern "C" PyObject* PyList_New(Py_ssize_t size) noexcept {
RELEASE_ASSERT(size == 0, "");
try {
return new BoxedList();
} catch (Box* b) {
} catch (ExcInfo e) {
abort();
}
}
......@@ -622,8 +623,8 @@ extern "C" PyObject* _PyList_Extend(PyListObject* self, PyObject* b) noexcept {
try {
return listIAdd(l, b);
} catch (Box* b) {
PyErr_SetObject(b->cls, b);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
......@@ -643,8 +644,8 @@ extern "C" int PyList_SetSlice(PyObject* a, Py_ssize_t ilow, Py_ssize_t ihigh, P
else
listDelitemSlice(l, new BoxedSlice(boxInt(ilow), boxInt(ihigh), None));
return 0;
} catch (Box* b) {
PyErr_SetObject(b->cls, b);
} catch (ExcInfo e) {
setCAPIException(e);
return -1;
}
}
......
......@@ -94,7 +94,7 @@ extern "C" unsigned long PyLong_AsUnsignedLong(PyObject* vv) noexcept {
try {
return asUnsignedLong(l);
} catch (Box* e) {
} catch (ExcInfo e) {
abort();
}
}
......
......@@ -1748,7 +1748,7 @@ extern "C" BoxedString* reprOrNull(Box* obj) {
Box* r = repr(obj);
assert(r->cls == str_cls); // this should be checked by repr()
return static_cast<BoxedString*>(r);
} catch (Box* b) {
} catch (ExcInfo e) {
return nullptr;
}
}
......@@ -1757,7 +1757,7 @@ extern "C" BoxedString* strOrNull(Box* obj) {
try {
BoxedString* r = str(obj);
return static_cast<BoxedString*>(r);
} catch (Box* b) {
} catch (ExcInfo e) {
return nullptr;
}
}
......@@ -3879,10 +3879,10 @@ extern "C" Box* importStar(Box* _from_module, BoxedModule* to_module) {
Box* attr_name;
try {
attr_name = runtimeCallInternal2(all_getitem, NULL, ArgPassSpec(2), all, boxInt(idx));
} catch (Box* b) {
if (b->cls == IndexError)
} catch (ExcInfo e) {
if (e.matches(IndexError))
break;
throw;
throw e;
}
idx++;
......
......@@ -34,6 +34,7 @@ class BoxedGenerator;
extern "C" void raise0() __attribute__((__noreturn__));
extern "C" void raise3(Box*, Box*, Box*) __attribute__((__noreturn__));
void raiseExc(Box* exc_obj) __attribute__((__noreturn__));
void raiseRaw(const ExcInfo& e) __attribute__((__noreturn__));
// helper function for raising from the runtime:
void raiseExcHelper(BoxedClass*, const char* fmt, ...) __attribute__((__noreturn__));
......@@ -138,5 +139,7 @@ static const char* objectNewParameterTypeErrorMsg() {
return "object.__new__() takes no parameters";
}
}
bool exceptionMatches(const ExcInfo& e, BoxedClass* cls);
}
#endif
......@@ -98,10 +98,10 @@ void unwindExc(Box* exc_obj) {
static gc::GCRootHandle last_exc;
static std::vector<const LineInfo*> last_tb;
void raiseRaw(Box* exc_obj) __attribute__((__noreturn__));
void raiseRaw(Box* exc_obj) {
void raiseRaw(const ExcInfo& e) __attribute__((__noreturn__));
void raiseRaw(const ExcInfo& e) {
// Using libgcc:
throw exc_obj;
throw e;
// Using libunwind
// unwindExc(exc_obj);
......@@ -112,7 +112,7 @@ void raiseExc(Box* exc_obj) {
last_tb = std::move(entries);
last_exc = exc_obj;
raiseRaw(exc_obj);
raiseRaw(ExcInfo(exc_obj->cls, exc_obj, NULL));
}
// Have a special helper function for syntax errors, since we want to include the location
......@@ -125,7 +125,7 @@ void raiseSyntaxError(const char* msg, int lineno, int col_offset, const std::st
// TODO: leaks this!
last_tb.push_back(new LineInfo(lineno, col_offset, file, func));
raiseRaw(last_exc);
raiseRaw(ExcInfo(SyntaxError, last_exc, NULL));
}
static void _printTraceback(const std::vector<const LineInfo*>& tb) {
......@@ -216,7 +216,12 @@ extern "C" void exit(int code) {
}
void raise0() {
raiseRaw(last_exc);
raiseRaw(ExcInfo(last_exc->cls, last_exc, NULL));
}
bool ExcInfo::matches(BoxedClass* cls) const {
RELEASE_ASSERT(isSubclass(this->type->cls, type_cls), "throwing old-style objects not supported yet");
return isSubclass(static_cast<BoxedClass*>(this->type), cls);
}
void raise3(Box* arg0, Box* arg1, Box* arg2) {
......
......@@ -73,7 +73,7 @@ extern "C" PyObject* PyTuple_GetItem(PyObject* op, Py_ssize_t i) noexcept {
RELEASE_ASSERT(i >= 0, ""); // unlike tuple.__getitem__, PyTuple_GetItem doesn't do index wrapping
try {
return tupleGetitemUnboxed(static_cast<BoxedTuple*>(op), i);
} catch (Box* b) {
} catch (ExcInfo e) {
abort();
}
}
......
......@@ -240,12 +240,12 @@ BoxIterator& BoxIterator::operator++() {
} else {
try {
value = iter->nextIC();
} catch (Box* e) {
if ((e == StopIteration) || isSubclass(e->cls, StopIteration)) {
} catch (ExcInfo e) {
if (e.matches(StopIteration)) {
iter = nullptr;
value = nullptr;
} else
throw;
throw e;
}
}
return *this;
......@@ -531,12 +531,12 @@ extern "C" Box* createUserClass(std::string* name, Box* _bases, Box* _attr_dict)
Box* r = runtimeCall(metaclass, ArgPassSpec(3), boxStringPtr(name), _bases, _attr_dict, NULL, NULL);
RELEASE_ASSERT(r, "");
return r;
} catch (Box* b) {
} catch (ExcInfo e) {
// TODO [CAPI] bad error handling...
RELEASE_ASSERT(isSubclass(b->cls, BaseException), "");
RELEASE_ASSERT(e.matches(BaseException), "");
Box* msg = b->getattr("message");
Box* msg = e.value->getattr("message");
RELEASE_ASSERT(msg, "");
RELEASE_ASSERT(msg->cls == str_cls, "");
......@@ -545,7 +545,7 @@ extern "C" Box* createUserClass(std::string* name, Box* _bases, Box* _attr_dict)
" %s",
PyString_AS_STRING(msg));
PyErr_Restore(b->cls, newmsg, NULL);
PyErr_Restore(e.type, newmsg, NULL);
checkAndThrowCAPIException();
// Should not reach here
......
......@@ -557,7 +557,7 @@ public:
bool entryExited;
bool running;
Box* returnValue;
Box* exception;
ExcInfo exception;
ucontext_t context, returnContext;
void* stack_begin;
......
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