Commit 2dcbe804 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Add more special-cases to nonzero

We could also add more general rewriting, but
- these new special cases catch something like
  95% of the cases that we weren't rewriting
- these special cases are faster than doing the generic
  nonzerno mechanism (looking up the attribute, etc)

It'd be nice if we could get to the point that the generic
rewrites we'd create would be as good as the hand-crafted ones,
but that would require knowing that we don't need to guard on
constant classes, and then inlining within rewrites.
parent 5294816c
......@@ -1626,10 +1626,10 @@ Rewriter* Rewriter::createRewriter(void* rtn_addr, int num_args, const char* deb
// Horrible non-robust optimization: addresses below this address are probably in the binary (ex the interpreter),
// so don't do the more-expensive hash table lookup to find it.
if (rtn_addr > (void*)0x1000000) {
if (rtn_addr > (void*)0x1800000) {
ic = getICInfo(rtn_addr);
} else {
assert(!getICInfo(rtn_addr));
ASSERT(!getICInfo(rtn_addr), "%p", rtn_addr);
}
log_ic_attempts(debug_name);
......
......@@ -1237,6 +1237,10 @@ Box* longNonzero(BoxedLong* self) {
return True;
}
bool longNonzeroUnboxed(BoxedLong* self) {
return mpz_sgn(self->n) != 0;
}
Box* longHash(BoxedLong* self) {
if (!isSubclass(self->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__pow__' requires a 'long' object but received a '%s'",
......
......@@ -54,6 +54,8 @@ Box* longRshift(BoxedLong* lhs, Box* rhs);
Box* longHex(BoxedLong* v);
Box* longOct(BoxedLong* v);
Box* longStr(BoxedLong* v);
bool longNonzeroUnboxed(BoxedLong* n);
}
#endif
......@@ -2131,6 +2131,9 @@ extern "C" bool nonzero(Box* obj) {
r_obj->addAttrGuard(BOX_CLS_OFFSET, (intptr_t)obj->cls);
}
// Note: it feels silly to have all these special cases here, and we should probably be
// able to at least generate rewrites that are as good as the ones we write here.
// But for now we can't and these should be a bit faster:
if (obj->cls == bool_cls) {
// TODO: is it faster to compare to True? (especially since it will be a constant we can embed in the rewrite)
if (rewriter.get()) {
......@@ -2142,9 +2145,6 @@ extern "C" bool nonzero(Box* obj) {
return bool_obj->n;
} else if (obj->cls == int_cls) {
if (rewriter.get()) {
// TODO should do:
// test %rsi, %rsi
// setne %al
RewriterVar* n = r_obj->getAttr(INT_N_OFFSET, rewriter->getReturnDestination());
RewriterVar* b = n->toBool(rewriter->getReturnDestination());
rewriter->commitReturning(b);
......@@ -2164,18 +2164,47 @@ extern "C" bool nonzero(Box* obj) {
rewriter->commitReturning(b);
}
return false;
}
} else if (obj->cls == long_cls) {
BoxedLong* long_obj = static_cast<BoxedLong*>(obj);
bool r = longNonzeroUnboxed(long_obj);
// FIXME we have internal functions calling this method;
// instead, we should break this out into an external and internal function.
// slowpath_* counters are supposed to count external calls; putting it down
// here gets a better representation of that.
// TODO move internal callers to nonzeroInternal, and log *all* calls to nonzero
slowpath_nonzero.log();
if (rewriter.get()) {
RewriterVar* r_rtn = rewriter->call(false, (void*)longNonzeroUnboxed, r_obj);
rewriter->commitReturning(r_rtn);
}
return r;
} else if (obj->cls == tuple_cls) {
BoxedTuple* tuple_obj = static_cast<BoxedTuple*>(obj);
bool r = (tuple_obj->ob_size != 0);
// int id = Stats::getStatId("slowpath_nonzero_" + *getTypeName(obj));
// Stats::log(id);
if (rewriter.get()) {
RewriterVar* r_rtn
= r_obj->getAttr(offsetof(BoxedTuple, ob_size))->toBool(rewriter->getReturnDestination());
rewriter->commitReturning(r_rtn);
}
return r;
} else if (obj->cls == list_cls) {
BoxedList* list_obj = static_cast<BoxedList*>(obj);
bool r = (list_obj->size != 0);
if (rewriter.get()) {
RewriterVar* r_rtn = r_obj->getAttr(offsetof(BoxedList, size))->toBool(rewriter->getReturnDestination());
rewriter->commitReturning(r_rtn);
}
return r;
} else if (obj->cls == str_cls) {
BoxedString* str_obj = static_cast<BoxedString*>(obj);
bool r = (str_obj->ob_size != 0);
if (rewriter.get()) {
RewriterVar* r_rtn
= r_obj->getAttr(offsetof(BoxedString, ob_size))->toBool(rewriter->getReturnDestination());
rewriter->commitReturning(r_rtn);
}
return r;
}
// TODO: rewrite these.
static BoxedString* nonzero_str = static_cast<BoxedString*>(PyString_InternFromString("__nonzero__"));
static BoxedString* len_str = static_cast<BoxedString*>(PyString_InternFromString("__len__"));
// go through descriptor logic
......
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