OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X87 | 7 #if V8_TARGET_ARCH_X87 |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
11 #include "src/code-stubs.h" | 11 #include "src/code-stubs.h" |
12 #include "src/codegen.h" | 12 #include "src/codegen.h" |
13 #include "src/ic/handler-compiler.h" | 13 #include "src/ic/handler-compiler.h" |
| 14 #include "src/ic/ic.h" |
14 #include "src/isolate.h" | 15 #include "src/isolate.h" |
15 #include "src/jsregexp.h" | 16 #include "src/jsregexp.h" |
16 #include "src/regexp-macro-assembler.h" | 17 #include "src/regexp-macro-assembler.h" |
17 #include "src/runtime.h" | 18 #include "src/runtime.h" |
18 | 19 |
19 namespace v8 { | 20 namespace v8 { |
20 namespace internal { | 21 namespace internal { |
21 | 22 |
22 | 23 |
23 static void InitializeArrayConstructorDescriptor( | 24 static void InitializeArrayConstructorDescriptor( |
(...skipping 1164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1188 | 1189 |
1189 | 1190 |
1190 static int NegativeComparisonResult(Condition cc) { | 1191 static int NegativeComparisonResult(Condition cc) { |
1191 DCHECK(cc != equal); | 1192 DCHECK(cc != equal); |
1192 DCHECK((cc == less) || (cc == less_equal) | 1193 DCHECK((cc == less) || (cc == less_equal) |
1193 || (cc == greater) || (cc == greater_equal)); | 1194 || (cc == greater) || (cc == greater_equal)); |
1194 return (cc == greater || cc == greater_equal) ? LESS : GREATER; | 1195 return (cc == greater || cc == greater_equal) ? LESS : GREATER; |
1195 } | 1196 } |
1196 | 1197 |
1197 | 1198 |
1198 static void CheckInputType(MacroAssembler* masm, | 1199 static void CheckInputType(MacroAssembler* masm, Register input, |
1199 Register input, | 1200 CompareICState::State expected, Label* fail) { |
1200 CompareIC::State expected, | |
1201 Label* fail) { | |
1202 Label ok; | 1201 Label ok; |
1203 if (expected == CompareIC::SMI) { | 1202 if (expected == CompareICState::SMI) { |
1204 __ JumpIfNotSmi(input, fail); | 1203 __ JumpIfNotSmi(input, fail); |
1205 } else if (expected == CompareIC::NUMBER) { | 1204 } else if (expected == CompareICState::NUMBER) { |
1206 __ JumpIfSmi(input, &ok); | 1205 __ JumpIfSmi(input, &ok); |
1207 __ cmp(FieldOperand(input, HeapObject::kMapOffset), | 1206 __ cmp(FieldOperand(input, HeapObject::kMapOffset), |
1208 Immediate(masm->isolate()->factory()->heap_number_map())); | 1207 Immediate(masm->isolate()->factory()->heap_number_map())); |
1209 __ j(not_equal, fail); | 1208 __ j(not_equal, fail); |
1210 } | 1209 } |
1211 // We could be strict about internalized/non-internalized here, but as long as | 1210 // We could be strict about internalized/non-internalized here, but as long as |
1212 // hydrogen doesn't care, the stub doesn't have to care either. | 1211 // hydrogen doesn't care, the stub doesn't have to care either. |
1213 __ bind(&ok); | 1212 __ bind(&ok); |
1214 } | 1213 } |
1215 | 1214 |
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1811 Factory* factory = masm->isolate()->factory(); | 1810 Factory* factory = masm->isolate()->factory(); |
1812 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), | 1811 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
1813 factory->allocation_site_map()); | 1812 factory->allocation_site_map()); |
1814 __ j(not_equal, &miss); | 1813 __ j(not_equal, &miss); |
1815 | 1814 |
1816 __ mov(ebx, ecx); | 1815 __ mov(ebx, ecx); |
1817 ArrayConstructorStub stub(masm->isolate(), arg_count()); | 1816 ArrayConstructorStub stub(masm->isolate(), arg_count()); |
1818 __ TailCallStub(&stub); | 1817 __ TailCallStub(&stub); |
1819 | 1818 |
1820 __ bind(&miss); | 1819 __ bind(&miss); |
1821 GenerateMiss(masm, IC::kCallIC_Customization_Miss); | 1820 GenerateMiss(masm); |
1822 | 1821 |
1823 // The slow case, we need this no matter what to complete a call after a miss. | 1822 // The slow case, we need this no matter what to complete a call after a miss. |
1824 CallFunctionNoFeedback(masm, | 1823 CallFunctionNoFeedback(masm, |
1825 arg_count(), | 1824 arg_count(), |
1826 true, | 1825 true, |
1827 CallAsMethod()); | 1826 CallAsMethod()); |
1828 | 1827 |
1829 // Unreachable. | 1828 // Unreachable. |
1830 __ int3(); | 1829 __ int3(); |
1831 } | 1830 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1890 __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx); | 1889 __ CmpObjectType(ecx, JS_FUNCTION_TYPE, ecx); |
1891 __ j(not_equal, &miss); | 1890 __ j(not_equal, &miss); |
1892 __ mov(FieldOperand(ebx, edx, times_half_pointer_size, | 1891 __ mov(FieldOperand(ebx, edx, times_half_pointer_size, |
1893 FixedArray::kHeaderSize), | 1892 FixedArray::kHeaderSize), |
1894 Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate))); | 1893 Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate))); |
1895 __ jmp(&slow_start); | 1894 __ jmp(&slow_start); |
1896 } | 1895 } |
1897 | 1896 |
1898 // We are here because tracing is on or we are going monomorphic. | 1897 // We are here because tracing is on or we are going monomorphic. |
1899 __ bind(&miss); | 1898 __ bind(&miss); |
1900 GenerateMiss(masm, IC::kCallIC_Miss); | 1899 GenerateMiss(masm); |
1901 | 1900 |
1902 // the slow case | 1901 // the slow case |
1903 __ bind(&slow_start); | 1902 __ bind(&slow_start); |
1904 | 1903 |
1905 // Check that the function really is a JavaScript function. | 1904 // Check that the function really is a JavaScript function. |
1906 __ JumpIfSmi(edi, &non_function); | 1905 __ JumpIfSmi(edi, &non_function); |
1907 | 1906 |
1908 // Goto slow case if we do not have a function. | 1907 // Goto slow case if we do not have a function. |
1909 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 1908 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
1910 __ j(not_equal, &slow); | 1909 __ j(not_equal, &slow); |
1911 __ jmp(&have_js_function); | 1910 __ jmp(&have_js_function); |
1912 | 1911 |
1913 // Unreachable | 1912 // Unreachable |
1914 __ int3(); | 1913 __ int3(); |
1915 } | 1914 } |
1916 | 1915 |
1917 | 1916 |
1918 void CallICStub::GenerateMiss(MacroAssembler* masm, IC::UtilityId id) { | 1917 void CallICStub::GenerateMiss(MacroAssembler* masm) { |
1919 // Get the receiver of the function from the stack; 1 ~ return address. | 1918 // Get the receiver of the function from the stack; 1 ~ return address. |
1920 __ mov(ecx, Operand(esp, (arg_count() + 1) * kPointerSize)); | 1919 __ mov(ecx, Operand(esp, (arg_count() + 1) * kPointerSize)); |
1921 | 1920 |
1922 { | 1921 { |
1923 FrameScope scope(masm, StackFrame::INTERNAL); | 1922 FrameScope scope(masm, StackFrame::INTERNAL); |
1924 | 1923 |
1925 // Push the receiver and the function and feedback info. | 1924 // Push the receiver and the function and feedback info. |
1926 __ push(ecx); | 1925 __ push(ecx); |
1927 __ push(edi); | 1926 __ push(edi); |
1928 __ push(ebx); | 1927 __ push(ebx); |
1929 __ push(edx); | 1928 __ push(edx); |
1930 | 1929 |
1931 // Call the entry. | 1930 // Call the entry. |
| 1931 IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss |
| 1932 : IC::kCallIC_Customization_Miss; |
| 1933 |
1932 ExternalReference miss = ExternalReference(IC_Utility(id), | 1934 ExternalReference miss = ExternalReference(IC_Utility(id), |
1933 masm->isolate()); | 1935 masm->isolate()); |
1934 __ CallExternalReference(miss, 4); | 1936 __ CallExternalReference(miss, 4); |
1935 | 1937 |
1936 // Move result to edi and exit the internal frame. | 1938 // Move result to edi and exit the internal frame. |
1937 __ mov(edi, eax); | 1939 __ mov(edi, eax); |
1938 } | 1940 } |
1939 } | 1941 } |
1940 | 1942 |
1941 | 1943 |
(...skipping 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2966 } | 2968 } |
2967 | 2969 |
2968 // Tail call into the stub that handles binary operations with allocation | 2970 // Tail call into the stub that handles binary operations with allocation |
2969 // sites. | 2971 // sites. |
2970 BinaryOpWithAllocationSiteStub stub(isolate(), state()); | 2972 BinaryOpWithAllocationSiteStub stub(isolate(), state()); |
2971 __ TailCallStub(&stub); | 2973 __ TailCallStub(&stub); |
2972 } | 2974 } |
2973 | 2975 |
2974 | 2976 |
2975 void CompareICStub::GenerateSmis(MacroAssembler* masm) { | 2977 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
2976 DCHECK(state() == CompareIC::SMI); | 2978 DCHECK(state() == CompareICState::SMI); |
2977 Label miss; | 2979 Label miss; |
2978 __ mov(ecx, edx); | 2980 __ mov(ecx, edx); |
2979 __ or_(ecx, eax); | 2981 __ or_(ecx, eax); |
2980 __ JumpIfNotSmi(ecx, &miss, Label::kNear); | 2982 __ JumpIfNotSmi(ecx, &miss, Label::kNear); |
2981 | 2983 |
2982 if (GetCondition() == equal) { | 2984 if (GetCondition() == equal) { |
2983 // For equality we do not care about the sign of the result. | 2985 // For equality we do not care about the sign of the result. |
2984 __ sub(eax, edx); | 2986 __ sub(eax, edx); |
2985 } else { | 2987 } else { |
2986 Label done; | 2988 Label done; |
2987 __ sub(edx, eax); | 2989 __ sub(edx, eax); |
2988 __ j(no_overflow, &done, Label::kNear); | 2990 __ j(no_overflow, &done, Label::kNear); |
2989 // Correct sign of result in case of overflow. | 2991 // Correct sign of result in case of overflow. |
2990 __ not_(edx); | 2992 __ not_(edx); |
2991 __ bind(&done); | 2993 __ bind(&done); |
2992 __ mov(eax, edx); | 2994 __ mov(eax, edx); |
2993 } | 2995 } |
2994 __ ret(0); | 2996 __ ret(0); |
2995 | 2997 |
2996 __ bind(&miss); | 2998 __ bind(&miss); |
2997 GenerateMiss(masm); | 2999 GenerateMiss(masm); |
2998 } | 3000 } |
2999 | 3001 |
3000 | 3002 |
3001 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { | 3003 void CompareICStub::GenerateNumbers(MacroAssembler* masm) { |
3002 DCHECK(state() == CompareIC::NUMBER); | 3004 DCHECK(state() == CompareICState::NUMBER); |
3003 | 3005 |
3004 Label generic_stub; | 3006 Label generic_stub; |
3005 Label unordered, maybe_undefined1, maybe_undefined2; | 3007 Label unordered, maybe_undefined1, maybe_undefined2; |
3006 Label miss; | 3008 Label miss; |
3007 | 3009 |
3008 if (left() == CompareIC::SMI) { | 3010 if (left() == CompareICState::SMI) { |
3009 __ JumpIfNotSmi(edx, &miss); | 3011 __ JumpIfNotSmi(edx, &miss); |
3010 } | 3012 } |
3011 if (right() == CompareIC::SMI) { | 3013 if (right() == CompareICState::SMI) { |
3012 __ JumpIfNotSmi(eax, &miss); | 3014 __ JumpIfNotSmi(eax, &miss); |
3013 } | 3015 } |
3014 | 3016 |
3015 // Inlining the double comparison and falling back to the general compare | 3017 // Inlining the double comparison and falling back to the general compare |
3016 // stub if NaN is involved or SSE2 or CMOV is unsupported. | 3018 // stub if NaN is involved or SSE2 or CMOV is unsupported. |
3017 __ mov(ecx, edx); | 3019 __ mov(ecx, edx); |
3018 __ and_(ecx, eax); | 3020 __ and_(ecx, eax); |
3019 __ JumpIfSmi(ecx, &generic_stub, Label::kNear); | 3021 __ JumpIfSmi(ecx, &generic_stub, Label::kNear); |
3020 | 3022 |
3021 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 3023 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
3022 isolate()->factory()->heap_number_map()); | 3024 isolate()->factory()->heap_number_map()); |
3023 __ j(not_equal, &maybe_undefined1, Label::kNear); | 3025 __ j(not_equal, &maybe_undefined1, Label::kNear); |
3024 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 3026 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
3025 isolate()->factory()->heap_number_map()); | 3027 isolate()->factory()->heap_number_map()); |
3026 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3028 __ j(not_equal, &maybe_undefined2, Label::kNear); |
3027 | 3029 |
3028 __ bind(&unordered); | 3030 __ bind(&unordered); |
3029 __ bind(&generic_stub); | 3031 __ bind(&generic_stub); |
3030 CompareICStub stub(isolate(), op(), CompareIC::GENERIC, CompareIC::GENERIC, | 3032 CompareICStub stub(isolate(), op(), CompareICState::GENERIC, |
3031 CompareIC::GENERIC); | 3033 CompareICState::GENERIC, CompareICState::GENERIC); |
3032 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3034 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
3033 | 3035 |
3034 __ bind(&maybe_undefined1); | 3036 __ bind(&maybe_undefined1); |
3035 if (Token::IsOrderedRelationalCompareOp(op())) { | 3037 if (Token::IsOrderedRelationalCompareOp(op())) { |
3036 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); | 3038 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); |
3037 __ j(not_equal, &miss); | 3039 __ j(not_equal, &miss); |
3038 __ JumpIfSmi(edx, &unordered); | 3040 __ JumpIfSmi(edx, &unordered); |
3039 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); | 3041 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); |
3040 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3042 __ j(not_equal, &maybe_undefined2, Label::kNear); |
3041 __ jmp(&unordered); | 3043 __ jmp(&unordered); |
3042 } | 3044 } |
3043 | 3045 |
3044 __ bind(&maybe_undefined2); | 3046 __ bind(&maybe_undefined2); |
3045 if (Token::IsOrderedRelationalCompareOp(op())) { | 3047 if (Token::IsOrderedRelationalCompareOp(op())) { |
3046 __ cmp(edx, Immediate(isolate()->factory()->undefined_value())); | 3048 __ cmp(edx, Immediate(isolate()->factory()->undefined_value())); |
3047 __ j(equal, &unordered); | 3049 __ j(equal, &unordered); |
3048 } | 3050 } |
3049 | 3051 |
3050 __ bind(&miss); | 3052 __ bind(&miss); |
3051 GenerateMiss(masm); | 3053 GenerateMiss(masm); |
3052 } | 3054 } |
3053 | 3055 |
3054 | 3056 |
3055 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { | 3057 void CompareICStub::GenerateInternalizedStrings(MacroAssembler* masm) { |
3056 DCHECK(state() == CompareIC::INTERNALIZED_STRING); | 3058 DCHECK(state() == CompareICState::INTERNALIZED_STRING); |
3057 DCHECK(GetCondition() == equal); | 3059 DCHECK(GetCondition() == equal); |
3058 | 3060 |
3059 // Registers containing left and right operands respectively. | 3061 // Registers containing left and right operands respectively. |
3060 Register left = edx; | 3062 Register left = edx; |
3061 Register right = eax; | 3063 Register right = eax; |
3062 Register tmp1 = ecx; | 3064 Register tmp1 = ecx; |
3063 Register tmp2 = ebx; | 3065 Register tmp2 = ebx; |
3064 | 3066 |
3065 // Check that both operands are heap objects. | 3067 // Check that both operands are heap objects. |
3066 Label miss; | 3068 Label miss; |
(...skipping 24 matching lines...) Expand all Loading... |
3091 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 3093 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
3092 __ bind(&done); | 3094 __ bind(&done); |
3093 __ ret(0); | 3095 __ ret(0); |
3094 | 3096 |
3095 __ bind(&miss); | 3097 __ bind(&miss); |
3096 GenerateMiss(masm); | 3098 GenerateMiss(masm); |
3097 } | 3099 } |
3098 | 3100 |
3099 | 3101 |
3100 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { | 3102 void CompareICStub::GenerateUniqueNames(MacroAssembler* masm) { |
3101 DCHECK(state() == CompareIC::UNIQUE_NAME); | 3103 DCHECK(state() == CompareICState::UNIQUE_NAME); |
3102 DCHECK(GetCondition() == equal); | 3104 DCHECK(GetCondition() == equal); |
3103 | 3105 |
3104 // Registers containing left and right operands respectively. | 3106 // Registers containing left and right operands respectively. |
3105 Register left = edx; | 3107 Register left = edx; |
3106 Register right = eax; | 3108 Register right = eax; |
3107 Register tmp1 = ecx; | 3109 Register tmp1 = ecx; |
3108 Register tmp2 = ebx; | 3110 Register tmp2 = ebx; |
3109 | 3111 |
3110 // Check that both operands are heap objects. | 3112 // Check that both operands are heap objects. |
3111 Label miss; | 3113 Label miss; |
(...skipping 24 matching lines...) Expand all Loading... |
3136 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 3138 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
3137 __ bind(&done); | 3139 __ bind(&done); |
3138 __ ret(0); | 3140 __ ret(0); |
3139 | 3141 |
3140 __ bind(&miss); | 3142 __ bind(&miss); |
3141 GenerateMiss(masm); | 3143 GenerateMiss(masm); |
3142 } | 3144 } |
3143 | 3145 |
3144 | 3146 |
3145 void CompareICStub::GenerateStrings(MacroAssembler* masm) { | 3147 void CompareICStub::GenerateStrings(MacroAssembler* masm) { |
3146 DCHECK(state() == CompareIC::STRING); | 3148 DCHECK(state() == CompareICState::STRING); |
3147 Label miss; | 3149 Label miss; |
3148 | 3150 |
3149 bool equality = Token::IsEqualityOp(op()); | 3151 bool equality = Token::IsEqualityOp(op()); |
3150 | 3152 |
3151 // Registers containing left and right operands respectively. | 3153 // Registers containing left and right operands respectively. |
3152 Register left = edx; | 3154 Register left = edx; |
3153 Register right = eax; | 3155 Register right = eax; |
3154 Register tmp1 = ecx; | 3156 Register tmp1 = ecx; |
3155 Register tmp2 = ebx; | 3157 Register tmp2 = ebx; |
3156 Register tmp3 = edi; | 3158 Register tmp3 = edi; |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3226 } else { | 3228 } else { |
3227 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 3229 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
3228 } | 3230 } |
3229 | 3231 |
3230 __ bind(&miss); | 3232 __ bind(&miss); |
3231 GenerateMiss(masm); | 3233 GenerateMiss(masm); |
3232 } | 3234 } |
3233 | 3235 |
3234 | 3236 |
3235 void CompareICStub::GenerateObjects(MacroAssembler* masm) { | 3237 void CompareICStub::GenerateObjects(MacroAssembler* masm) { |
3236 DCHECK(state() == CompareIC::OBJECT); | 3238 DCHECK(state() == CompareICState::OBJECT); |
3237 Label miss; | 3239 Label miss; |
3238 __ mov(ecx, edx); | 3240 __ mov(ecx, edx); |
3239 __ and_(ecx, eax); | 3241 __ and_(ecx, eax); |
3240 __ JumpIfSmi(ecx, &miss, Label::kNear); | 3242 __ JumpIfSmi(ecx, &miss, Label::kNear); |
3241 | 3243 |
3242 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); | 3244 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); |
3243 __ j(not_equal, &miss, Label::kNear); | 3245 __ j(not_equal, &miss, Label::kNear); |
3244 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); | 3246 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); |
3245 __ j(not_equal, &miss, Label::kNear); | 3247 __ j(not_equal, &miss, Label::kNear); |
3246 | 3248 |
(...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4315 Operand(ebp, 7 * kPointerSize), | 4317 Operand(ebp, 7 * kPointerSize), |
4316 NULL); | 4318 NULL); |
4317 } | 4319 } |
4318 | 4320 |
4319 | 4321 |
4320 #undef __ | 4322 #undef __ |
4321 | 4323 |
4322 } } // namespace v8::internal | 4324 } } // namespace v8::internal |
4323 | 4325 |
4324 #endif // V8_TARGET_ARCH_X87 | 4326 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |