Optimize implementation of Math.floor a little by special casing

the comparison it uses in the code generator.  Use Math.floor for
date operations.
Review URL: http://codereview.chromium.org/509007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3508 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
erik.corry@gmail.com 2009-12-21 15:04:00 +00:00
parent fc26307487
commit 14975f3dd0
4 changed files with 41 additions and 7 deletions

View File

@ -5928,6 +5928,8 @@ void CodeGenerator::VisitThisFunction(ThisFunction* node) {
void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
Comment cmnt(masm_, "[ CompareOperation");
bool left_already_loaded = false;
// Get the expressions from the node.
Expression* left = node->left();
Expression* right = node->right();
@ -6008,7 +6010,6 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
__ CmpInstanceType(answer.reg(), JS_REGEXP_TYPE);
answer.Unuse();
destination()->Split(equal);
} else if (check->Equals(Heap::object_symbol())) {
__ test(answer.reg(), Immediate(kSmiTagMask));
destination()->false_target()->Branch(zero);
@ -6040,6 +6041,38 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
destination()->Goto(false);
}
return;
} else if (op == Token::LT &&
right->AsLiteral() != NULL &&
right->AsLiteral()->handle()->IsHeapNumber()) {
Handle<HeapNumber> check(HeapNumber::cast(*right->AsLiteral()->handle()));
if (check->value() == 2147483648.0) { // 0x80000000.
Load(left);
left_already_loaded = true;
Result lhs = frame_->Pop();
lhs.ToRegister();
__ test(lhs.reg(), Immediate(kSmiTagMask));
destination()->true_target()->Branch(zero); // All Smis are less.
Result scratch = allocator()->Allocate();
ASSERT(scratch.is_valid());
__ mov(scratch.reg(), FieldOperand(lhs.reg(), HeapObject::kMapOffset));
__ cmp(scratch.reg(), Factory::heap_number_map());
JumpTarget not_a_number;
not_a_number.Branch(not_equal, &lhs);
__ mov(scratch.reg(),
FieldOperand(lhs.reg(), HeapNumber::kExponentOffset));
__ cmp(Operand(scratch.reg()), Immediate(0xfff00000));
not_a_number.Branch(above_equal, &lhs); // It's a negative NaN or -Inf.
const uint32_t borderline_exponent =
(HeapNumber::kExponentBias + 31) << HeapNumber::kExponentShift;
__ cmp(Operand(scratch.reg()), Immediate(borderline_exponent));
scratch.Unuse();
lhs.Unuse();
destination()->true_target()->Branch(less);
destination()->false_target()->Jump();
not_a_number.Bind(&lhs);
frame_->Push(&lhs);
}
}
Condition cc = no_condition;
@ -6064,14 +6097,14 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
cc = greater_equal;
break;
case Token::IN: {
Load(left);
if (!left_already_loaded) Load(left);
Load(right);
Result answer = frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2);
frame_->Push(&answer); // push the result
return;
}
case Token::INSTANCEOF: {
Load(left);
if (!left_already_loaded) Load(left);
Load(right);
InstanceofStub stub;
Result answer = frame_->CallStub(&stub, 2);
@ -6084,7 +6117,7 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
default:
UNREACHABLE();
}
Load(left);
if (!left_already_loaded) Load(left);
Load(right);
Comparison(node, cc, strict, destination());
}

View File

@ -112,7 +112,8 @@ class JumpTarget : public ZoneObject { // Shadows are dynamically allocated.
// Emit a conditional branch to the target. There must be a current
// frame at the branch. The current frame will fall through to the
// code after the branch.
// code after the branch. The arg is a result that is live both at
// the target and the fall-through.
virtual void Branch(Condition cc, Hint hint = no_hint);
virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);

View File

@ -92,7 +92,7 @@ macro IS_ERROR(arg) = (%_ClassOf(arg) === 'Error');
macro IS_SCRIPT(arg) = (%_ClassOf(arg) === 'Script');
macro IS_ARGUMENTS(arg) = (%_ClassOf(arg) === 'Arguments');
macro IS_GLOBAL(arg) = (%_ClassOf(arg) === 'global');
macro FLOOR(arg) = %Math_floor(arg);
macro FLOOR(arg) = $floor(arg);
# Inline macros. Use %IS_VAR to make sure arg is evaluated only once.
macro NUMBER_IS_NAN(arg) = (!%_IsSmi(%IS_VAR(arg)) && !(arg == arg));

View File

@ -98,7 +98,7 @@ function MathFloor(x) {
if (!IS_NUMBER(x)) x = ToNumber(x);
// It's more common to call this with a positive number that's out
// of range than negative numbers; check the upper bound first.
if (x <= 0x7FFFFFFF && x > 0) {
if (x < 0x80000000 && x > 0) {
// Numbers in the range [0, 2^31) can be floored by converting
// them to an unsigned 32-bit value using the shift operator.
// We avoid doing so for -0, because the result of Math.floor(-0)