Index: src/x64/codegen-x64.cc |
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc |
index ef9e493ba618c3f470af06314ddfa8b2192e0704..9e4bc5c51e3cec74274f9ee579d63a21a37d7252 100644 |
--- a/src/x64/codegen-x64.cc |
+++ b/src/x64/codegen-x64.cc |
@@ -1221,7 +1221,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { |
// Compare and branch to the body if true or the next test if |
// false. Prefer the next test as a fall through. |
ControlDestination dest(clause->body_target(), &next_test, false); |
- Comparison(equal, true, &dest); |
+ Comparison(node, equal, true, &dest); |
// If the comparison fell through to the true target, jump to the |
// actual body. |
@@ -3585,7 +3585,7 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) { |
} |
Load(left); |
Load(right); |
- Comparison(cc, strict, destination()); |
+ Comparison(node, cc, strict, destination()); |
} |
@@ -4867,7 +4867,8 @@ void CodeGenerator::LoadTypeofExpression(Expression* expr) { |
} |
-void CodeGenerator::Comparison(Condition cc, |
+void CodeGenerator::Comparison(AstNode* node, |
+ Condition cc, |
bool strict, |
ControlDestination* dest) { |
// Strict only makes sense for equality comparisons. |
@@ -4914,7 +4915,8 @@ void CodeGenerator::Comparison(Condition cc, |
default: |
UNREACHABLE(); |
} |
- } else { // Only one side is a constant Smi. |
+ } else { |
+ // Only one side is a constant Smi. |
// If left side is a constant Smi, reverse the operands. |
// Since one side is a constant Smi, conversion order does not matter. |
if (left_side_constant_smi) { |
@@ -4928,6 +4930,8 @@ void CodeGenerator::Comparison(Condition cc, |
// Implement comparison against a constant Smi, inlining the case |
// where both sides are Smis. |
left_side.ToRegister(); |
+ Register left_reg = left_side.reg(); |
+ Handle<Object> right_val = right_side.handle(); |
// Here we split control flow to the stub call and inlined cases |
// before finally splitting it to the control destination. We use |
@@ -4935,12 +4939,48 @@ void CodeGenerator::Comparison(Condition cc, |
// the first split. We manually handle the off-frame references |
// by reconstituting them on the non-fall-through path. |
JumpTarget is_smi; |
- Register left_reg = left_side.reg(); |
- Handle<Object> right_val = right_side.handle(); |
Condition left_is_smi = masm_->CheckSmi(left_side.reg()); |
is_smi.Branch(left_is_smi); |
+ bool is_for_loop_compare = (node->AsCompareOperation() != NULL) |
+ && node->AsCompareOperation()->is_for_loop_condition(); |
+ if (&& right_val->IsSmi()) { |
Søren Thygesen Gjesse
2010/02/09 12:24:01
is_for_loop_compare missing before &&?
|
+ // Right side is a constant smi and left side has been checked |
+ // not to be a smi. |
+ JumpTarget not_number; |
+ __ Cmp(FieldOperand(left_reg, HeapObject::kMapOffset), |
+ Factory::heap_number_map()); |
+ not_number.Branch(not_equal, &left_side); |
+ __ movsd(xmm1, |
+ FieldOperand(left_reg, HeapNumber::kValueOffset)); |
+ int value = Smi::cast(*right_val)->value(); |
+ if (value == 0) { |
+ __ xorpd(xmm0, xmm0); |
+ } else { |
+ Result temp = allocator()->Allocate(); |
+ __ movl(temp.reg(), Immediate(value)); |
+ __ cvtlsi2sd(xmm0, temp.reg()); |
+ temp.Unuse(); |
+ } |
+ __ ucomisd(xmm1, xmm0); |
+ // Jump to builtin for NaN. |
+ not_number.Branch(parity_even, &left_side); |
+ left_side.Unuse(); |
+ Condition double_cc = cc; |
+ switch (cc) { |
+ case less: double_cc = below; break; |
+ case equal: double_cc = equal; break; |
+ case less_equal: double_cc = below_equal; break; |
+ case greater: double_cc = above; break; |
+ case greater_equal: double_cc = above_equal; break; |
+ default: UNREACHABLE(); |
+ } |
+ dest->true_target()->Branch(double_cc); |
+ dest->false_target()->Jump(); |
+ not_number.Bind(&left_side); |
+ } |
+ |
// Setup and call the compare stub. |
CompareStub stub(cc, strict); |
Result result = frame_->CallStub(&stub, &left_side, &right_side); |