Commit 8813c42e authored by Kevin Modzelewski's avatar Kevin Modzelewski

Support checking for return codes other than NULL

parent 893dbbb7
...@@ -712,22 +712,7 @@ void Assembler::cmp(Register reg1, Register reg2) { ...@@ -712,22 +712,7 @@ void Assembler::cmp(Register reg1, Register reg2) {
} }
void Assembler::cmp(Register reg, Immediate imm) { void Assembler::cmp(Register reg, Immediate imm) {
int64_t val = imm.val; emitArith(imm, reg, OPCODE_CMP);
assert((-1L << 31) <= val && val < (1L << 31) - 1);
int reg_idx = reg.regnum;
int rex = REX_W;
if (reg_idx >= 8) {
rex |= REX_B;
reg_idx -= 8;
}
assert(0 <= reg_idx && reg_idx < 8);
emitRex(rex);
emitByte(0x81);
emitModRM(0b11, 7, reg_idx);
emitInt(val, 4);
} }
void Assembler::cmp(Indirect mem, Immediate imm) { void Assembler::cmp(Indirect mem, Immediate imm) {
......
...@@ -73,7 +73,7 @@ private: ...@@ -73,7 +73,7 @@ private:
uint8_t* addr; uint8_t* addr;
bool failed; // if the rewrite failed at the assembly-generation level for some reason bool failed; // if the rewrite failed at the assembly-generation level for some reason
static const uint8_t OPCODE_ADD = 0b000, OPCODE_SUB = 0b101; static const uint8_t OPCODE_ADD = 0b000, OPCODE_SUB = 0b101, OPCODE_CMP = 0b111;
static const uint8_t REX_B = 1, REX_X = 2, REX_R = 4, REX_W = 8; static const uint8_t REX_B = 1, REX_X = 2, REX_R = 4, REX_W = 8;
#ifndef NDEBUG #ifndef NDEBUG
......
...@@ -1523,17 +1523,20 @@ void Rewriter::_allocateAndCopyPlus1(RewriterVar* result, RewriterVar* first_ele ...@@ -1523,17 +1523,20 @@ void Rewriter::_allocateAndCopyPlus1(RewriterVar* result, RewriterVar* first_ele
assertConsistent(); assertConsistent();
} }
void Rewriter::checkAndThrowCAPIException(RewriterVar* r) { void Rewriter::checkAndThrowCAPIException(RewriterVar* r, int64_t exc_val) {
STAT_TIMER(t0, "us_timer_rewriter", 10); STAT_TIMER(t0, "us_timer_rewriter", 10);
addAction([=]() { this->_checkAndThrowCAPIException(r); }, { r }, ActionType::MUTATION); addAction([=]() { this->_checkAndThrowCAPIException(r, exc_val); }, { r }, ActionType::MUTATION);
} }
void Rewriter::_checkAndThrowCAPIException(RewriterVar* r) { void Rewriter::_checkAndThrowCAPIException(RewriterVar* r, int64_t exc_val) {
assembler->comment("_checkAndThrowCAPIException"); assembler->comment("_checkAndThrowCAPIException");
assembler::Register var_reg = r->getInReg(); assembler::Register var_reg = r->getInReg();
assembler->test(var_reg, var_reg); if (exc_val == 0)
assembler->test(var_reg, var_reg);
else
assembler->cmp(var_reg, assembler::Immediate(exc_val));
{ {
assembler::ForwardJump jnz(*assembler, assembler::COND_NOT_ZERO); assembler::ForwardJump jnz(*assembler, assembler::COND_NOT_ZERO);
......
...@@ -430,7 +430,7 @@ protected: ...@@ -430,7 +430,7 @@ protected:
int _allocate(RewriterVar* result, int n); int _allocate(RewriterVar* result, int n);
void _allocateAndCopy(RewriterVar* result, RewriterVar* array, int n); void _allocateAndCopy(RewriterVar* result, RewriterVar* array, int n);
void _allocateAndCopyPlus1(RewriterVar* result, RewriterVar* first_elem, RewriterVar* rest, int n_rest); void _allocateAndCopyPlus1(RewriterVar* result, RewriterVar* first_elem, RewriterVar* rest, int n_rest);
void _checkAndThrowCAPIException(RewriterVar* r); void _checkAndThrowCAPIException(RewriterVar* r, int64_t exc_val);
// The public versions of these are in RewriterVar // The public versions of these are in RewriterVar
void _addGuard(RewriterVar* var, RewriterVar* val_constant); void _addGuard(RewriterVar* var, RewriterVar* val_constant);
...@@ -515,8 +515,8 @@ public: ...@@ -515,8 +515,8 @@ public:
RewriterVar* allocateAndCopy(RewriterVar* array, int n); RewriterVar* allocateAndCopy(RewriterVar* array, int n);
RewriterVar* allocateAndCopyPlus1(RewriterVar* first_elem, RewriterVar* rest, int n_rest); RewriterVar* allocateAndCopyPlus1(RewriterVar* first_elem, RewriterVar* rest, int n_rest);
// This emits `if (!r) throwCAPIException()` // This emits `if (r == exc_val) throwCAPIException()`
void checkAndThrowCAPIException(RewriterVar* r); void checkAndThrowCAPIException(RewriterVar* r, int64_t exc_val = 0);
void abort(); void abort();
void commit(); void commit();
......
...@@ -3247,7 +3247,7 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp ...@@ -3247,7 +3247,7 @@ static Box* tppProxyToTpCall(Box* self, CallRewriteArgs* rewrite_args, ArgPassSp
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->cls->tp_call, rewrite_args->obj, rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->cls->tp_call, rewrite_args->obj,
rewrite_args->arg1, rewrite_args->arg2); rewrite_args->arg1, rewrite_args->arg2);
if (S == CXX) if (S == CXX)
rewrite_args->rewriter->call(true, (void*)checkAndThrowCAPIException); rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn);
rewrite_args->out_success = true; rewrite_args->out_success = true;
} }
......
...@@ -797,6 +797,10 @@ void throwCAPIException() { ...@@ -797,6 +797,10 @@ void throwCAPIException() {
} }
void checkAndThrowCAPIException() { void checkAndThrowCAPIException() {
// Log these since these are expensive and usually avoidable:
static StatCounter num_checkAndThrowCAPIException("num_checkAndThrowCAPIException");
num_checkAndThrowCAPIException.log();
Box* _type = cur_thread_state.curexc_type; Box* _type = cur_thread_state.curexc_type;
if (!_type) if (!_type)
assert(!cur_thread_state.curexc_value); assert(!cur_thread_state.curexc_value);
...@@ -1572,7 +1576,7 @@ Box* BoxedCApiFunction::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPa ...@@ -1572,7 +1576,7 @@ Box* BoxedCApiFunction::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPa
} }
if (rewrite_args) { if (rewrite_args) {
rewrite_args->rewriter->call(false, (void*)checkAndThrowCAPIException); rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn);
rewrite_args->out_success = true; rewrite_args->out_success = true;
} }
......
...@@ -387,7 +387,7 @@ Box* BoxedMethodDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args, A ...@@ -387,7 +387,7 @@ Box* BoxedMethodDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args, A
throwCAPIException(); throwCAPIException();
if (rewrite_args) { if (rewrite_args) {
rewrite_args->rewriter->call(false, (void*)checkAndThrowCAPIException); rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn);
rewrite_args->out_success = true; rewrite_args->out_success = true;
} }
...@@ -565,7 +565,7 @@ Box* BoxedWrapperObject::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgP ...@@ -565,7 +565,7 @@ Box* BoxedWrapperObject::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgP
rewrite_args->out_rtn = rewriter->call( rewrite_args->out_rtn = rewriter->call(
true, (void*)wk, r_obj, rewrite_args->arg1, true, (void*)wk, r_obj, rewrite_args->arg1,
rewriter->loadConst((intptr_t)self->descr->wrapped, Location::forArg(2)), rewrite_args->arg2); rewriter->loadConst((intptr_t)self->descr->wrapped, Location::forArg(2)), rewrite_args->arg2);
rewriter->call(false, (void*)checkAndThrowCAPIException); rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn);
rewrite_args->out_success = true; rewrite_args->out_success = true;
} }
} else if (flags == PyWrapperFlag_PYSTON || flags == 0) { } else if (flags == PyWrapperFlag_PYSTON || flags == 0) {
...@@ -577,7 +577,7 @@ Box* BoxedWrapperObject::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgP ...@@ -577,7 +577,7 @@ Box* BoxedWrapperObject::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgP
rewrite_args->out_rtn rewrite_args->out_rtn
= rewriter->call(true, (void*)wrapper, r_obj, rewrite_args->arg1, = rewriter->call(true, (void*)wrapper, r_obj, rewrite_args->arg1,
rewriter->loadConst((intptr_t)self->descr->wrapped, Location::forArg(2))); rewriter->loadConst((intptr_t)self->descr->wrapped, Location::forArg(2)));
rewriter->call(false, (void*)checkAndThrowCAPIException); rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn);
rewrite_args->out_success = true; rewrite_args->out_success = true;
} }
} else { } else {
......
...@@ -2056,12 +2056,11 @@ bool dataDescriptorSetSpecialCases(Box* obj, Box* val, Box* descr, SetattrRewrit ...@@ -2056,12 +2056,11 @@ bool dataDescriptorSetSpecialCases(Box* obj, Box* val, Box* descr, SetattrRewrit
args.push_back(r_obj); args.push_back(r_obj);
args.push_back(r_val); args.push_back(r_val);
args.push_back(r_closure); args.push_back(r_closure);
rewrite_args->rewriter->call( RewriterVar* r_rtn = rewrite_args->rewriter->call(
/* has_side_effects */ true, (void*)getset_descr->set, args); /* has_side_effects */ true, (void*)getset_descr->set, args);
if (descr->cls == capi_getset_cls) if (descr->cls == capi_getset_cls)
// TODO I think we are supposed to check the return value? rewrite_args->rewriter->checkAndThrowCAPIException(r_rtn, -1);
rewrite_args->rewriter->call(true, (void*)checkAndThrowCAPIException);
rewrite_args->out_success = true; rewrite_args->out_success = true;
} }
...@@ -2578,7 +2577,11 @@ template <ExceptionStyle S> BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewr ...@@ -2578,7 +2577,11 @@ template <ExceptionStyle S> BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewr
// support calling a RewriterVar (can only call fixed function addresses). // support calling a RewriterVar (can only call fixed function addresses).
r_m->addAttrGuard(offsetof(PySequenceMethods, sq_length), (intptr_t)m->sq_length); r_m->addAttrGuard(offsetof(PySequenceMethods, sq_length), (intptr_t)m->sq_length);
RewriterVar* r_n = rewrite_args->rewriter->call(true, (void*)m->sq_length, r_obj); RewriterVar* r_n = rewrite_args->rewriter->call(true, (void*)m->sq_length, r_obj);
rewrite_args->rewriter->call(true, (void*)checkAndThrowCAPIException);
// Some CPython code seems to think that any negative return value means an exception,
// but the docs say -1. TODO it would be nice to just handle any negative value.
rewrite_args->rewriter->checkAndThrowCAPIException(r_n, -1);
RewriterVar* r_r = rewrite_args->rewriter->call(false, (void*)boxInt, r_n); RewriterVar* r_r = rewrite_args->rewriter->call(false, (void*)boxInt, r_n);
rewrite_args->out_success = true; rewrite_args->out_success = true;
...@@ -4231,7 +4234,8 @@ Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrit ...@@ -4231,7 +4234,8 @@ Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrit
// support calling a RewriterVar (can only call fixed function addresses). // support calling a RewriterVar (can only call fixed function addresses).
r_sqm->addAttrGuard(offsetof(PySequenceMethods, sq_contains), (intptr_t)sqm->sq_contains); r_sqm->addAttrGuard(offsetof(PySequenceMethods, sq_contains), (intptr_t)sqm->sq_contains);
RewriterVar* r_b = rewrite_args->rewriter->call(true, (void*)sqm->sq_contains, r_rhs, r_lhs); RewriterVar* r_b = rewrite_args->rewriter->call(true, (void*)sqm->sq_contains, r_rhs, r_lhs);
rewrite_args->rewriter->call(true, (void*)checkAndThrowCAPIException); rewrite_args->rewriter->checkAndThrowCAPIException(r_b, -1);
// This could be inlined: // This could be inlined:
RewriterVar* r_r; RewriterVar* r_r;
if (op_type == AST_TYPE::NotIn) if (op_type == AST_TYPE::NotIn)
......
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