Implement fast code for the common cases of left hand sides that are less than three times larger as the right hand side and and right hand sides that are powers of two up and including 32.

In the covered special cases the result is computed directly, else the generic stub is called. The implementation deoptimizes only for mod 0 and if the result may be a negative zero.

BUG=none
TEST=none

Review URL: http://codereview.chromium.org/6331005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6421 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
karlklose@chromium.org 2011-01-20 17:42:29 +00:00
parent 5b2dff9806
commit f914324293

View File

@ -1039,6 +1039,37 @@ void LCodeGen::DoModI(LModI* instr) {
__ bind(&ok);
}
// Try a few common cases before using the generic stub.
Label call_stub;
const int kUnfolds = 3;
// Skip if either side is negative.
__ cmp(left, Operand(0));
__ cmp(right, Operand(0), NegateCondition(mi));
__ b(mi, &call_stub);
// If the right hand side is smaller than the (nonnegative)
// left hand side, it is the result. Else try a few subtractions
// of the left hand side.
__ mov(scratch, left);
for (int i = 0; i < kUnfolds; i++) {
// Check if the left hand side is less or equal than the
// the right hand side.
__ cmp(scratch, right);
__ mov(result, scratch, LeaveCC, lt);
__ b(lt, &done);
// If not, reduce the left hand side by the right hand
// side and check again.
if (i < kUnfolds - 1) __ sub(scratch, scratch, right);
}
// Check for power of two on the right hand side.
__ sub(scratch, right, Operand(1), SetCC);
__ b(mi, &call_stub);
__ tst(scratch, right);
__ b(ne, &call_stub);
// Perform modulo operation.
__ and_(result, scratch, Operand(left));
__ bind(&call_stub);
// Call the generic stub. The numbers in r0 and r1 have
// to be tagged to Smis. If that is not possible, deoptimize.
DeferredModI* deferred = new DeferredModI(this, instr);
@ -1050,7 +1081,7 @@ void LCodeGen::DoModI(LModI* instr) {
// If the result in r0 is a Smi, untag it, else deoptimize.
__ BranchOnNotSmi(result, &deoptimize);
__ mov(result, Operand(result, ASR, 1));
__ SmiUntag(result);
__ b(al, &done);
__ bind(&deoptimize);