Index: src/ia32/codegen-ia32.cc |
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc |
index 1fff22d1beed1351cd5821221a0f1219bb6ceb0e..eac0fc71ca11e91a38a909c4da5317949d1c8718 100644 |
--- a/src/ia32/codegen-ia32.cc |
+++ b/src/ia32/codegen-ia32.cc |
@@ -11057,62 +11057,94 @@ void RecordWriteStub::Generate(MacroAssembler* masm) { |
} |
+static int NegativeComparisonResult(Condition cc) { |
+ ASSERT(cc != equal); |
+ ASSERT((cc == less) || (cc == less_equal) |
+ || (cc == greater) || (cc == greater_equal)); |
+ return (cc == greater || cc == greater_equal) ? LESS : GREATER; |
+} |
+ |
+ |
void CompareStub::Generate(MacroAssembler* masm) { |
Label call_builtin, done; |
// NOTICE! This code is only reached after a smi-fast-case check, so |
// it is certain that at least one operand isn't a smi. |
- if (cc_ == equal) { // Both strict and non-strict. |
- Label slow; // Fallthrough label. |
- // Equality is almost reflexive (everything but NaN), so start by testing |
- // for "identity and not NaN". |
- { |
- Label not_identical; |
- __ cmp(eax, Operand(edx)); |
- __ j(not_equal, ¬_identical); |
- // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), |
- // so we do the second best thing - test it ourselves. |
- |
- if (never_nan_nan_) { |
- __ Set(eax, Immediate(0)); |
+ // Identical objects can be compared fast, but there are some tricky cases |
+ // for NaN and undefined. |
+ { |
+ Label not_identical; |
+ __ cmp(eax, Operand(edx)); |
+ __ j(not_equal, ¬_identical); |
+ |
+ if (cc_ != equal) { |
+ // Check for undefined. undefined OP undefined is false even though |
+ // undefined == undefined. |
+ Label check_for_nan; |
+ __ cmp(edx, Factory::undefined_value()); |
+ __ j(not_equal, &check_for_nan); |
+ __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); |
+ __ ret(0); |
+ __ bind(&check_for_nan); |
+ } |
+ |
+ // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), |
+ // so we do the second best thing - test it ourselves. |
+ // Note: if cc_ != equal, never_nan_nan_ is not used. |
+ if (never_nan_nan_ && (cc_ == equal)) { |
+ __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
+ __ ret(0); |
+ } else { |
+ Label return_equal; |
+ Label heap_number; |
+ // If it's not a heap number, then return equal. |
+ __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
+ Immediate(Factory::heap_number_map())); |
+ __ j(equal, &heap_number); |
+ __ bind(&return_equal); |
+ __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
+ __ ret(0); |
+ |
+ __ bind(&heap_number); |
+ // It is a heap number, so return non-equal if it's NaN and equal if |
+ // it's not NaN. |
+ // The representation of NaN values has all exponent bits (52..62) set, |
+ // and not all mantissa bits (0..51) clear. |
+ // We only accept QNaNs, which have bit 51 set. |
+ // Read top bits of double representation (second word of value). |
+ |
+ // Value is a QNaN if value & kQuietNaNMask == kQuietNaNMask, i.e., |
+ // all bits in the mask are set. We only need to check the word |
+ // that contains the exponent and high bit of the mantissa. |
+ ASSERT_NE(0, (kQuietNaNHighBitsMask << 1) & 0x80000000u); |
+ __ mov(edx, FieldOperand(edx, HeapNumber::kExponentOffset)); |
+ __ xor_(eax, Operand(eax)); |
+ // Shift value and mask so kQuietNaNHighBitsMask applies to topmost |
+ // bits. |
+ __ add(edx, Operand(edx)); |
+ __ cmp(edx, kQuietNaNHighBitsMask << 1); |
+ if (cc_ == equal) { |
+ ASSERT_NE(1, EQUAL); |
+ __ setcc(above_equal, eax); |
__ ret(0); |
} else { |
- Label return_equal; |
- Label heap_number; |
- // If it's not a heap number, then return equal. |
- __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
- Immediate(Factory::heap_number_map())); |
- __ j(equal, &heap_number); |
- __ bind(&return_equal); |
- __ Set(eax, Immediate(0)); |
+ Label nan; |
+ __ j(above_equal, &nan); |
+ __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
__ ret(0); |
- |
- __ bind(&heap_number); |
- // It is a heap number, so return non-equal if it's NaN and equal if |
- // it's not NaN. |
- // The representation of NaN values has all exponent bits (52..62) set, |
- // and not all mantissa bits (0..51) clear. |
- // We only accept QNaNs, which have bit 51 set. |
- // Read top bits of double representation (second word of value). |
- |
- // Value is a QNaN if value & kQuietNaNMask == kQuietNaNMask, i.e., |
- // all bits in the mask are set. We only need to check the word |
- // that contains the exponent and high bit of the mantissa. |
- ASSERT_NE(0, (kQuietNaNHighBitsMask << 1) & 0x80000000u); |
- __ mov(edx, FieldOperand(edx, HeapNumber::kExponentOffset)); |
- __ xor_(eax, Operand(eax)); |
- // Shift value and mask so kQuietNaNHighBitsMask applies to topmost |
- // bits. |
- __ add(edx, Operand(edx)); |
- __ cmp(edx, kQuietNaNHighBitsMask << 1); |
- __ setcc(above_equal, eax); |
+ __ bind(&nan); |
+ __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); |
__ ret(0); |
} |
- |
- __ bind(¬_identical); |
} |
+ __ bind(¬_identical); |
+ } |
+ |
+ if (cc_ == equal) { // Both strict and non-strict. |
+ Label slow; // Fallthrough label. |
+ |
// If we're doing a strict equality comparison, we don't have to do |
// type conversion, so we generate code to do fast comparison for objects |
// and oddballs. Non-smi numbers and strings still go through the usual |
@@ -11302,14 +11334,7 @@ void CompareStub::Generate(MacroAssembler* masm) { |
builtin = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS; |
} else { |
builtin = Builtins::COMPARE; |
- int ncr; // NaN compare result |
- if (cc_ == less || cc_ == less_equal) { |
- ncr = GREATER; |
- } else { |
- ASSERT(cc_ == greater || cc_ == greater_equal); // remaining cases |
- ncr = LESS; |
- } |
- __ push(Immediate(Smi::FromInt(ncr))); |
+ __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); |
} |
// Restore return address on the stack. |