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