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 |