OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 11821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11832 __ j(above_equal, &return_not_equal); | 11832 __ j(above_equal, &return_not_equal); |
11833 | 11833 |
11834 // Check for oddballs: true, false, null, undefined. | 11834 // Check for oddballs: true, false, null, undefined. |
11835 __ CmpInstanceType(ecx, ODDBALL_TYPE); | 11835 __ CmpInstanceType(ecx, ODDBALL_TYPE); |
11836 __ j(equal, &return_not_equal); | 11836 __ j(equal, &return_not_equal); |
11837 | 11837 |
11838 // Fall through to the general case. | 11838 // Fall through to the general case. |
11839 __ bind(&slow); | 11839 __ bind(&slow); |
11840 } | 11840 } |
11841 | 11841 |
| 11842 // Push arguments below the return address. |
| 11843 __ pop(ecx); |
| 11844 __ push(eax); |
| 11845 __ push(edx); |
| 11846 __ push(ecx); |
| 11847 |
11842 // Generate the number comparison code. | 11848 // Generate the number comparison code. |
11843 if (include_number_compare_) { | 11849 if (include_number_compare_) { |
11844 Label non_number_comparison; | 11850 Label non_number_comparison; |
11845 Label unordered; | 11851 Label unordered; |
11846 if (CpuFeatures::IsSupported(SSE2)) { | 11852 if (CpuFeatures::IsSupported(SSE2)) { |
11847 CpuFeatures::Scope use_sse2(SSE2); | 11853 CpuFeatures::Scope use_sse2(SSE2); |
11848 CpuFeatures::Scope use_cmov(CMOV); | 11854 CpuFeatures::Scope use_cmov(CMOV); |
11849 | 11855 |
11850 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison); | 11856 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison); |
11851 __ ucomisd(xmm0, xmm1); | 11857 __ ucomisd(xmm0, xmm1); |
11852 | 11858 |
11853 // Don't base result on EFLAGS when a NaN is involved. | 11859 // Don't base result on EFLAGS when a NaN is involved. |
11854 __ j(parity_even, &unordered, not_taken); | 11860 __ j(parity_even, &unordered, not_taken); |
11855 // Return a result of -1, 0, or 1, based on EFLAGS. | 11861 // Return a result of -1, 0, or 1, based on EFLAGS. |
11856 __ mov(eax, 0); // equal | 11862 __ mov(eax, 0); // equal |
11857 __ mov(ecx, Immediate(Smi::FromInt(1))); | 11863 __ mov(ecx, Immediate(Smi::FromInt(1))); |
11858 __ cmov(above, eax, Operand(ecx)); | 11864 __ cmov(above, eax, Operand(ecx)); |
11859 __ mov(ecx, Immediate(Smi::FromInt(-1))); | 11865 __ mov(ecx, Immediate(Smi::FromInt(-1))); |
11860 __ cmov(below, eax, Operand(ecx)); | 11866 __ cmov(below, eax, Operand(ecx)); |
11861 __ ret(0); | 11867 __ ret(2 * kPointerSize); |
11862 } else { | 11868 } else { |
11863 FloatingPointHelper::CheckFloatOperands( | 11869 FloatingPointHelper::CheckFloatOperands( |
11864 masm, &non_number_comparison, ebx); | 11870 masm, &non_number_comparison, ebx); |
11865 FloatingPointHelper::LoadFloatOperands(masm, ecx); | 11871 FloatingPointHelper::LoadFloatOperands(masm, ecx); |
11866 __ FCmp(); | 11872 __ FCmp(); |
11867 | 11873 |
11868 // Don't base result on EFLAGS when a NaN is involved. | 11874 // Don't base result on EFLAGS when a NaN is involved. |
11869 __ j(parity_even, &unordered, not_taken); | 11875 __ j(parity_even, &unordered, not_taken); |
11870 | 11876 |
11871 Label below_label, above_label; | 11877 Label below_label, above_label; |
11872 // Return a result of -1, 0, or 1, based on EFLAGS. | 11878 // Return a result of -1, 0, or 1, based on EFLAGS. In all cases remove |
| 11879 // two arguments from the stack as they have been pushed in preparation |
| 11880 // of a possible runtime call. |
11873 __ j(below, &below_label, not_taken); | 11881 __ j(below, &below_label, not_taken); |
11874 __ j(above, &above_label, not_taken); | 11882 __ j(above, &above_label, not_taken); |
11875 | 11883 |
11876 __ xor_(eax, Operand(eax)); | 11884 __ xor_(eax, Operand(eax)); |
11877 __ ret(0); | 11885 __ ret(2 * kPointerSize); |
11878 | 11886 |
11879 __ bind(&below_label); | 11887 __ bind(&below_label); |
11880 __ mov(eax, Immediate(Smi::FromInt(-1))); | 11888 __ mov(eax, Immediate(Smi::FromInt(-1))); |
11881 __ ret(0); | 11889 __ ret(2 * kPointerSize); |
11882 | 11890 |
11883 __ bind(&above_label); | 11891 __ bind(&above_label); |
11884 __ mov(eax, Immediate(Smi::FromInt(1))); | 11892 __ mov(eax, Immediate(Smi::FromInt(1))); |
11885 __ ret(0); | 11893 __ ret(2 * kPointerSize); |
11886 } | 11894 } |
11887 | 11895 |
11888 // If one of the numbers was NaN, then the result is always false. | 11896 // If one of the numbers was NaN, then the result is always false. |
11889 // The cc is never not-equal. | 11897 // The cc is never not-equal. |
11890 __ bind(&unordered); | 11898 __ bind(&unordered); |
11891 ASSERT(cc_ != not_equal); | 11899 ASSERT(cc_ != not_equal); |
11892 if (cc_ == less || cc_ == less_equal) { | 11900 if (cc_ == less || cc_ == less_equal) { |
11893 __ mov(eax, Immediate(Smi::FromInt(1))); | 11901 __ mov(eax, Immediate(Smi::FromInt(1))); |
11894 } else { | 11902 } else { |
11895 __ mov(eax, Immediate(Smi::FromInt(-1))); | 11903 __ mov(eax, Immediate(Smi::FromInt(-1))); |
11896 } | 11904 } |
11897 __ ret(0); | 11905 __ ret(2 * kPointerSize); // eax, edx were pushed |
11898 | 11906 |
11899 // The number comparison code did not provide a valid result. | 11907 // The number comparison code did not provide a valid result. |
11900 __ bind(&non_number_comparison); | 11908 __ bind(&non_number_comparison); |
11901 } | 11909 } |
11902 | 11910 |
11903 // Fast negative check for symbol-to-symbol equality. | 11911 // Fast negative check for symbol-to-symbol equality. |
11904 Label check_for_strings; | 11912 Label check_for_strings; |
11905 if (cc_ == equal) { | 11913 if (cc_ == equal) { |
11906 BranchIfNonSymbol(masm, &check_for_strings, eax, ecx); | 11914 BranchIfNonSymbol(masm, &check_for_strings, eax, ecx); |
11907 BranchIfNonSymbol(masm, &check_for_strings, edx, ecx); | 11915 BranchIfNonSymbol(masm, &check_for_strings, edx, ecx); |
11908 | 11916 |
11909 // We've already checked for object identity, so if both operands | 11917 // We've already checked for object identity, so if both operands |
11910 // are symbols they aren't equal. Register eax already holds a | 11918 // are symbols they aren't equal. Register eax already holds a |
11911 // non-zero value, which indicates not equal, so just return. | 11919 // non-zero value, which indicates not equal, so just return. |
11912 __ ret(0); | 11920 __ ret(2 * kPointerSize); |
11913 } | 11921 } |
11914 | 11922 |
11915 __ bind(&check_for_strings); | 11923 __ bind(&check_for_strings); |
11916 | 11924 |
11917 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, | 11925 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, |
11918 &check_unequal_objects); | 11926 &check_unequal_objects); |
11919 | 11927 |
11920 // Inline comparison of ascii strings. | 11928 // Inline comparison of ascii strings. |
11921 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, | 11929 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, |
11922 edx, | 11930 edx, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11955 __ j(zero, &return_unequal); | 11963 __ j(zero, &return_unequal); |
11956 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), | 11964 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), |
11957 1 << Map::kIsUndetectable); | 11965 1 << Map::kIsUndetectable); |
11958 __ j(zero, &return_unequal); | 11966 __ j(zero, &return_unequal); |
11959 // The objects are both undetectable, so they both compare as the value | 11967 // The objects are both undetectable, so they both compare as the value |
11960 // undefined, and are equal. | 11968 // undefined, and are equal. |
11961 __ Set(eax, Immediate(EQUAL)); | 11969 __ Set(eax, Immediate(EQUAL)); |
11962 __ bind(&return_unequal); | 11970 __ bind(&return_unequal); |
11963 // Return non-equal by returning the non-zero object pointer in eax, | 11971 // Return non-equal by returning the non-zero object pointer in eax, |
11964 // or return equal if we fell through to here. | 11972 // or return equal if we fell through to here. |
11965 __ ret(0); // rax, rdx were pushed | 11973 __ ret(2 * kPointerSize); // rax, rdx were pushed |
11966 __ bind(¬_both_objects); | 11974 __ bind(¬_both_objects); |
11967 } | 11975 } |
11968 | 11976 |
11969 // Push arguments below the return address. | 11977 // must swap argument order |
11970 __ pop(ecx); | 11978 __ pop(ecx); |
| 11979 __ pop(edx); |
| 11980 __ pop(eax); |
11971 __ push(edx); | 11981 __ push(edx); |
11972 __ push(eax); | 11982 __ push(eax); |
11973 | 11983 |
11974 // Figure out which native to call and setup the arguments. | 11984 // Figure out which native to call and setup the arguments. |
11975 Builtins::JavaScript builtin; | 11985 Builtins::JavaScript builtin; |
11976 if (cc_ == equal) { | 11986 if (cc_ == equal) { |
11977 builtin = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS; | 11987 builtin = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS; |
11978 } else { | 11988 } else { |
11979 builtin = Builtins::COMPARE; | 11989 builtin = Builtins::COMPARE; |
11980 __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); | 11990 __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); |
(...skipping 1556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13537 | 13547 |
13538 // Compare lengths - strings up to min-length are equal. | 13548 // Compare lengths - strings up to min-length are equal. |
13539 __ bind(&compare_lengths); | 13549 __ bind(&compare_lengths); |
13540 __ test(length_delta, Operand(length_delta)); | 13550 __ test(length_delta, Operand(length_delta)); |
13541 __ j(not_zero, &result_not_equal); | 13551 __ j(not_zero, &result_not_equal); |
13542 | 13552 |
13543 // Result is EQUAL. | 13553 // Result is EQUAL. |
13544 ASSERT_EQ(0, EQUAL); | 13554 ASSERT_EQ(0, EQUAL); |
13545 ASSERT_EQ(0, kSmiTag); | 13555 ASSERT_EQ(0, kSmiTag); |
13546 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 13556 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
13547 __ ret(0); | 13557 __ ret(2 * kPointerSize); |
13548 | 13558 |
13549 __ bind(&result_not_equal); | 13559 __ bind(&result_not_equal); |
13550 __ j(greater, &result_greater); | 13560 __ j(greater, &result_greater); |
13551 | 13561 |
13552 // Result is LESS. | 13562 // Result is LESS. |
13553 __ Set(eax, Immediate(Smi::FromInt(LESS))); | 13563 __ Set(eax, Immediate(Smi::FromInt(LESS))); |
13554 __ ret(0); | 13564 __ ret(2 * kPointerSize); |
13555 | 13565 |
13556 // Result is GREATER. | 13566 // Result is GREATER. |
13557 __ bind(&result_greater); | 13567 __ bind(&result_greater); |
13558 __ Set(eax, Immediate(Smi::FromInt(GREATER))); | 13568 __ Set(eax, Immediate(Smi::FromInt(GREATER))); |
13559 __ ret(0); | 13569 __ ret(2 * kPointerSize); |
13560 } | 13570 } |
13561 | 13571 |
13562 | 13572 |
13563 void StringCompareStub::Generate(MacroAssembler* masm) { | 13573 void StringCompareStub::Generate(MacroAssembler* masm) { |
13564 Label runtime; | 13574 Label runtime; |
13565 | 13575 |
13566 // Stack frame on entry. | 13576 // Stack frame on entry. |
13567 // esp[0]: return address | 13577 // esp[0]: return address |
13568 // esp[4]: right string | 13578 // esp[4]: right string |
13569 // esp[8]: left string | 13579 // esp[8]: left string |
13570 | 13580 |
13571 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left | 13581 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left |
13572 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right | 13582 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right |
13573 | 13583 |
13574 Label not_same; | 13584 Label not_same; |
13575 __ cmp(edx, Operand(eax)); | 13585 __ cmp(edx, Operand(eax)); |
13576 __ j(not_equal, ¬_same); | 13586 __ j(not_equal, ¬_same); |
13577 ASSERT_EQ(0, EQUAL); | 13587 ASSERT_EQ(0, EQUAL); |
13578 ASSERT_EQ(0, kSmiTag); | 13588 ASSERT_EQ(0, kSmiTag); |
13579 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 13589 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
13580 __ IncrementCounter(&Counters::string_compare_native, 1); | 13590 __ IncrementCounter(&Counters::string_compare_native, 1); |
13581 __ ret(2 * kPointerSize); | 13591 __ ret(2 * kPointerSize); |
13582 | 13592 |
13583 __ bind(¬_same); | 13593 __ bind(¬_same); |
13584 | 13594 |
13585 // Check that both objects are sequential ascii strings. | 13595 // Check that both objects are sequential ascii strings. |
13586 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime); | 13596 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime); |
13587 | 13597 |
13588 // Compare flat ascii strings. | 13598 // Compare flat ascii strings. |
13589 // Drop arguments from the stack. | |
13590 __ pop(ecx); | |
13591 __ add(Operand(esp), Immediate(2 * kPointerSize)); | |
13592 __ push(ecx); | |
13593 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); | 13599 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); |
13594 | 13600 |
13595 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 13601 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
13596 // tagged as a small integer. | 13602 // tagged as a small integer. |
13597 __ bind(&runtime); | 13603 __ bind(&runtime); |
13598 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 13604 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
13599 } | 13605 } |
13600 | 13606 |
13601 #undef __ | 13607 #undef __ |
13602 | 13608 |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13801 masm.GetCode(&desc); | 13807 masm.GetCode(&desc); |
13802 // Call the function from C++. | 13808 // Call the function from C++. |
13803 return FUNCTION_CAST<MemCopyFunction>(buffer); | 13809 return FUNCTION_CAST<MemCopyFunction>(buffer); |
13804 } | 13810 } |
13805 | 13811 |
13806 #undef __ | 13812 #undef __ |
13807 | 13813 |
13808 } } // namespace v8::internal | 13814 } } // namespace v8::internal |
13809 | 13815 |
13810 #endif // V8_TARGET_ARCH_IA32 | 13816 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |