Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(178)

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 2805046: Decide that different detectable objects are not equal without calling runtim... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/codegen-arm.cc ('k') | src/x64/codegen-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 11638 matching lines...) Expand 10 before | Expand all | Expand 10 after
11649 11649
11650 static int NegativeComparisonResult(Condition cc) { 11650 static int NegativeComparisonResult(Condition cc) {
11651 ASSERT(cc != equal); 11651 ASSERT(cc != equal);
11652 ASSERT((cc == less) || (cc == less_equal) 11652 ASSERT((cc == less) || (cc == less_equal)
11653 || (cc == greater) || (cc == greater_equal)); 11653 || (cc == greater) || (cc == greater_equal));
11654 return (cc == greater || cc == greater_equal) ? LESS : GREATER; 11654 return (cc == greater || cc == greater_equal) ? LESS : GREATER;
11655 } 11655 }
11656 11656
11657 11657
11658 void CompareStub::Generate(MacroAssembler* masm) { 11658 void CompareStub::Generate(MacroAssembler* masm) {
11659 Label call_builtin, done; 11659 Label check_unequal_objects, done;
11660 11660
11661 // NOTICE! This code is only reached after a smi-fast-case check, so 11661 // NOTICE! This code is only reached after a smi-fast-case check, so
11662 // it is certain that at least one operand isn't a smi. 11662 // it is certain that at least one operand isn't a smi.
11663 11663
11664 // Identical objects can be compared fast, but there are some tricky cases 11664 // Identical objects can be compared fast, but there are some tricky cases
11665 // for NaN and undefined. 11665 // for NaN and undefined.
11666 { 11666 {
11667 Label not_identical; 11667 Label not_identical;
11668 __ cmp(eax, Operand(edx)); 11668 __ cmp(eax, Operand(edx));
11669 __ j(not_equal, &not_identical); 11669 __ j(not_equal, &not_identical);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
11727 __ ret(0); 11727 __ ret(0);
11728 __ bind(&nan); 11728 __ bind(&nan);
11729 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); 11729 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_))));
11730 __ ret(0); 11730 __ ret(0);
11731 } 11731 }
11732 } 11732 }
11733 11733
11734 __ bind(&not_identical); 11734 __ bind(&not_identical);
11735 } 11735 }
11736 11736
11737 if (cc_ == equal) { // Both strict and non-strict. 11737 // Strict equality can quickly decide whether objects are equal.
11738 // Non-strict object equality is slower, so it is handled later in the stub.
11739 if (cc_ == equal && strict_) {
11738 Label slow; // Fallthrough label. 11740 Label slow; // Fallthrough label.
11739 11741 Label not_smis;
11740 // If we're doing a strict equality comparison, we don't have to do 11742 // If we're doing a strict equality comparison, we don't have to do
11741 // type conversion, so we generate code to do fast comparison for objects 11743 // type conversion, so we generate code to do fast comparison for objects
11742 // and oddballs. Non-smi numbers and strings still go through the usual 11744 // and oddballs. Non-smi numbers and strings still go through the usual
11743 // slow-case code. 11745 // slow-case code.
11744 if (strict_) { 11746 // If either is a Smi (we know that not both are), then they can only
11745 // If either is a Smi (we know that not both are), then they can only 11747 // be equal if the other is a HeapNumber. If so, use the slow case.
11746 // be equal if the other is a HeapNumber. If so, use the slow case. 11748 ASSERT_EQ(0, kSmiTag);
11747 { 11749 ASSERT_EQ(0, Smi::FromInt(0));
11748 Label not_smis; 11750 __ mov(ecx, Immediate(kSmiTagMask));
11749 ASSERT_EQ(0, kSmiTag); 11751 __ and_(ecx, Operand(eax));
11750 ASSERT_EQ(0, Smi::FromInt(0)); 11752 __ test(ecx, Operand(edx));
11751 __ mov(ecx, Immediate(kSmiTagMask)); 11753 __ j(not_zero, &not_smis);
11752 __ and_(ecx, Operand(eax)); 11754 // One operand is a smi.
11753 __ test(ecx, Operand(edx));
11754 __ j(not_zero, &not_smis);
11755 // One operand is a smi.
11756 11755
11757 // Check whether the non-smi is a heap number. 11756 // Check whether the non-smi is a heap number.
11758 ASSERT_EQ(1, kSmiTagMask); 11757 ASSERT_EQ(1, kSmiTagMask);
11759 // ecx still holds eax & kSmiTag, which is either zero or one. 11758 // ecx still holds eax & kSmiTag, which is either zero or one.
11760 __ sub(Operand(ecx), Immediate(0x01)); 11759 __ sub(Operand(ecx), Immediate(0x01));
11761 __ mov(ebx, edx); 11760 __ mov(ebx, edx);
11762 __ xor_(ebx, Operand(eax)); 11761 __ xor_(ebx, Operand(eax));
11763 __ and_(ebx, Operand(ecx)); // ebx holds either 0 or eax ^ edx. 11762 __ and_(ebx, Operand(ecx)); // ebx holds either 0 or eax ^ edx.
11764 __ xor_(ebx, Operand(eax)); 11763 __ xor_(ebx, Operand(eax));
11765 // if eax was smi, ebx is now edx, else eax. 11764 // if eax was smi, ebx is now edx, else eax.
11766 11765
11767 // Check if the non-smi operand is a heap number. 11766 // Check if the non-smi operand is a heap number.
11768 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 11767 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
11769 Immediate(Factory::heap_number_map())); 11768 Immediate(Factory::heap_number_map()));
11770 // If heap number, handle it in the slow case. 11769 // If heap number, handle it in the slow case.
11771 __ j(equal, &slow); 11770 __ j(equal, &slow);
11772 // Return non-equal (ebx is not zero) 11771 // Return non-equal (ebx is not zero)
11773 __ mov(eax, ebx); 11772 __ mov(eax, ebx);
11774 __ ret(0); 11773 __ ret(0);
11775 11774
11776 __ bind(&not_smis); 11775 __ bind(&not_smis);
11777 } 11776 // If either operand is a JSObject or an oddball value, then they are not
11777 // equal since their pointers are different
11778 // There is no test for undetectability in strict equality.
11778 11779
11779 // If either operand is a JSObject or an oddball value, then they are not 11780 // Get the type of the first operand.
11780 // equal since their pointers are different 11781 // If the first object is a JS object, we have done pointer comparison.
11781 // There is no test for undetectability in strict equality. 11782 Label first_non_object;
11783 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
11784 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
11785 __ j(below, &first_non_object);
11782 11786
11783 // Get the type of the first operand. 11787 // Return non-zero (eax is not zero)
11784 // If the first object is a JS object, we have done pointer comparison. 11788 Label return_not_equal;
11785 Label first_non_object; 11789 ASSERT(kHeapObjectTag != 0);
11786 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 11790 __ bind(&return_not_equal);
11787 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); 11791 __ ret(0);
11788 __ j(below, &first_non_object);
11789 11792
11790 // Return non-zero (eax is not zero) 11793 __ bind(&first_non_object);
11791 Label return_not_equal; 11794 // Check for oddballs: true, false, null, undefined.
11792 ASSERT(kHeapObjectTag != 0); 11795 __ CmpInstanceType(ecx, ODDBALL_TYPE);
11793 __ bind(&return_not_equal); 11796 __ j(equal, &return_not_equal);
11794 __ ret(0);
11795 11797
11796 __ bind(&first_non_object); 11798 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ecx);
11797 // Check for oddballs: true, false, null, undefined. 11799 __ j(above_equal, &return_not_equal);
11798 __ CmpInstanceType(ecx, ODDBALL_TYPE);
11799 __ j(equal, &return_not_equal);
11800 11800
11801 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ecx); 11801 // Check for oddballs: true, false, null, undefined.
11802 __ j(above_equal, &return_not_equal); 11802 __ CmpInstanceType(ecx, ODDBALL_TYPE);
11803 __ j(equal, &return_not_equal);
11803 11804
11804 // Check for oddballs: true, false, null, undefined. 11805 // Fall through to the general case.
11805 __ CmpInstanceType(ecx, ODDBALL_TYPE);
11806 __ j(equal, &return_not_equal);
11807
11808 // Fall through to the general case.
11809 }
11810 __ bind(&slow); 11806 __ bind(&slow);
11811 } 11807 }
11812 11808
11813 // Push arguments below the return address. 11809 // Push arguments below the return address.
11814 __ pop(ecx); 11810 __ pop(ecx);
11815 __ push(eax); 11811 __ push(eax);
11816 __ push(edx); 11812 __ push(edx);
11817 __ push(ecx); 11813 __ push(ecx);
11818 11814
11819 // Generate the number comparison code. 11815 // Generate the number comparison code.
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
11886 BranchIfNonSymbol(masm, &check_for_strings, edx, ecx); 11882 BranchIfNonSymbol(masm, &check_for_strings, edx, ecx);
11887 11883
11888 // We've already checked for object identity, so if both operands 11884 // We've already checked for object identity, so if both operands
11889 // are symbols they aren't equal. Register eax already holds a 11885 // are symbols they aren't equal. Register eax already holds a
11890 // non-zero value, which indicates not equal, so just return. 11886 // non-zero value, which indicates not equal, so just return.
11891 __ ret(2 * kPointerSize); 11887 __ ret(2 * kPointerSize);
11892 } 11888 }
11893 11889
11894 __ bind(&check_for_strings); 11890 __ bind(&check_for_strings);
11895 11891
11896 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &call_builtin); 11892 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx,
11893 &check_unequal_objects);
11897 11894
11898 // Inline comparison of ascii strings. 11895 // Inline comparison of ascii strings.
11899 StringCompareStub::GenerateCompareFlatAsciiStrings(masm, 11896 StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
11900 edx, 11897 edx,
11901 eax, 11898 eax,
11902 ecx, 11899 ecx,
11903 ebx, 11900 ebx,
11904 edi); 11901 edi);
11905 #ifdef DEBUG 11902 #ifdef DEBUG
11906 __ Abort("Unexpected fall-through from string comparison"); 11903 __ Abort("Unexpected fall-through from string comparison");
11907 #endif 11904 #endif
11908 11905
11909 __ bind(&call_builtin); 11906 __ bind(&check_unequal_objects);
11907 if (cc_ == equal && !strict_) {
11908 // Non-strict equality. Objects are unequal if
11909 // they are both JSObjects and not undetectable,
11910 // and their pointers are different.
11911 Label not_both_objects;
11912 Label return_unequal;
11913 // At most one is a smi, so we can test for smi by adding the two.
11914 // A smi plus a heap object has the low bit set, a heap object plus
11915 // a heap object has the low bit clear.
11916 ASSERT_EQ(0, kSmiTag);
11917 ASSERT_EQ(1, kSmiTagMask);
11918 __ lea(ecx, Operand(eax, edx, times_1, 0));
11919 __ test(ecx, Immediate(kSmiTagMask));
11920 __ j(not_zero, &not_both_objects);
11921 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
11922 __ j(below, &not_both_objects);
11923 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ebx);
11924 __ j(below, &not_both_objects);
11925 // We do not bail out after this point. Both are JSObjects, and
11926 // they are equal if and only if both are undetectable.
11927 // The and of the undetectable flags is 1 if and only if they are equal.
11928 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset),
11929 1 << Map::kIsUndetectable);
11930 __ j(zero, &return_unequal);
11931 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset),
11932 1 << Map::kIsUndetectable);
11933 __ j(zero, &return_unequal);
11934 // The objects are both undetectable, so they both compare as the value
11935 // undefined, and are equal.
11936 __ Set(eax, Immediate(EQUAL));
11937 __ bind(&return_unequal);
11938 // Return non-equal by returning the non-zero object pointer in eax,
11939 // or return equal if we fell through to here.
11940 __ ret(2 * kPointerSize); // rax, rdx were pushed
11941 __ bind(&not_both_objects);
11942 }
11943
11910 // must swap argument order 11944 // must swap argument order
11911 __ pop(ecx); 11945 __ pop(ecx);
11912 __ pop(edx); 11946 __ pop(edx);
11913 __ pop(eax); 11947 __ pop(eax);
11914 __ push(edx); 11948 __ push(edx);
11915 __ push(eax); 11949 __ push(eax);
11916 11950
11917 // Figure out which native to call and setup the arguments. 11951 // Figure out which native to call and setup the arguments.
11918 Builtins::JavaScript builtin; 11952 Builtins::JavaScript builtin;
11919 if (cc_ == equal) { 11953 if (cc_ == equal) {
(...skipping 1816 matching lines...) Expand 10 before | Expand all | Expand 10 after
13736 masm.GetCode(&desc); 13770 masm.GetCode(&desc);
13737 // Call the function from C++. 13771 // Call the function from C++.
13738 return FUNCTION_CAST<MemCopyFunction>(buffer); 13772 return FUNCTION_CAST<MemCopyFunction>(buffer);
13739 } 13773 }
13740 13774
13741 #undef __ 13775 #undef __
13742 13776
13743 } } // namespace v8::internal 13777 } } // namespace v8::internal
13744 13778
13745 #endif // V8_TARGET_ARCH_IA32 13779 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.cc ('k') | src/x64/codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698