Commit 7df079cb authored by Kevin Modzelewski's avatar Kevin Modzelewski

Pass frame-state through to make reraising faster

Instead of relying on stack unwinding to find it.
parent 1b9d802e
......@@ -1128,7 +1128,7 @@ Value ASTInterpreter::visit_raise(AST_Raise* node) {
finishJITing();
}
raise0();
ASTInterpreterJitInterface::raise0Helper(this);
}
Value arg0 = node->arg0 ? visit_expr(node->arg0) : getNone();
......@@ -1678,6 +1678,11 @@ Box* ASTInterpreterJitInterface::uncacheExcInfoHelper(void* _interpreter) {
return None;
}
void ASTInterpreterJitInterface::raise0Helper(void* _interpreter) {
ASTInterpreter* interpreter = (ASTInterpreter*)_interpreter;
raise0(&interpreter->getFrameInfo()->exc);
}
const void* interpreter_instr_addr = (void*)&executeInnerAndSetupFrame;
// small wrapper around executeInner because we can not directly call the member function from asm.
......
......@@ -48,6 +48,7 @@ struct ASTInterpreterJitInterface {
static Box* setExcInfoHelper(void* interp, Box* type, Box* value, Box* traceback);
static void setLocalClosureHelper(void* interp, long vreg, InternedString id, Box* v);
static Box* uncacheExcInfoHelper(void* interp);
static void raise0Helper(void* interp) __attribute__((noreturn));
};
class RewriterVar;
......
......@@ -478,7 +478,7 @@ void JitFragmentWriter::emitPrint(RewriterVar* dest, RewriterVar* var, bool nl)
}
void JitFragmentWriter::emitRaise0() {
call(false, (void*)raise0);
call(false, (void*)ASTInterpreterJitInterface::raise0Helper, getInterp());
}
void JitFragmentWriter::emitRaise3(RewriterVar* arg0, RewriterVar* arg1, RewriterVar* arg2) {
......
......@@ -2327,13 +2327,14 @@ private:
assert(!node->arg1);
assert(!node->arg2);
llvm::Value* exc_info = emitter.getBuilder()->CreateConstInBoundsGEP2_32(irstate->getFrameInfoVar(), 0, 0);
if (target_exception_style == CAPI) {
emitter.createCall(unw_info, g.funcs.raise0_capi, std::vector<llvm::Value*>(), CAPI);
emitter.createCall(unw_info, g.funcs.raise0_capi, exc_info, CAPI);
emitter.checkAndPropagateCapiException(unw_info, getNullPtr(g.llvm_value_type_ptr),
getNullPtr(g.llvm_value_type_ptr));
emitter.getBuilder()->CreateUnreachable();
} else {
emitter.createCall(unw_info, g.funcs.raise0, std::vector<llvm::Value*>());
emitter.createCall(unw_info, g.funcs.raise0, exc_info);
emitter.getBuilder()->CreateUnreachable();
}
......
......@@ -777,6 +777,15 @@ ExcInfo* getFrameExcInfo() {
return cur_exc;
}
void updateFrameExcInfoIfNeeded(ExcInfo* latest) {
if (latest->type)
return;
ExcInfo* updated = getFrameExcInfo();
assert(updated == latest);
return;
}
CLFunction* getTopPythonFunction() {
auto rtn = getTopPythonFrame();
if (!rtn)
......
......@@ -106,6 +106,10 @@ PythonFrameIterator getPythonFrame(int depth);
// Fetches a writeable pointer to the frame-local excinfo object,
// calculating it if necessary (from previous frames).
ExcInfo* getFrameExcInfo();
// A similar function, but that takes a pointer to the most-recent ExcInfo.
// This is faster in the case that the frame-level excinfo is already up-to-date,
// but just as slow if it's not.
void updateFrameExcInfoIfNeeded(ExcInfo* latest);
struct FrameStackState {
// This includes all # variables (but not the ! ones).
......
......@@ -135,33 +135,34 @@ ExcInfo excInfoForRaise(Box* type, Box* value, Box* tb) {
return ExcInfo(type, value, tb);
}
extern "C" void raise0() {
ExcInfo* exc_info = getFrameExcInfo();
assert(exc_info->type);
extern "C" void raise0(ExcInfo* frame_exc_info) {
updateFrameExcInfoIfNeeded(frame_exc_info);
assert(frame_exc_info->type);
// TODO need to clean up when we call normalize, do_raise, etc
if (exc_info->type == None)
if (frame_exc_info->type == None)
raiseExcHelper(TypeError, "exceptions must be old-style classes or derived from BaseException, not NoneType");
startReraise();
assert(!PyErr_Occurred());
throw * exc_info;
throw * frame_exc_info;
}
extern "C" void raise0_capi() noexcept {
ExcInfo exc_info = *getFrameExcInfo();
assert(exc_info.type);
extern "C" void raise0_capi(ExcInfo* frame_exc_info) noexcept {
updateFrameExcInfoIfNeeded(frame_exc_info);
assert(frame_exc_info->type);
// TODO need to clean up when we call normalize, do_raise, etc
if (exc_info.type == None) {
exc_info.type = TypeError;
exc_info.value = boxString("exceptions must be old-style classes or derived from BaseException, not NoneType");
exc_info.traceback = None;
PyErr_NormalizeException(&exc_info.type, &exc_info.value, &exc_info.traceback);
if (frame_exc_info->type == None) {
frame_exc_info->type = TypeError;
frame_exc_info->value
= boxString("exceptions must be old-style classes or derived from BaseException, not NoneType");
frame_exc_info->traceback = None;
PyErr_NormalizeException(&frame_exc_info->type, &frame_exc_info->value, &frame_exc_info->traceback);
}
startReraise();
PyErr_Restore(exc_info.type, exc_info.value, exc_info.traceback);
PyErr_Restore(frame_exc_info->type, frame_exc_info->value, frame_exc_info->traceback);
}
extern "C" void raise3(Box* arg0, Box* arg1, Box* arg2) {
......
......@@ -33,8 +33,8 @@ class BoxedTuple;
// user-level raise functions that implement python-level semantics
ExcInfo excInfoForRaise(Box*, Box*, Box*);
extern "C" void raise0() __attribute__((__noreturn__));
extern "C" void raise0_capi() noexcept;
extern "C" void raise0(ExcInfo* frame_exc_info) __attribute__((__noreturn__));
extern "C" void raise0_capi(ExcInfo* frame_exc_info) noexcept;
extern "C" void raise3(Box*, Box*, Box*) __attribute__((__noreturn__));
extern "C" void raise3_capi(Box*, Box*, Box*) noexcept;
void raiseExc(Box* exc_obj) __attribute__((__noreturn__));
......
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