OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
7 #include "src/bootstrapper.h" | 7 #include "src/bootstrapper.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/ic/handler-compiler.h" | 10 #include "src/ic/handler-compiler.h" |
(...skipping 1093 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1104 // Two identical objects are equal unless they are both NaN or undefined. | 1104 // Two identical objects are equal unless they are both NaN or undefined. |
1105 { | 1105 { |
1106 Label not_identical; | 1106 Label not_identical; |
1107 __ cmpp(rax, rdx); | 1107 __ cmpp(rax, rdx); |
1108 __ j(not_equal, ¬_identical, Label::kNear); | 1108 __ j(not_equal, ¬_identical, Label::kNear); |
1109 | 1109 |
1110 if (cc != equal) { | 1110 if (cc != equal) { |
1111 // Check for undefined. undefined OP undefined is false even though | 1111 // Check for undefined. undefined OP undefined is false even though |
1112 // undefined == undefined. | 1112 // undefined == undefined. |
1113 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); | 1113 __ CompareRoot(rdx, Heap::kUndefinedValueRootIndex); |
1114 if (is_strong(strength())) { | 1114 Label check_for_nan; |
1115 // In strong mode, this comparison must throw, so call the runtime. | 1115 __ j(not_equal, &check_for_nan, Label::kNear); |
1116 __ j(equal, &runtime_call, Label::kFar); | 1116 __ Set(rax, NegativeComparisonResult(cc)); |
1117 } else { | 1117 __ ret(0); |
1118 Label check_for_nan; | 1118 __ bind(&check_for_nan); |
1119 __ j(not_equal, &check_for_nan, Label::kNear); | |
1120 __ Set(rax, NegativeComparisonResult(cc)); | |
1121 __ ret(0); | |
1122 __ bind(&check_for_nan); | |
1123 } | |
1124 } | 1119 } |
1125 | 1120 |
1126 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), | 1121 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), |
1127 // so we do the second best thing - test it ourselves. | 1122 // so we do the second best thing - test it ourselves. |
1128 Label heap_number; | 1123 Label heap_number; |
1129 // If it's not a heap number, then return equal for (in)equality operator. | 1124 // If it's not a heap number, then return equal for (in)equality operator. |
1130 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), | 1125 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), |
1131 factory->heap_number_map()); | 1126 factory->heap_number_map()); |
1132 __ j(equal, &heap_number, Label::kNear); | 1127 __ j(equal, &heap_number, Label::kNear); |
1133 if (cc != equal) { | 1128 if (cc != equal) { |
1134 __ movp(rcx, FieldOperand(rax, HeapObject::kMapOffset)); | 1129 __ movp(rcx, FieldOperand(rax, HeapObject::kMapOffset)); |
1135 __ movzxbl(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset)); | 1130 __ movzxbl(rcx, FieldOperand(rcx, Map::kInstanceTypeOffset)); |
1136 // Call runtime on identical objects. Otherwise return equal. | 1131 // Call runtime on identical objects. Otherwise return equal. |
1137 __ cmpb(rcx, Immediate(static_cast<uint8_t>(FIRST_JS_RECEIVER_TYPE))); | 1132 __ cmpb(rcx, Immediate(static_cast<uint8_t>(FIRST_JS_RECEIVER_TYPE))); |
1138 __ j(above_equal, &runtime_call, Label::kFar); | 1133 __ j(above_equal, &runtime_call, Label::kFar); |
1139 // Call runtime on identical symbols since we need to throw a TypeError. | 1134 // Call runtime on identical symbols since we need to throw a TypeError. |
1140 __ cmpb(rcx, Immediate(static_cast<uint8_t>(SYMBOL_TYPE))); | 1135 __ cmpb(rcx, Immediate(static_cast<uint8_t>(SYMBOL_TYPE))); |
1141 __ j(equal, &runtime_call, Label::kFar); | 1136 __ j(equal, &runtime_call, Label::kFar); |
1142 // Call runtime on identical SIMD values since we must throw a TypeError. | 1137 // Call runtime on identical SIMD values since we must throw a TypeError. |
1143 __ cmpb(rcx, Immediate(static_cast<uint8_t>(SIMD128_VALUE_TYPE))); | 1138 __ cmpb(rcx, Immediate(static_cast<uint8_t>(SIMD128_VALUE_TYPE))); |
1144 __ j(equal, &runtime_call, Label::kFar); | 1139 __ j(equal, &runtime_call, Label::kFar); |
1145 if (is_strong(strength())) { | |
1146 // We have already tested for smis and heap numbers, so if both | |
1147 // arguments are not strings we must proceed to the slow case. | |
1148 __ testb(rcx, Immediate(kIsNotStringMask)); | |
1149 __ j(not_zero, &runtime_call, Label::kFar); | |
1150 } | |
1151 } | 1140 } |
1152 __ Set(rax, EQUAL); | 1141 __ Set(rax, EQUAL); |
1153 __ ret(0); | 1142 __ ret(0); |
1154 | 1143 |
1155 __ bind(&heap_number); | 1144 __ bind(&heap_number); |
1156 // It is a heap number, so return equal if it's not NaN. | 1145 // It is a heap number, so return equal if it's not NaN. |
1157 // For NaN, return 1 for every condition except greater and | 1146 // For NaN, return 1 for every condition except greater and |
1158 // greater-equal. Return -1 for them, so the comparison yields | 1147 // greater-equal. Return -1 for them, so the comparison yields |
1159 // false for all conditions except not-equal. | 1148 // false for all conditions except not-equal. |
1160 __ Set(rax, EQUAL); | 1149 __ Set(rax, EQUAL); |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1336 __ Push(rdx); | 1325 __ Push(rdx); |
1337 __ Push(rax); | 1326 __ Push(rax); |
1338 | 1327 |
1339 // Figure out which native to call and setup the arguments. | 1328 // Figure out which native to call and setup the arguments. |
1340 if (cc == equal) { | 1329 if (cc == equal) { |
1341 __ PushReturnAddressFrom(rcx); | 1330 __ PushReturnAddressFrom(rcx); |
1342 __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals); | 1331 __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals); |
1343 } else { | 1332 } else { |
1344 __ Push(Smi::FromInt(NegativeComparisonResult(cc))); | 1333 __ Push(Smi::FromInt(NegativeComparisonResult(cc))); |
1345 __ PushReturnAddressFrom(rcx); | 1334 __ PushReturnAddressFrom(rcx); |
1346 __ TailCallRuntime(is_strong(strength()) ? Runtime::kCompare_Strong | 1335 __ TailCallRuntime(Runtime::kCompare); |
1347 : Runtime::kCompare); | |
1348 } | 1336 } |
1349 | 1337 |
1350 __ bind(&miss); | 1338 __ bind(&miss); |
1351 GenerateMiss(masm); | 1339 GenerateMiss(masm); |
1352 } | 1340 } |
1353 | 1341 |
1354 | 1342 |
1355 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { | 1343 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { |
1356 // rax : number of arguments to the construct function | 1344 // rax : number of arguments to the construct function |
1357 // rbx : feedback vector | 1345 // rbx : feedback vector |
(...skipping 1536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2894 Label miss; | 2882 Label miss; |
2895 Label::Distance const miss_distance = | 2883 Label::Distance const miss_distance = |
2896 masm->emit_debug_code() ? Label::kFar : Label::kNear; | 2884 masm->emit_debug_code() ? Label::kFar : Label::kNear; |
2897 | 2885 |
2898 __ JumpIfSmi(rdx, &miss, miss_distance); | 2886 __ JumpIfSmi(rdx, &miss, miss_distance); |
2899 __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); | 2887 __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); |
2900 __ JumpIfSmi(rax, &miss, miss_distance); | 2888 __ JumpIfSmi(rax, &miss, miss_distance); |
2901 __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 2889 __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
2902 __ JumpIfNotRoot(rcx, Heap::kBooleanMapRootIndex, &miss, miss_distance); | 2890 __ JumpIfNotRoot(rcx, Heap::kBooleanMapRootIndex, &miss, miss_distance); |
2903 __ JumpIfNotRoot(rbx, Heap::kBooleanMapRootIndex, &miss, miss_distance); | 2891 __ JumpIfNotRoot(rbx, Heap::kBooleanMapRootIndex, &miss, miss_distance); |
2904 if (op() != Token::EQ_STRICT && is_strong(strength())) { | 2892 if (!Token::IsEqualityOp(op())) { |
2905 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); | 2893 __ movp(rax, FieldOperand(rax, Oddball::kToNumberOffset)); |
2906 } else { | 2894 __ AssertSmi(rax); |
2907 if (!Token::IsEqualityOp(op())) { | 2895 __ movp(rdx, FieldOperand(rdx, Oddball::kToNumberOffset)); |
2908 __ movp(rax, FieldOperand(rax, Oddball::kToNumberOffset)); | 2896 __ AssertSmi(rdx); |
2909 __ AssertSmi(rax); | 2897 __ pushq(rax); |
2910 __ movp(rdx, FieldOperand(rdx, Oddball::kToNumberOffset)); | 2898 __ movq(rax, rdx); |
2911 __ AssertSmi(rdx); | 2899 __ popq(rdx); |
2912 __ pushq(rax); | |
2913 __ movq(rax, rdx); | |
2914 __ popq(rdx); | |
2915 } | |
2916 __ subp(rax, rdx); | |
2917 __ Ret(); | |
2918 } | 2900 } |
| 2901 __ subp(rax, rdx); |
| 2902 __ Ret(); |
2919 | 2903 |
2920 __ bind(&miss); | 2904 __ bind(&miss); |
2921 GenerateMiss(masm); | 2905 GenerateMiss(masm); |
2922 } | 2906 } |
2923 | 2907 |
2924 | 2908 |
2925 void CompareICStub::GenerateSmis(MacroAssembler* masm) { | 2909 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
2926 DCHECK(state() == CompareICState::SMI); | 2910 DCHECK(state() == CompareICState::SMI); |
2927 Label miss; | 2911 Label miss; |
2928 __ JumpIfNotBothSmi(rdx, rax, &miss, Label::kNear); | 2912 __ JumpIfNotBothSmi(rdx, rax, &miss, Label::kNear); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2991 // Return a result of -1, 0, or 1, based on EFLAGS. | 2975 // Return a result of -1, 0, or 1, based on EFLAGS. |
2992 // Performing mov, because xor would destroy the flag register. | 2976 // Performing mov, because xor would destroy the flag register. |
2993 __ movl(rax, Immediate(0)); | 2977 __ movl(rax, Immediate(0)); |
2994 __ movl(rcx, Immediate(0)); | 2978 __ movl(rcx, Immediate(0)); |
2995 __ setcc(above, rax); // Add one to zero if carry clear and not equal. | 2979 __ setcc(above, rax); // Add one to zero if carry clear and not equal. |
2996 __ sbbp(rax, rcx); // Subtract one if below (aka. carry set). | 2980 __ sbbp(rax, rcx); // Subtract one if below (aka. carry set). |
2997 __ ret(0); | 2981 __ ret(0); |
2998 | 2982 |
2999 __ bind(&unordered); | 2983 __ bind(&unordered); |
3000 __ bind(&generic_stub); | 2984 __ bind(&generic_stub); |
3001 CompareICStub stub(isolate(), op(), strength(), CompareICState::GENERIC, | 2985 CompareICStub stub(isolate(), op(), CompareICState::GENERIC, |
3002 CompareICState::GENERIC, CompareICState::GENERIC); | 2986 CompareICState::GENERIC, CompareICState::GENERIC); |
3003 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 2987 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
3004 | 2988 |
3005 __ bind(&maybe_undefined1); | 2989 __ bind(&maybe_undefined1); |
3006 if (Token::IsOrderedRelationalCompareOp(op())) { | 2990 if (Token::IsOrderedRelationalCompareOp(op())) { |
3007 __ Cmp(rax, isolate()->factory()->undefined_value()); | 2991 __ Cmp(rax, isolate()->factory()->undefined_value()); |
3008 __ j(not_equal, &miss); | 2992 __ j(not_equal, &miss); |
3009 __ JumpIfSmi(rdx, &unordered); | 2993 __ JumpIfSmi(rdx, &unordered); |
3010 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); | 2994 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); |
3011 __ j(not_equal, &maybe_undefined2, Label::kNear); | 2995 __ j(not_equal, &maybe_undefined2, Label::kNear); |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3225 | 3209 |
3226 __ GetWeakValue(rdi, cell); | 3210 __ GetWeakValue(rdi, cell); |
3227 __ cmpp(FieldOperand(rdx, HeapObject::kMapOffset), rdi); | 3211 __ cmpp(FieldOperand(rdx, HeapObject::kMapOffset), rdi); |
3228 __ j(not_equal, &miss, Label::kNear); | 3212 __ j(not_equal, &miss, Label::kNear); |
3229 __ cmpp(FieldOperand(rax, HeapObject::kMapOffset), rdi); | 3213 __ cmpp(FieldOperand(rax, HeapObject::kMapOffset), rdi); |
3230 __ j(not_equal, &miss, Label::kNear); | 3214 __ j(not_equal, &miss, Label::kNear); |
3231 | 3215 |
3232 if (Token::IsEqualityOp(op())) { | 3216 if (Token::IsEqualityOp(op())) { |
3233 __ subp(rax, rdx); | 3217 __ subp(rax, rdx); |
3234 __ ret(0); | 3218 __ ret(0); |
3235 } else if (is_strong(strength())) { | |
3236 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); | |
3237 } else { | 3219 } else { |
3238 __ PopReturnAddressTo(rcx); | 3220 __ PopReturnAddressTo(rcx); |
3239 __ Push(rdx); | 3221 __ Push(rdx); |
3240 __ Push(rax); | 3222 __ Push(rax); |
3241 __ Push(Smi::FromInt(NegativeComparisonResult(GetCondition()))); | 3223 __ Push(Smi::FromInt(NegativeComparisonResult(GetCondition()))); |
3242 __ PushReturnAddressFrom(rcx); | 3224 __ PushReturnAddressFrom(rcx); |
3243 __ TailCallRuntime(Runtime::kCompare); | 3225 __ TailCallRuntime(Runtime::kCompare); |
3244 } | 3226 } |
3245 | 3227 |
3246 __ bind(&miss); | 3228 __ bind(&miss); |
(...skipping 2274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5521 NULL); | 5503 NULL); |
5522 } | 5504 } |
5523 | 5505 |
5524 | 5506 |
5525 #undef __ | 5507 #undef __ |
5526 | 5508 |
5527 } // namespace internal | 5509 } // namespace internal |
5528 } // namespace v8 | 5510 } // namespace v8 |
5529 | 5511 |
5530 #endif // V8_TARGET_ARCH_X64 | 5512 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |