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

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

Issue 551048: Very small optimization of ARM compare stub. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 11 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 | « no previous file | src/arm/fast-codegen-arm.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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 29 matching lines...) Expand all
40 namespace v8 { 40 namespace v8 {
41 namespace internal { 41 namespace internal {
42 42
43 #define __ ACCESS_MASM(masm_) 43 #define __ ACCESS_MASM(masm_)
44 44
45 static void EmitIdenticalObjectComparison(MacroAssembler* masm, 45 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
46 Label* slow, 46 Label* slow,
47 Condition cc, 47 Condition cc,
48 bool never_nan_nan); 48 bool never_nan_nan);
49 static void EmitSmiNonsmiComparison(MacroAssembler* masm, 49 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
50 Label* rhs_not_nan, 50 Label* lhs_not_nan,
51 Label* slow, 51 Label* slow,
52 bool strict); 52 bool strict);
53 static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc); 53 static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc);
54 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm); 54 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm);
55 static void MultiplyByKnownInt(MacroAssembler* masm, 55 static void MultiplyByKnownInt(MacroAssembler* masm,
56 Register source, 56 Register source,
57 Register destination, 57 Register destination,
58 int known_int); 58 int known_int);
59 static bool IsEasyToMultiplyBy(int x); 59 static bool IsEasyToMultiplyBy(int x);
60 60
(...skipping 4710 matching lines...) Expand 10 before | Expand all | Expand 10 after
4771 } 4771 }
4772 } 4772 }
4773 } 4773 }
4774 4774
4775 __ bind(&return_equal); 4775 __ bind(&return_equal);
4776 if (cc == lt) { 4776 if (cc == lt) {
4777 __ mov(r0, Operand(GREATER)); // Things aren't less than themselves. 4777 __ mov(r0, Operand(GREATER)); // Things aren't less than themselves.
4778 } else if (cc == gt) { 4778 } else if (cc == gt) {
4779 __ mov(r0, Operand(LESS)); // Things aren't greater than themselves. 4779 __ mov(r0, Operand(LESS)); // Things aren't greater than themselves.
4780 } else { 4780 } else {
4781 __ mov(r0, Operand(0)); // Things are <=, >=, ==, === themselves. 4781 __ mov(r0, Operand(EQUAL)); // Things are <=, >=, ==, === themselves.
4782 } 4782 }
4783 __ mov(pc, Operand(lr)); // Return. 4783 __ mov(pc, Operand(lr)); // Return.
4784 4784
4785 if (cc != eq || !never_nan_nan) { 4785 if (cc != eq || !never_nan_nan) {
4786 // For less and greater we don't have to check for NaN since the result of 4786 // For less and greater we don't have to check for NaN since the result of
4787 // x < x is false regardless. For the others here is some code to check 4787 // x < x is false regardless. For the others here is some code to check
4788 // for NaN. 4788 // for NaN.
4789 if (cc != lt && cc != gt) { 4789 if (cc != lt && cc != gt) {
4790 __ bind(&heap_number); 4790 __ bind(&heap_number);
4791 // It is a heap number, so return non-equal if it's NaN and equal if it's 4791 // It is a heap number, so return non-equal if it's NaN and equal if it's
4792 // not NaN. 4792 // not NaN.
4793
4793 // The representation of NaN values has all exponent bits (52..62) set, 4794 // The representation of NaN values has all exponent bits (52..62) set,
4794 // and not all mantissa bits (0..51) clear. 4795 // and not all mantissa bits (0..51) clear.
4795 // Read top bits of double representation (second word of value). 4796 // Read top bits of double representation (second word of value).
4796 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 4797 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
4797 // Test that exponent bits are all set. 4798 // Test that exponent bits are all set.
4798 __ and_(r3, r2, Operand(exp_mask_reg)); 4799 __ and_(r3, r2, Operand(exp_mask_reg));
4799 __ cmp(r3, Operand(exp_mask_reg)); 4800 __ cmp(r3, Operand(exp_mask_reg));
4800 __ b(ne, &return_equal); 4801 __ b(ne, &return_equal);
4801 4802
4802 // Shift out flag and all exponent bits, retaining only mantissa. 4803 // Shift out flag and all exponent bits, retaining only mantissa.
4803 __ mov(r2, Operand(r2, LSL, HeapNumber::kNonMantissaBitsInTopWord)); 4804 __ mov(r2, Operand(r2, LSL, HeapNumber::kNonMantissaBitsInTopWord));
4804 // Or with all low-bits of mantissa. 4805 // Or with all low-bits of mantissa.
4805 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 4806 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
4806 __ orr(r0, r3, Operand(r2), SetCC); 4807 __ orr(r0, r3, Operand(r2), SetCC);
4807 // For equal we already have the right value in r0: Return zero (equal) 4808 // For equal we already have the right value in r0: Return zero (equal)
4808 // if all bits in mantissa are zero (it's an Infinity) and non-zero if not 4809 // if all bits in mantissa are zero (it's an Infinity) and non-zero if
4809 // (it's a NaN). For <= and >= we need to load r0 with the failing value 4810 // not (it's a NaN). For <= and >= we need to load r0 with the failing
4810 // if it's a NaN. 4811 // value if it's a NaN.
4811 if (cc != eq) { 4812 if (cc != eq) {
4812 // All-zero means Infinity means equal. 4813 // All-zero means Infinity means equal.
4813 __ mov(pc, Operand(lr), LeaveCC, eq); // Return equal 4814 __ mov(pc, Operand(lr), LeaveCC, eq); // Return equal
4814 if (cc == le) { 4815 if (cc == le) {
4815 __ mov(r0, Operand(GREATER)); // NaN <= NaN should fail. 4816 __ mov(r0, Operand(GREATER)); // NaN <= NaN should fail.
4816 } else { 4817 } else {
4817 __ mov(r0, Operand(LESS)); // NaN >= NaN should fail. 4818 __ mov(r0, Operand(LESS)); // NaN >= NaN should fail.
4818 } 4819 }
4819 } 4820 }
4820 __ mov(pc, Operand(lr)); // Return. 4821 __ mov(pc, Operand(lr)); // Return.
4821 } 4822 }
4822 // No fall through here. 4823 // No fall through here.
4823 } 4824 }
4824 4825
4825 __ bind(&not_identical); 4826 __ bind(&not_identical);
4826 } 4827 }
4827 4828
4828 4829
4829 // See comment at call site. 4830 // See comment at call site.
4830 static void EmitSmiNonsmiComparison(MacroAssembler* masm, 4831 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
4831 Label* rhs_not_nan, 4832 Label* lhs_not_nan,
4832 Label* slow, 4833 Label* slow,
4833 bool strict) { 4834 bool strict) {
4834 Label lhs_is_smi; 4835 Label lhs_is_smi;
4835 __ tst(r0, Operand(kSmiTagMask)); 4836 __ tst(r0, Operand(kSmiTagMask));
4836 __ b(eq, &lhs_is_smi); 4837 __ b(eq, &lhs_is_smi);
4837 4838
4838 // Rhs is a Smi. Check whether the non-smi is a heap number. 4839 // Rhs is a Smi. Check whether the non-smi is a heap number.
4839 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE); 4840 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE);
4840 if (strict) { 4841 if (strict) {
4841 // If lhs was not a number and rhs was a Smi then strict equality cannot 4842 // If lhs was not a number and rhs was a Smi then strict equality cannot
(...skipping 17 matching lines...) Expand all
4859 __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET); 4860 __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
4860 } 4861 }
4861 4862
4862 4863
4863 // r3 and r2 are rhs as double. 4864 // r3 and r2 are rhs as double.
4864 __ ldr(r1, FieldMemOperand(r0, HeapNumber::kValueOffset + kPointerSize)); 4865 __ ldr(r1, FieldMemOperand(r0, HeapNumber::kValueOffset + kPointerSize));
4865 __ ldr(r0, FieldMemOperand(r0, HeapNumber::kValueOffset)); 4866 __ ldr(r0, FieldMemOperand(r0, HeapNumber::kValueOffset));
4866 // We now have both loaded as doubles but we can skip the lhs nan check 4867 // We now have both loaded as doubles but we can skip the lhs nan check
4867 // since it's a Smi. 4868 // since it's a Smi.
4868 __ pop(lr); 4869 __ pop(lr);
4869 __ jmp(rhs_not_nan); 4870 __ jmp(lhs_not_nan);
4870 4871
4871 __ bind(&lhs_is_smi); 4872 __ bind(&lhs_is_smi);
4872 // Lhs is a Smi. Check whether the non-smi is a heap number. 4873 // Lhs is a Smi. Check whether the non-smi is a heap number.
4873 __ CompareObjectType(r1, r4, r4, HEAP_NUMBER_TYPE); 4874 __ CompareObjectType(r1, r4, r4, HEAP_NUMBER_TYPE);
4874 if (strict) { 4875 if (strict) {
4875 // If lhs was not a number and rhs was a Smi then strict equality cannot 4876 // If lhs was not a number and rhs was a Smi then strict equality cannot
4876 // succeed. Return non-equal. 4877 // succeed. Return non-equal.
4877 __ mov(r0, Operand(1), LeaveCC, ne); // Non-zero indicates not equal. 4878 __ mov(r0, Operand(1), LeaveCC, ne); // Non-zero indicates not equal.
4878 __ mov(pc, Operand(lr), LeaveCC, ne); // Return. 4879 __ mov(pc, Operand(lr), LeaveCC, ne); // Return.
4879 } else { 4880 } else {
(...skipping 15 matching lines...) Expand all
4895 __ mov(r7, Operand(r0)); 4896 __ mov(r7, Operand(r0));
4896 ConvertToDoubleStub stub2(r1, r0, r7, r6); 4897 ConvertToDoubleStub stub2(r1, r0, r7, r6);
4897 __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET); 4898 __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET);
4898 } 4899 }
4899 4900
4900 __ pop(lr); 4901 __ pop(lr);
4901 // Fall through to both_loaded_as_doubles. 4902 // Fall through to both_loaded_as_doubles.
4902 } 4903 }
4903 4904
4904 4905
4905 void EmitNanCheck(MacroAssembler* masm, Label* rhs_not_nan, Condition cc) { 4906 void EmitNanCheck(MacroAssembler* masm, Label* lhs_not_nan, Condition cc) {
4906 bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset); 4907 bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset);
4907 Register lhs_exponent = exp_first ? r0 : r1; 4908 Register rhs_exponent = exp_first ? r0 : r1;
4908 Register rhs_exponent = exp_first ? r2 : r3; 4909 Register lhs_exponent = exp_first ? r2 : r3;
4909 Register lhs_mantissa = exp_first ? r1 : r0; 4910 Register rhs_mantissa = exp_first ? r1 : r0;
4910 Register rhs_mantissa = exp_first ? r3 : r2; 4911 Register lhs_mantissa = exp_first ? r3 : r2;
4911 Label one_is_nan, neither_is_nan; 4912 Label one_is_nan, neither_is_nan;
4913 Label lhs_not_nan_exp_mask_is_loaded;
4912 4914
4913 Register exp_mask_reg = r5; 4915 Register exp_mask_reg = r5;
4914 4916
4915 __ mov(exp_mask_reg, Operand(HeapNumber::kExponentMask)); 4917 __ mov(exp_mask_reg, Operand(HeapNumber::kExponentMask));
4918 __ and_(r4, lhs_exponent, Operand(exp_mask_reg));
4919 __ cmp(r4, Operand(exp_mask_reg));
4920 __ b(ne, &lhs_not_nan_exp_mask_is_loaded);
4921 __ mov(r4,
4922 Operand(lhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord),
4923 SetCC);
4924 __ b(ne, &one_is_nan);
4925 __ cmp(lhs_mantissa, Operand(0));
4926 __ b(ne, &one_is_nan);
4927
4928 __ bind(lhs_not_nan);
4929 __ mov(exp_mask_reg, Operand(HeapNumber::kExponentMask));
4930 __ bind(&lhs_not_nan_exp_mask_is_loaded);
4916 __ and_(r4, rhs_exponent, Operand(exp_mask_reg)); 4931 __ and_(r4, rhs_exponent, Operand(exp_mask_reg));
4917 __ cmp(r4, Operand(exp_mask_reg)); 4932 __ cmp(r4, Operand(exp_mask_reg));
4918 __ b(ne, rhs_not_nan); 4933 __ b(ne, &neither_is_nan);
4919 __ mov(r4, 4934 __ mov(r4,
4920 Operand(rhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord), 4935 Operand(rhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord),
4921 SetCC); 4936 SetCC);
4922 __ b(ne, &one_is_nan); 4937 __ b(ne, &one_is_nan);
4923 __ cmp(rhs_mantissa, Operand(0)); 4938 __ cmp(rhs_mantissa, Operand(0));
4924 __ b(ne, &one_is_nan);
4925
4926 __ bind(rhs_not_nan);
4927 __ mov(exp_mask_reg, Operand(HeapNumber::kExponentMask));
4928 __ and_(r4, lhs_exponent, Operand(exp_mask_reg));
4929 __ cmp(r4, Operand(exp_mask_reg));
4930 __ b(ne, &neither_is_nan);
4931 __ mov(r4,
4932 Operand(lhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord),
4933 SetCC);
4934 __ b(ne, &one_is_nan);
4935 __ cmp(lhs_mantissa, Operand(0));
4936 __ b(eq, &neither_is_nan); 4939 __ b(eq, &neither_is_nan);
4937 4940
4938 __ bind(&one_is_nan); 4941 __ bind(&one_is_nan);
4939 // NaN comparisons always fail. 4942 // NaN comparisons always fail.
4940 // Load whatever we need in r0 to make the comparison fail. 4943 // Load whatever we need in r0 to make the comparison fail.
4941 if (cc == lt || cc == le) { 4944 if (cc == lt || cc == le) {
4942 __ mov(r0, Operand(GREATER)); 4945 __ mov(r0, Operand(GREATER));
4943 } else { 4946 } else {
4944 __ mov(r0, Operand(LESS)); 4947 __ mov(r0, Operand(LESS));
4945 } 4948 }
4946 __ mov(pc, Operand(lr)); // Return. 4949 __ mov(pc, Operand(lr)); // Return.
4947 4950
4948 __ bind(&neither_is_nan); 4951 __ bind(&neither_is_nan);
4949 } 4952 }
4950 4953
4951 4954
4952 // See comment at call site. 4955 // See comment at call site.
4953 static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc) { 4956 static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc) {
4954 bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset); 4957 bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset);
4955 Register lhs_exponent = exp_first ? r0 : r1; 4958 Register rhs_exponent = exp_first ? r0 : r1;
4956 Register rhs_exponent = exp_first ? r2 : r3; 4959 Register lhs_exponent = exp_first ? r2 : r3;
4957 Register lhs_mantissa = exp_first ? r1 : r0; 4960 Register rhs_mantissa = exp_first ? r1 : r0;
4958 Register rhs_mantissa = exp_first ? r3 : r2; 4961 Register lhs_mantissa = exp_first ? r3 : r2;
4959 4962
4960 // r0, r1, r2, r3 have the two doubles. Neither is a NaN. 4963 // r0, r1, r2, r3 have the two doubles. Neither is a NaN.
4961 if (cc == eq) { 4964 if (cc == eq) {
4962 // Doubles are not equal unless they have the same bit pattern. 4965 // Doubles are not equal unless they have the same bit pattern.
4963 // Exception: 0 and -0. 4966 // Exception: 0 and -0.
4964 __ cmp(lhs_mantissa, Operand(rhs_mantissa)); 4967 __ cmp(rhs_mantissa, Operand(lhs_mantissa));
4965 __ orr(r0, lhs_mantissa, Operand(rhs_mantissa), LeaveCC, ne); 4968 __ orr(r0, rhs_mantissa, Operand(lhs_mantissa), LeaveCC, ne);
4966 // Return non-zero if the numbers are unequal. 4969 // Return non-zero if the numbers are unequal.
4967 __ mov(pc, Operand(lr), LeaveCC, ne); 4970 __ mov(pc, Operand(lr), LeaveCC, ne);
4968 4971
4969 __ sub(r0, lhs_exponent, Operand(rhs_exponent), SetCC); 4972 __ sub(r0, rhs_exponent, Operand(lhs_exponent), SetCC);
4970 // If exponents are equal then return 0. 4973 // If exponents are equal then return 0.
4971 __ mov(pc, Operand(lr), LeaveCC, eq); 4974 __ mov(pc, Operand(lr), LeaveCC, eq);
4972 4975
4973 // Exponents are unequal. The only way we can return that the numbers 4976 // Exponents are unequal. The only way we can return that the numbers
4974 // are equal is if one is -0 and the other is 0. We already dealt 4977 // are equal is if one is -0 and the other is 0. We already dealt
4975 // with the case where both are -0 or both are 0. 4978 // with the case where both are -0 or both are 0.
4976 // We start by seeing if the mantissas (that are equal) or the bottom 4979 // We start by seeing if the mantissas (that are equal) or the bottom
4977 // 31 bits of the rhs exponent are non-zero. If so we return not 4980 // 31 bits of the rhs exponent are non-zero. If so we return not
4978 // equal. 4981 // equal.
4979 __ orr(r4, rhs_mantissa, Operand(rhs_exponent, LSL, kSmiTagSize), SetCC); 4982 __ orr(r4, lhs_mantissa, Operand(lhs_exponent, LSL, kSmiTagSize), SetCC);
4980 __ mov(r0, Operand(r4), LeaveCC, ne); 4983 __ mov(r0, Operand(r4), LeaveCC, ne);
4981 __ mov(pc, Operand(lr), LeaveCC, ne); // Return conditionally. 4984 __ mov(pc, Operand(lr), LeaveCC, ne); // Return conditionally.
4982 // Now they are equal if and only if the lhs exponent is zero in its 4985 // Now they are equal if and only if the lhs exponent is zero in its
4983 // low 31 bits. 4986 // low 31 bits.
4984 __ mov(r0, Operand(lhs_exponent, LSL, kSmiTagSize)); 4987 __ mov(r0, Operand(rhs_exponent, LSL, kSmiTagSize));
4985 __ mov(pc, Operand(lr)); 4988 __ mov(pc, Operand(lr));
4986 } else { 4989 } else {
4987 // Call a native function to do a comparison between two non-NaNs. 4990 // Call a native function to do a comparison between two non-NaNs.
4988 // Call C routine that may not cause GC or other trouble. 4991 // Call C routine that may not cause GC or other trouble.
4989 __ mov(r5, Operand(ExternalReference::compare_doubles())); 4992 __ mov(r5, Operand(ExternalReference::compare_doubles()));
4990 __ Jump(r5); // Tail call. 4993 __ Jump(r5); // Tail call.
4991 } 4994 }
4992 } 4995 }
4993 4996
4994 4997
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
5029 __ tst(r2, Operand(kIsSymbolMask)); 5032 __ tst(r2, Operand(kIsSymbolMask));
5030 __ b(ne, &return_not_equal); 5033 __ b(ne, &return_not_equal);
5031 } 5034 }
5032 5035
5033 5036
5034 // See comment at call site. 5037 // See comment at call site.
5035 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm, 5038 static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
5036 Label* both_loaded_as_doubles, 5039 Label* both_loaded_as_doubles,
5037 Label* not_heap_numbers, 5040 Label* not_heap_numbers,
5038 Label* slow) { 5041 Label* slow) {
5039 __ CompareObjectType(r0, r2, r2, HEAP_NUMBER_TYPE); 5042 __ CompareObjectType(r0, r3, r2, HEAP_NUMBER_TYPE);
5040 __ b(ne, not_heap_numbers); 5043 __ b(ne, not_heap_numbers);
5041 __ CompareObjectType(r1, r3, r3, HEAP_NUMBER_TYPE); 5044 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
5045 __ cmp(r2, r3);
5042 __ b(ne, slow); // First was a heap number, second wasn't. Go slow case. 5046 __ b(ne, slow); // First was a heap number, second wasn't. Go slow case.
5043 5047
5044 // Both are heap numbers. Load them up then jump to the code we have 5048 // Both are heap numbers. Load them up then jump to the code we have
5045 // for that. 5049 // for that.
5046 __ ldr(r2, FieldMemOperand(r1, HeapNumber::kValueOffset)); 5050 __ ldr(r2, FieldMemOperand(r1, HeapNumber::kValueOffset));
5047 __ ldr(r3, FieldMemOperand(r1, HeapNumber::kValueOffset + kPointerSize)); 5051 __ ldr(r3, FieldMemOperand(r1, HeapNumber::kValueOffset + kPointerSize));
5048 __ ldr(r1, FieldMemOperand(r0, HeapNumber::kValueOffset + kPointerSize)); 5052 __ ldr(r1, FieldMemOperand(r0, HeapNumber::kValueOffset + kPointerSize));
5049 __ ldr(r0, FieldMemOperand(r0, HeapNumber::kValueOffset)); 5053 __ ldr(r0, FieldMemOperand(r0, HeapNumber::kValueOffset));
5050 __ jmp(both_loaded_as_doubles); 5054 __ jmp(both_loaded_as_doubles);
5051 } 5055 }
(...skipping 16 matching lines...) Expand all
5068 // so they are not equal. 5072 // so they are not equal.
5069 __ mov(r0, Operand(1)); // Non-zero indicates not equal. 5073 __ mov(r0, Operand(1)); // Non-zero indicates not equal.
5070 __ mov(pc, Operand(lr)); // Return. 5074 __ mov(pc, Operand(lr)); // Return.
5071 } 5075 }
5072 5076
5073 5077
5074 // On entry r0 and r1 are the things to be compared. On exit r0 is 0, 5078 // On entry r0 and r1 are the things to be compared. On exit r0 is 0,
5075 // positive or negative to indicate the result of the comparison. 5079 // positive or negative to indicate the result of the comparison.
5076 void CompareStub::Generate(MacroAssembler* masm) { 5080 void CompareStub::Generate(MacroAssembler* masm) {
5077 Label slow; // Call builtin. 5081 Label slow; // Call builtin.
5078 Label not_smis, both_loaded_as_doubles, rhs_not_nan; 5082 Label not_smis, both_loaded_as_doubles, lhs_not_nan;
5079 5083
5080 // NOTICE! This code is only reached after a smi-fast-case check, so 5084 // NOTICE! This code is only reached after a smi-fast-case check, so
5081 // it is certain that at least one operand isn't a smi. 5085 // it is certain that at least one operand isn't a smi.
5082 5086
5083 // Handle the case where the objects are identical. Either returns the answer 5087 // Handle the case where the objects are identical. Either returns the answer
5084 // or goes to slow. Only falls through if the objects were not identical. 5088 // or goes to slow. Only falls through if the objects were not identical.
5085 EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_); 5089 EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_);
5086 5090
5087 // If either is a Smi (we know that not both are), then they can only 5091 // If either is a Smi (we know that not both are), then they can only
5088 // be strictly equal if the other is a HeapNumber. 5092 // be strictly equal if the other is a HeapNumber.
5089 ASSERT_EQ(0, kSmiTag); 5093 ASSERT_EQ(0, kSmiTag);
5090 ASSERT_EQ(0, Smi::FromInt(0)); 5094 ASSERT_EQ(0, Smi::FromInt(0));
5091 __ and_(r2, r0, Operand(r1)); 5095 __ and_(r2, r0, Operand(r1));
5092 __ tst(r2, Operand(kSmiTagMask)); 5096 __ tst(r2, Operand(kSmiTagMask));
5093 __ b(ne, &not_smis); 5097 __ b(ne, &not_smis);
5094 // One operand is a smi. EmitSmiNonsmiComparison generates code that can: 5098 // One operand is a smi. EmitSmiNonsmiComparison generates code that can:
5095 // 1) Return the answer. 5099 // 1) Return the answer.
5096 // 2) Go to slow. 5100 // 2) Go to slow.
5097 // 3) Fall through to both_loaded_as_doubles. 5101 // 3) Fall through to both_loaded_as_doubles.
5098 // 4) Jump to rhs_not_nan. 5102 // 4) Jump to lhs_not_nan.
5099 // In cases 3 and 4 we have found out we were dealing with a number-number 5103 // In cases 3 and 4 we have found out we were dealing with a number-number
5100 // comparison and the numbers have been loaded into r0, r1, r2, r3 as doubles. 5104 // comparison and the numbers have been loaded into r0, r1, r2, r3 as doubles.
5101 EmitSmiNonsmiComparison(masm, &rhs_not_nan, &slow, strict_); 5105 EmitSmiNonsmiComparison(masm, &lhs_not_nan, &slow, strict_);
5102 5106
5103 __ bind(&both_loaded_as_doubles); 5107 __ bind(&both_loaded_as_doubles);
5104 // r0, r1, r2, r3 are the double representations of the left hand side 5108 // r0, r1, r2, r3 are the double representations of the right hand side
5105 // and the right hand side. 5109 // and the left hand side.
5106
5107 // Checks for NaN in the doubles we have loaded. Can return the answer or
5108 // fall through if neither is a NaN. Also binds rhs_not_nan.
5109 EmitNanCheck(masm, &rhs_not_nan, cc_);
5110 5110
5111 if (CpuFeatures::IsSupported(VFP3)) { 5111 if (CpuFeatures::IsSupported(VFP3)) {
5112 __ bind(&lhs_not_nan);
5112 CpuFeatures::Scope scope(VFP3); 5113 CpuFeatures::Scope scope(VFP3);
5114 Label no_nan;
5113 // ARMv7 VFP3 instructions to implement double precision comparison. 5115 // ARMv7 VFP3 instructions to implement double precision comparison.
5114 __ vmov(d6, r0, r1); 5116 __ vmov(d6, r0, r1);
5115 __ vmov(d7, r2, r3); 5117 __ vmov(d7, r2, r3);
5116 5118
5117 __ vcmp(d6, d7); 5119 __ vcmp(d7, d6);
5118 __ vmrs(pc); 5120 __ vmrs(pc); // Move vector status bits to normal status bits.
5119 __ mov(r0, Operand(0), LeaveCC, eq); 5121 Label nan;
5120 __ mov(r0, Operand(1), LeaveCC, lt); 5122 __ b(vs, &nan);
5121 __ mvn(r0, Operand(0), LeaveCC, gt); 5123 __ mov(r0, Operand(EQUAL), LeaveCC, eq);
5124 __ mov(r0, Operand(LESS), LeaveCC, lt);
5125 __ mov(r0, Operand(GREATER), LeaveCC, gt);
5126 __ mov(pc, Operand(lr));
5127
5128 __ bind(&nan);
5129 // If one of the sides was a NaN then the v flag is set. Load r0 with
5130 // whatever it takes to make the comparison fail, since comparisons with NaN
5131 // always fail.
5132 if (cc_ == lt || cc_ == le) {
5133 __ mov(r0, Operand(GREATER));
5134 } else {
5135 __ mov(r0, Operand(LESS));
5136 }
5122 __ mov(pc, Operand(lr)); 5137 __ mov(pc, Operand(lr));
5123 } else { 5138 } else {
5139 // Checks for NaN in the doubles we have loaded. Can return the answer or
5140 // fall through if neither is a NaN. Also binds lhs_not_nan.
5141 EmitNanCheck(masm, &lhs_not_nan, cc_);
5124 // Compares two doubles in r0, r1, r2, r3 that are not NaNs. Returns the 5142 // Compares two doubles in r0, r1, r2, r3 that are not NaNs. Returns the
5125 // answer. Never falls through. 5143 // answer. Never falls through.
5126 EmitTwoNonNanDoubleComparison(masm, cc_); 5144 EmitTwoNonNanDoubleComparison(masm, cc_);
5127 } 5145 }
5128 5146
5129 __ bind(&not_smis); 5147 __ bind(&not_smis);
5130 // At this point we know we are dealing with two different objects, 5148 // At this point we know we are dealing with two different objects,
5131 // and neither of them is a Smi. The objects are in r0 and r1. 5149 // and neither of them is a Smi. The objects are in r0 and r1.
5132 if (strict_) { 5150 if (strict_) {
5133 // This returns non-equal for some object types, or falls through if it 5151 // This returns non-equal for some object types, or falls through if it
5134 // was not lucky. 5152 // was not lucky.
5135 EmitStrictTwoHeapObjectCompare(masm); 5153 EmitStrictTwoHeapObjectCompare(masm);
5136 } 5154 }
5137 5155
5138 Label check_for_symbols; 5156 Label check_for_symbols;
5139 // Check for heap-number-heap-number comparison. Can jump to slow case, 5157 // Check for heap-number-heap-number comparison. Can jump to slow case,
5140 // or load both doubles into r0, r1, r2, r3 and jump to the code that handles 5158 // or load both doubles into r0, r1, r2, r3 and jump to the code that handles
5141 // that case. If the inputs are not doubles then jumps to check_for_symbols. 5159 // that case. If the inputs are not doubles then jumps to check_for_symbols.
5142 // In this case r2 will contain the type of r0. 5160 // In this case r2 will contain the type of r0. Never falls through.
5143 EmitCheckForTwoHeapNumbers(masm, 5161 EmitCheckForTwoHeapNumbers(masm,
5144 &both_loaded_as_doubles, 5162 &both_loaded_as_doubles,
5145 &check_for_symbols, 5163 &check_for_symbols,
5146 &slow); 5164 &slow);
5147 5165
5148 __ bind(&check_for_symbols); 5166 __ bind(&check_for_symbols);
5149 // In the strict case the EmitStrictTwoHeapObjectCompare already took care of 5167 // In the strict case the EmitStrictTwoHeapObjectCompare already took care of
5150 // symbols. 5168 // symbols.
5151 if (cc_ == eq && !strict_) { 5169 if (cc_ == eq && !strict_) {
5152 // Either jumps to slow or returns the answer. Assumes that r2 is the type 5170 // Either jumps to slow or returns the answer. Assumes that r2 is the type
(...skipping 1548 matching lines...) Expand 10 before | Expand all | Expand 10 after
6701 ASSERT((static_cast<unsigned>(cc_) >> 26) < (1 << 16)); 6719 ASSERT((static_cast<unsigned>(cc_) >> 26) < (1 << 16));
6702 int nnn_value = (never_nan_nan_ ? 2 : 0); 6720 int nnn_value = (never_nan_nan_ ? 2 : 0);
6703 if (cc_ != eq) nnn_value = 0; // Avoid duplicate stubs. 6721 if (cc_ != eq) nnn_value = 0; // Avoid duplicate stubs.
6704 return (static_cast<unsigned>(cc_) >> 26) | nnn_value | (strict_ ? 1 : 0); 6722 return (static_cast<unsigned>(cc_) >> 26) | nnn_value | (strict_ ? 1 : 0);
6705 } 6723 }
6706 6724
6707 6725
6708 #undef __ 6726 #undef __
6709 6727
6710 } } // namespace v8::internal 6728 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/arm/fast-codegen-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698