| Index: src/arm/codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/codegen-arm.cc (revision 3618)
|
| +++ src/arm/codegen-arm.cc (working copy)
|
| @@ -47,7 +47,7 @@
|
| Condition cc,
|
| bool never_nan_nan);
|
| static void EmitSmiNonsmiComparison(MacroAssembler* masm,
|
| - Label* rhs_not_nan,
|
| + Label* lhs_not_nan,
|
| Label* slow,
|
| bool strict);
|
| static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc);
|
| @@ -4778,7 +4778,7 @@
|
| } else if (cc == gt) {
|
| __ mov(r0, Operand(LESS)); // Things aren't greater than themselves.
|
| } else {
|
| - __ mov(r0, Operand(0)); // Things are <=, >=, ==, === themselves.
|
| + __ mov(r0, Operand(EQUAL)); // Things are <=, >=, ==, === themselves.
|
| }
|
| __ mov(pc, Operand(lr)); // Return.
|
|
|
| @@ -4790,6 +4790,7 @@
|
| __ 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.
|
| // Read top bits of double representation (second word of value).
|
| @@ -4805,9 +4806,9 @@
|
| __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
|
| __ orr(r0, r3, Operand(r2), SetCC);
|
| // For equal we already have the right value in r0: Return zero (equal)
|
| - // if all bits in mantissa are zero (it's an Infinity) and non-zero if not
|
| - // (it's a NaN). For <= and >= we need to load r0 with the failing value
|
| - // if it's a NaN.
|
| + // if all bits in mantissa are zero (it's an Infinity) and non-zero if
|
| + // not (it's a NaN). For <= and >= we need to load r0 with the failing
|
| + // value if it's a NaN.
|
| if (cc != eq) {
|
| // All-zero means Infinity means equal.
|
| __ mov(pc, Operand(lr), LeaveCC, eq); // Return equal
|
| @@ -4828,7 +4829,7 @@
|
|
|
| // See comment at call site.
|
| static void EmitSmiNonsmiComparison(MacroAssembler* masm,
|
| - Label* rhs_not_nan,
|
| + Label* lhs_not_nan,
|
| Label* slow,
|
| bool strict) {
|
| Label lhs_is_smi;
|
| @@ -4866,7 +4867,7 @@
|
| // We now have both loaded as doubles but we can skip the lhs nan check
|
| // since it's a Smi.
|
| __ pop(lr);
|
| - __ jmp(rhs_not_nan);
|
| + __ jmp(lhs_not_nan);
|
|
|
| __ bind(&lhs_is_smi);
|
| // Lhs is a Smi. Check whether the non-smi is a heap number.
|
| @@ -4902,37 +4903,39 @@
|
| }
|
|
|
|
|
| -void EmitNanCheck(MacroAssembler* masm, Label* rhs_not_nan, Condition cc) {
|
| +void EmitNanCheck(MacroAssembler* masm, Label* lhs_not_nan, Condition cc) {
|
| bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset);
|
| - Register lhs_exponent = exp_first ? r0 : r1;
|
| - Register rhs_exponent = exp_first ? r2 : r3;
|
| - Register lhs_mantissa = exp_first ? r1 : r0;
|
| - Register rhs_mantissa = exp_first ? r3 : r2;
|
| + Register rhs_exponent = exp_first ? r0 : r1;
|
| + Register lhs_exponent = exp_first ? r2 : r3;
|
| + Register rhs_mantissa = exp_first ? r1 : r0;
|
| + Register lhs_mantissa = exp_first ? r3 : r2;
|
| Label one_is_nan, neither_is_nan;
|
| + Label lhs_not_nan_exp_mask_is_loaded;
|
|
|
| Register exp_mask_reg = r5;
|
|
|
| __ mov(exp_mask_reg, Operand(HeapNumber::kExponentMask));
|
| - __ and_(r4, rhs_exponent, Operand(exp_mask_reg));
|
| + __ and_(r4, lhs_exponent, Operand(exp_mask_reg));
|
| __ cmp(r4, Operand(exp_mask_reg));
|
| - __ b(ne, rhs_not_nan);
|
| + __ b(ne, &lhs_not_nan_exp_mask_is_loaded);
|
| __ mov(r4,
|
| - Operand(rhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord),
|
| + Operand(lhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord),
|
| SetCC);
|
| __ b(ne, &one_is_nan);
|
| - __ cmp(rhs_mantissa, Operand(0));
|
| + __ cmp(lhs_mantissa, Operand(0));
|
| __ b(ne, &one_is_nan);
|
|
|
| - __ bind(rhs_not_nan);
|
| + __ bind(lhs_not_nan);
|
| __ mov(exp_mask_reg, Operand(HeapNumber::kExponentMask));
|
| - __ and_(r4, lhs_exponent, Operand(exp_mask_reg));
|
| + __ bind(&lhs_not_nan_exp_mask_is_loaded);
|
| + __ and_(r4, rhs_exponent, Operand(exp_mask_reg));
|
| __ cmp(r4, Operand(exp_mask_reg));
|
| __ b(ne, &neither_is_nan);
|
| __ mov(r4,
|
| - Operand(lhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord),
|
| + Operand(rhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord),
|
| SetCC);
|
| __ b(ne, &one_is_nan);
|
| - __ cmp(lhs_mantissa, Operand(0));
|
| + __ cmp(rhs_mantissa, Operand(0));
|
| __ b(eq, &neither_is_nan);
|
|
|
| __ bind(&one_is_nan);
|
| @@ -4952,21 +4955,21 @@
|
| // See comment at call site.
|
| static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc) {
|
| bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset);
|
| - Register lhs_exponent = exp_first ? r0 : r1;
|
| - Register rhs_exponent = exp_first ? r2 : r3;
|
| - Register lhs_mantissa = exp_first ? r1 : r0;
|
| - Register rhs_mantissa = exp_first ? r3 : r2;
|
| + Register rhs_exponent = exp_first ? r0 : r1;
|
| + Register lhs_exponent = exp_first ? r2 : r3;
|
| + Register rhs_mantissa = exp_first ? r1 : r0;
|
| + Register lhs_mantissa = exp_first ? r3 : r2;
|
|
|
| // r0, r1, r2, r3 have the two doubles. Neither is a NaN.
|
| if (cc == eq) {
|
| // Doubles are not equal unless they have the same bit pattern.
|
| // Exception: 0 and -0.
|
| - __ cmp(lhs_mantissa, Operand(rhs_mantissa));
|
| - __ orr(r0, lhs_mantissa, Operand(rhs_mantissa), LeaveCC, ne);
|
| + __ cmp(rhs_mantissa, Operand(lhs_mantissa));
|
| + __ orr(r0, rhs_mantissa, Operand(lhs_mantissa), LeaveCC, ne);
|
| // Return non-zero if the numbers are unequal.
|
| __ mov(pc, Operand(lr), LeaveCC, ne);
|
|
|
| - __ sub(r0, lhs_exponent, Operand(rhs_exponent), SetCC);
|
| + __ sub(r0, rhs_exponent, Operand(lhs_exponent), SetCC);
|
| // If exponents are equal then return 0.
|
| __ mov(pc, Operand(lr), LeaveCC, eq);
|
|
|
| @@ -4976,12 +4979,12 @@
|
| // We start by seeing if the mantissas (that are equal) or the bottom
|
| // 31 bits of the rhs exponent are non-zero. If so we return not
|
| // equal.
|
| - __ orr(r4, rhs_mantissa, Operand(rhs_exponent, LSL, kSmiTagSize), SetCC);
|
| + __ orr(r4, lhs_mantissa, Operand(lhs_exponent, LSL, kSmiTagSize), SetCC);
|
| __ mov(r0, Operand(r4), LeaveCC, ne);
|
| __ mov(pc, Operand(lr), LeaveCC, ne); // Return conditionally.
|
| // Now they are equal if and only if the lhs exponent is zero in its
|
| // low 31 bits.
|
| - __ mov(r0, Operand(lhs_exponent, LSL, kSmiTagSize));
|
| + __ mov(r0, Operand(rhs_exponent, LSL, kSmiTagSize));
|
| __ mov(pc, Operand(lr));
|
| } else {
|
| // Call a native function to do a comparison between two non-NaNs.
|
| @@ -5036,9 +5039,10 @@
|
| Label* both_loaded_as_doubles,
|
| Label* not_heap_numbers,
|
| Label* slow) {
|
| - __ CompareObjectType(r0, r2, r2, HEAP_NUMBER_TYPE);
|
| + __ CompareObjectType(r0, r3, r2, HEAP_NUMBER_TYPE);
|
| __ b(ne, not_heap_numbers);
|
| - __ CompareObjectType(r1, r3, r3, HEAP_NUMBER_TYPE);
|
| + __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
|
| + __ cmp(r2, r3);
|
| __ b(ne, slow); // First was a heap number, second wasn't. Go slow case.
|
|
|
| // Both are heap numbers. Load them up then jump to the code we have
|
| @@ -5075,7 +5079,7 @@
|
| // positive or negative to indicate the result of the comparison.
|
| void CompareStub::Generate(MacroAssembler* masm) {
|
| Label slow; // Call builtin.
|
| - Label not_smis, both_loaded_as_doubles, rhs_not_nan;
|
| + Label not_smis, both_loaded_as_doubles, lhs_not_nan;
|
|
|
| // 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.
|
| @@ -5095,32 +5099,46 @@
|
| // 1) Return the answer.
|
| // 2) Go to slow.
|
| // 3) Fall through to both_loaded_as_doubles.
|
| - // 4) Jump to rhs_not_nan.
|
| + // 4) Jump to lhs_not_nan.
|
| // In cases 3 and 4 we have found out we were dealing with a number-number
|
| // comparison and the numbers have been loaded into r0, r1, r2, r3 as doubles.
|
| - EmitSmiNonsmiComparison(masm, &rhs_not_nan, &slow, strict_);
|
| + EmitSmiNonsmiComparison(masm, &lhs_not_nan, &slow, strict_);
|
|
|
| __ bind(&both_loaded_as_doubles);
|
| - // r0, r1, r2, r3 are the double representations of the left hand side
|
| - // and the right hand side.
|
| + // r0, r1, r2, r3 are the double representations of the right hand side
|
| + // and the left hand side.
|
|
|
| - // Checks for NaN in the doubles we have loaded. Can return the answer or
|
| - // fall through if neither is a NaN. Also binds rhs_not_nan.
|
| - EmitNanCheck(masm, &rhs_not_nan, cc_);
|
| -
|
| if (CpuFeatures::IsSupported(VFP3)) {
|
| + __ bind(&lhs_not_nan);
|
| CpuFeatures::Scope scope(VFP3);
|
| + Label no_nan;
|
| // ARMv7 VFP3 instructions to implement double precision comparison.
|
| __ vmov(d6, r0, r1);
|
| __ vmov(d7, r2, r3);
|
|
|
| - __ vcmp(d6, d7);
|
| - __ vmrs(pc);
|
| - __ mov(r0, Operand(0), LeaveCC, eq);
|
| - __ mov(r0, Operand(1), LeaveCC, lt);
|
| - __ mvn(r0, Operand(0), LeaveCC, gt);
|
| + __ vcmp(d7, d6);
|
| + __ vmrs(pc); // Move vector status bits to normal status bits.
|
| + Label nan;
|
| + __ b(vs, &nan);
|
| + __ mov(r0, Operand(EQUAL), LeaveCC, eq);
|
| + __ mov(r0, Operand(LESS), LeaveCC, lt);
|
| + __ mov(r0, Operand(GREATER), LeaveCC, gt);
|
| __ mov(pc, Operand(lr));
|
| +
|
| + __ bind(&nan);
|
| + // If one of the sides was a NaN then the v flag is set. Load r0 with
|
| + // whatever it takes to make the comparison fail, since comparisons with NaN
|
| + // always fail.
|
| + if (cc_ == lt || cc_ == le) {
|
| + __ mov(r0, Operand(GREATER));
|
| + } else {
|
| + __ mov(r0, Operand(LESS));
|
| + }
|
| + __ mov(pc, Operand(lr));
|
| } else {
|
| + // Checks for NaN in the doubles we have loaded. Can return the answer or
|
| + // fall through if neither is a NaN. Also binds lhs_not_nan.
|
| + EmitNanCheck(masm, &lhs_not_nan, cc_);
|
| // Compares two doubles in r0, r1, r2, r3 that are not NaNs. Returns the
|
| // answer. Never falls through.
|
| EmitTwoNonNanDoubleComparison(masm, cc_);
|
| @@ -5139,7 +5157,7 @@
|
| // Check for heap-number-heap-number comparison. Can jump to slow case,
|
| // or load both doubles into r0, r1, r2, r3 and jump to the code that handles
|
| // that case. If the inputs are not doubles then jumps to check_for_symbols.
|
| - // In this case r2 will contain the type of r0.
|
| + // In this case r2 will contain the type of r0. Never falls through.
|
| EmitCheckForTwoHeapNumbers(masm,
|
| &both_loaded_as_doubles,
|
| &check_for_symbols,
|
|
|