Index: src/x64/codegen-x64.cc |
=================================================================== |
--- src/x64/codegen-x64.cc (revision 4462) |
+++ src/x64/codegen-x64.cc (working copy) |
@@ -5297,6 +5297,15 @@ |
} |
+static bool CouldBeNaN(const Result& result) { |
+ if (result.type_info().IsSmi()) return false; |
+ if (result.type_info().IsInteger32()) return false; |
+ if (!result.is_constant()) return true; |
+ if (!result.handle()->IsHeapNumber()) return false; |
+ return isnan(HeapNumber::cast(*result.handle())->value()); |
+} |
+ |
+ |
void CodeGenerator::Comparison(AstNode* node, |
Condition cc, |
bool strict, |
@@ -5614,15 +5623,29 @@ |
right_side.Unuse(); |
dest->Split(cc); |
} |
- } else { // Neither side is a constant Smi or null. |
+ } else { |
+ // Neither side is a constant Smi, constant 1-char string, or constant null. |
// If either side is a non-smi constant, skip the smi check. |
bool known_non_smi = |
(left_side.is_constant() && !left_side.handle()->IsSmi()) || |
(right_side.is_constant() && !right_side.handle()->IsSmi()); |
+ |
+ NaNInformation nan_info = |
+ (CouldBeNaN(left_side) && CouldBeNaN(right_side)) ? |
+ kBothCouldBeNaN : |
+ kCantBothBeNaN; |
+ |
left_side.ToRegister(); |
right_side.ToRegister(); |
if (known_non_smi) { |
+ // If at least one of the objects is not NaN, then if the objects |
+ // are identical, they are equal. |
+ if (nan_info == kCantBothBeNaN && cc == equal) { |
+ __ cmpq(left_side.reg(), right_side.reg()); |
+ dest->true_target()->Branch(equal); |
+ } |
+ |
// When non-smi, call out to the compare stub. |
CompareStub stub(cc, strict); |
Result answer = frame_->CallStub(&stub, &left_side, &right_side); |
@@ -5642,7 +5665,14 @@ |
Condition both_smi = masm_->CheckBothSmi(left_reg, right_reg); |
is_smi.Branch(both_smi); |
- // When non-smi, call out to the compare stub. |
+ // When non-smi, call out to the compare stub, after inlined checks. |
+ // If at least one of the objects is not NaN, then if the objects |
+ // are identical, they are equal. |
+ if (nan_info == kCantBothBeNaN && cc == equal) { |
+ __ cmpq(left_side.reg(), right_side.reg()); |
+ dest->true_target()->Branch(equal); |
+ } |
+ |
CompareStub stub(cc, strict); |
Result answer = frame_->CallStub(&stub, &left_side, &right_side); |
__ SmiTest(answer.reg()); // Sets both zero and sign flags. |