| 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 11638 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 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, ¬_identical); | 11669     __ j(not_equal, ¬_identical); | 
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 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(¬_identical); | 11734     __ bind(¬_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, ¬_smis); | 
| 11752         __ and_(ecx, Operand(eax)); | 11754     // One operand is a smi. | 
| 11753         __ test(ecx, Operand(edx)); |  | 
| 11754         __ j(not_zero, ¬_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(¬_smis); | 11775     __ bind(¬_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  Loading... | 
| 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, ¬_both_objects); | 
|  | 11921     __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); | 
|  | 11922     __ j(below, ¬_both_objects); | 
|  | 11923     __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ebx); | 
|  | 11924     __ j(below, ¬_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(¬_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  Loading... | 
| 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 | 
| OLD | NEW | 
|---|