| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 4507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4518 __ bind(&smi_done); | 4518 __ bind(&smi_done); |
| 4519 __ mov(eax, edx); | 4519 __ mov(eax, edx); |
| 4520 __ ret(0); | 4520 __ ret(0); |
| 4521 __ bind(&non_smi); | 4521 __ bind(&non_smi); |
| 4522 | 4522 |
| 4523 // NOTICE! This code is only reached after a smi-fast-case check, so | 4523 // NOTICE! This code is only reached after a smi-fast-case check, so |
| 4524 // it is certain that at least one operand isn't a smi. | 4524 // it is certain that at least one operand isn't a smi. |
| 4525 | 4525 |
| 4526 // Identical objects can be compared fast, but there are some tricky cases | 4526 // Identical objects can be compared fast, but there are some tricky cases |
| 4527 // for NaN and undefined. | 4527 // for NaN and undefined. |
| 4528 Label generic_heap_number_comparison; |
| 4528 { | 4529 { |
| 4529 Label not_identical; | 4530 Label not_identical; |
| 4530 __ cmp(eax, edx); | 4531 __ cmp(eax, edx); |
| 4531 __ j(not_equal, ¬_identical); | 4532 __ j(not_equal, ¬_identical); |
| 4532 | 4533 |
| 4533 if (cc != equal) { | 4534 if (cc != equal) { |
| 4534 // Check for undefined. undefined OP undefined is false even though | 4535 // Check for undefined. undefined OP undefined is false even though |
| 4535 // undefined == undefined. | 4536 // undefined == undefined. |
| 4536 Label check_for_nan; | 4537 Label check_for_nan; |
| 4537 __ cmp(edx, masm->isolate()->factory()->undefined_value()); | 4538 __ cmp(edx, masm->isolate()->factory()->undefined_value()); |
| 4538 __ j(not_equal, &check_for_nan, Label::kNear); | 4539 __ j(not_equal, &check_for_nan, Label::kNear); |
| 4539 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); | 4540 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); |
| 4540 __ ret(0); | 4541 __ ret(0); |
| 4541 __ bind(&check_for_nan); | 4542 __ bind(&check_for_nan); |
| 4542 } | 4543 } |
| 4543 | 4544 |
| 4544 // Test for NaN. Sadly, we can't just compare to factory->nan_value(), | 4545 // Test for NaN. Compare heap numbers in a general way, |
| 4545 // so we do the second best thing - test it ourselves. | 4546 // to hanlde NaNs correctly. |
| 4546 Label heap_number; | |
| 4547 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 4547 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 4548 Immediate(masm->isolate()->factory()->heap_number_map())); | 4548 Immediate(masm->isolate()->factory()->heap_number_map())); |
| 4549 __ j(equal, &heap_number, Label::kNear); | 4549 __ j(equal, &generic_heap_number_comparison, Label::kNear); |
| 4550 if (cc != equal) { | 4550 if (cc != equal) { |
| 4551 // Call runtime on identical JSObjects. Otherwise return equal. | 4551 // Call runtime on identical JSObjects. Otherwise return equal. |
| 4552 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); | 4552 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); |
| 4553 __ j(above_equal, ¬_identical); | 4553 __ j(above_equal, ¬_identical); |
| 4554 } | 4554 } |
| 4555 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 4555 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
| 4556 __ ret(0); | 4556 __ ret(0); |
| 4557 | 4557 |
| 4558 __ bind(&heap_number); | |
| 4559 // It is a heap number, so return non-equal if it's NaN and equal if | |
| 4560 // it's not NaN. | |
| 4561 // The representation of NaN values has all exponent bits (52..62) set, | |
| 4562 // and not all mantissa bits (0..51) clear. | |
| 4563 // We only accept QNaNs, which have bit 51 set. | |
| 4564 // Read top bits of double representation (second word of value). | |
| 4565 | |
| 4566 // Value is a QNaN if value & kQuietNaNMask == kQuietNaNMask, i.e., | |
| 4567 // all bits in the mask are set. We only need to check the word | |
| 4568 // that contains the exponent and high bit of the mantissa. | |
| 4569 STATIC_ASSERT(((kQuietNaNHighBitsMask << 1) & 0x80000000u) != 0); | |
| 4570 __ mov(edx, FieldOperand(edx, HeapNumber::kExponentOffset)); | |
| 4571 __ Set(eax, Immediate(0)); | |
| 4572 // Shift value and mask so kQuietNaNHighBitsMask applies to topmost | |
| 4573 // bits. | |
| 4574 __ add(edx, edx); | |
| 4575 __ cmp(edx, kQuietNaNHighBitsMask << 1); | |
| 4576 if (cc == equal) { | |
| 4577 STATIC_ASSERT(EQUAL != 1); | |
| 4578 __ setcc(above_equal, eax); | |
| 4579 __ ret(0); | |
| 4580 } else { | |
| 4581 Label nan; | |
| 4582 __ j(above_equal, &nan, Label::kNear); | |
| 4583 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | |
| 4584 __ ret(0); | |
| 4585 __ bind(&nan); | |
| 4586 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); | |
| 4587 __ ret(0); | |
| 4588 } | |
| 4589 | 4558 |
| 4590 __ bind(¬_identical); | 4559 __ bind(¬_identical); |
| 4591 } | 4560 } |
| 4592 | 4561 |
| 4593 // Strict equality can quickly decide whether objects are equal. | 4562 // Strict equality can quickly decide whether objects are equal. |
| 4594 // Non-strict object equality is slower, so it is handled later in the stub. | 4563 // Non-strict object equality is slower, so it is handled later in the stub. |
| 4595 if (cc == equal && strict()) { | 4564 if (cc == equal && strict()) { |
| 4596 Label slow; // Fallthrough label. | 4565 Label slow; // Fallthrough label. |
| 4597 Label not_smis; | 4566 Label not_smis; |
| 4598 // If we're doing a strict equality comparison, we don't have to do | 4567 // If we're doing a strict equality comparison, we don't have to do |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4658 __ CmpInstanceType(ecx, ODDBALL_TYPE); | 4627 __ CmpInstanceType(ecx, ODDBALL_TYPE); |
| 4659 __ j(equal, &return_not_equal); | 4628 __ j(equal, &return_not_equal); |
| 4660 | 4629 |
| 4661 // Fall through to the general case. | 4630 // Fall through to the general case. |
| 4662 __ bind(&slow); | 4631 __ bind(&slow); |
| 4663 } | 4632 } |
| 4664 | 4633 |
| 4665 // Generate the number comparison code. | 4634 // Generate the number comparison code. |
| 4666 Label non_number_comparison; | 4635 Label non_number_comparison; |
| 4667 Label unordered; | 4636 Label unordered; |
| 4637 __ bind(&generic_heap_number_comparison); |
| 4668 if (CpuFeatures::IsSupported(SSE2)) { | 4638 if (CpuFeatures::IsSupported(SSE2)) { |
| 4669 CpuFeatureScope use_sse2(masm, SSE2); | 4639 CpuFeatureScope use_sse2(masm, SSE2); |
| 4670 CpuFeatureScope use_cmov(masm, CMOV); | 4640 CpuFeatureScope use_cmov(masm, CMOV); |
| 4671 | 4641 |
| 4672 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison); | 4642 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison); |
| 4673 __ ucomisd(xmm0, xmm1); | 4643 __ ucomisd(xmm0, xmm1); |
| 4674 | 4644 |
| 4675 // Don't base result on EFLAGS when a NaN is involved. | 4645 // Don't base result on EFLAGS when a NaN is involved. |
| 4676 __ j(parity_even, &unordered, Label::kNear); | 4646 __ j(parity_even, &unordered, Label::kNear); |
| 4677 // Return a result of -1, 0, or 1, based on EFLAGS. | 4647 // Return a result of -1, 0, or 1, based on EFLAGS. |
| (...skipping 3184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7862 // Restore ecx. | 7832 // Restore ecx. |
| 7863 __ pop(ecx); | 7833 __ pop(ecx); |
| 7864 __ ret(0); | 7834 __ ret(0); |
| 7865 } | 7835 } |
| 7866 | 7836 |
| 7867 #undef __ | 7837 #undef __ |
| 7868 | 7838 |
| 7869 } } // namespace v8::internal | 7839 } } // namespace v8::internal |
| 7870 | 7840 |
| 7871 #endif // V8_TARGET_ARCH_IA32 | 7841 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |