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 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 1218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1229 Label generic_heap_number_comparison; | 1229 Label generic_heap_number_comparison; |
1230 { | 1230 { |
1231 Label not_identical; | 1231 Label not_identical; |
1232 __ cmp(eax, edx); | 1232 __ cmp(eax, edx); |
1233 __ j(not_equal, ¬_identical); | 1233 __ j(not_equal, ¬_identical); |
1234 | 1234 |
1235 if (cc != equal) { | 1235 if (cc != equal) { |
1236 // Check for undefined. undefined OP undefined is false even though | 1236 // Check for undefined. undefined OP undefined is false even though |
1237 // undefined == undefined. | 1237 // undefined == undefined. |
1238 __ cmp(edx, isolate()->factory()->undefined_value()); | 1238 __ cmp(edx, isolate()->factory()->undefined_value()); |
1239 if (is_strong(strength())) { | 1239 Label check_for_nan; |
1240 // In strong mode, this comparison must throw, so call the runtime. | 1240 __ j(not_equal, &check_for_nan, Label::kNear); |
1241 __ j(equal, &runtime_call, Label::kFar); | 1241 __ Move(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); |
1242 } else { | 1242 __ ret(0); |
1243 Label check_for_nan; | 1243 __ bind(&check_for_nan); |
1244 __ j(not_equal, &check_for_nan, Label::kNear); | |
1245 __ Move(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); | |
1246 __ ret(0); | |
1247 __ bind(&check_for_nan); | |
1248 } | |
1249 } | 1244 } |
1250 | 1245 |
1251 // Test for NaN. Compare heap numbers in a general way, | 1246 // Test for NaN. Compare heap numbers in a general way, |
1252 // to handle NaNs correctly. | 1247 // to handle NaNs correctly. |
1253 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 1248 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
1254 Immediate(isolate()->factory()->heap_number_map())); | 1249 Immediate(isolate()->factory()->heap_number_map())); |
1255 __ j(equal, &generic_heap_number_comparison, Label::kNear); | 1250 __ j(equal, &generic_heap_number_comparison, Label::kNear); |
1256 if (cc != equal) { | 1251 if (cc != equal) { |
1257 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); | 1252 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
1258 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 1253 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
1259 // Call runtime on identical JSObjects. Otherwise return equal. | 1254 // Call runtime on identical JSObjects. Otherwise return equal. |
1260 __ cmpb(ecx, static_cast<uint8_t>(FIRST_JS_RECEIVER_TYPE)); | 1255 __ cmpb(ecx, static_cast<uint8_t>(FIRST_JS_RECEIVER_TYPE)); |
1261 __ j(above_equal, &runtime_call, Label::kFar); | 1256 __ j(above_equal, &runtime_call, Label::kFar); |
1262 // Call runtime on identical symbols since we need to throw a TypeError. | 1257 // Call runtime on identical symbols since we need to throw a TypeError. |
1263 __ cmpb(ecx, static_cast<uint8_t>(SYMBOL_TYPE)); | 1258 __ cmpb(ecx, static_cast<uint8_t>(SYMBOL_TYPE)); |
1264 __ j(equal, &runtime_call, Label::kFar); | 1259 __ j(equal, &runtime_call, Label::kFar); |
1265 // Call runtime on identical SIMD values since we must throw a TypeError. | 1260 // Call runtime on identical SIMD values since we must throw a TypeError. |
1266 __ cmpb(ecx, static_cast<uint8_t>(SIMD128_VALUE_TYPE)); | 1261 __ cmpb(ecx, static_cast<uint8_t>(SIMD128_VALUE_TYPE)); |
1267 __ j(equal, &runtime_call, Label::kFar); | 1262 __ j(equal, &runtime_call, Label::kFar); |
1268 if (is_strong(strength())) { | |
1269 // We have already tested for smis and heap numbers, so if both | |
1270 // arguments are not strings we must proceed to the slow case. | |
1271 __ test(ecx, Immediate(kIsNotStringMask)); | |
1272 __ j(not_zero, &runtime_call, Label::kFar); | |
1273 } | |
1274 } | 1263 } |
1275 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 1264 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
1276 __ ret(0); | 1265 __ ret(0); |
1277 | 1266 |
1278 | 1267 |
1279 __ bind(¬_identical); | 1268 __ bind(¬_identical); |
1280 } | 1269 } |
1281 | 1270 |
1282 // Strict equality can quickly decide whether objects are equal. | 1271 // Strict equality can quickly decide whether objects are equal. |
1283 // Non-strict object equality is slower, so it is handled later in the stub. | 1272 // Non-strict object equality is slower, so it is handled later in the stub. |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1463 __ push(ecx); | 1452 __ push(ecx); |
1464 __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals); | 1453 __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals); |
1465 } else { | 1454 } else { |
1466 __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); | 1455 __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); |
1467 | 1456 |
1468 // Restore return address on the stack. | 1457 // Restore return address on the stack. |
1469 __ push(ecx); | 1458 __ push(ecx); |
1470 | 1459 |
1471 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 1460 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
1472 // tagged as a small integer. | 1461 // tagged as a small integer. |
1473 __ TailCallRuntime(is_strong(strength()) ? Runtime::kCompare_Strong | 1462 __ TailCallRuntime(Runtime::kCompare); |
1474 : Runtime::kCompare); | |
1475 } | 1463 } |
1476 | 1464 |
1477 __ bind(&miss); | 1465 __ bind(&miss); |
1478 GenerateMiss(masm); | 1466 GenerateMiss(masm); |
1479 } | 1467 } |
1480 | 1468 |
1481 | 1469 |
1482 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { | 1470 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { |
1483 // eax : number of arguments to the construct function | 1471 // eax : number of arguments to the construct function |
1484 // ebx : feedback vector | 1472 // ebx : feedback vector |
(...skipping 1459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2944 Label miss; | 2932 Label miss; |
2945 Label::Distance const miss_distance = | 2933 Label::Distance const miss_distance = |
2946 masm->emit_debug_code() ? Label::kFar : Label::kNear; | 2934 masm->emit_debug_code() ? Label::kFar : Label::kNear; |
2947 | 2935 |
2948 __ JumpIfSmi(edx, &miss, miss_distance); | 2936 __ JumpIfSmi(edx, &miss, miss_distance); |
2949 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 2937 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
2950 __ JumpIfSmi(eax, &miss, miss_distance); | 2938 __ JumpIfSmi(eax, &miss, miss_distance); |
2951 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2939 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
2952 __ JumpIfNotRoot(ecx, Heap::kBooleanMapRootIndex, &miss, miss_distance); | 2940 __ JumpIfNotRoot(ecx, Heap::kBooleanMapRootIndex, &miss, miss_distance); |
2953 __ JumpIfNotRoot(ebx, Heap::kBooleanMapRootIndex, &miss, miss_distance); | 2941 __ JumpIfNotRoot(ebx, Heap::kBooleanMapRootIndex, &miss, miss_distance); |
2954 if (op() != Token::EQ_STRICT && is_strong(strength())) { | 2942 if (!Token::IsEqualityOp(op())) { |
2955 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); | 2943 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); |
2956 } else { | 2944 __ AssertSmi(eax); |
2957 if (!Token::IsEqualityOp(op())) { | 2945 __ mov(edx, FieldOperand(edx, Oddball::kToNumberOffset)); |
2958 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); | 2946 __ AssertSmi(edx); |
2959 __ AssertSmi(eax); | 2947 __ push(eax); |
2960 __ mov(edx, FieldOperand(edx, Oddball::kToNumberOffset)); | 2948 __ mov(eax, edx); |
2961 __ AssertSmi(edx); | 2949 __ pop(edx); |
2962 __ push(eax); | |
2963 __ mov(eax, edx); | |
2964 __ pop(edx); | |
2965 } | |
2966 __ sub(eax, edx); | |
2967 __ Ret(); | |
2968 } | 2950 } |
| 2951 __ sub(eax, edx); |
| 2952 __ Ret(); |
2969 | 2953 |
2970 __ bind(&miss); | 2954 __ bind(&miss); |
2971 GenerateMiss(masm); | 2955 GenerateMiss(masm); |
2972 } | 2956 } |
2973 | 2957 |
2974 | 2958 |
2975 void CompareICStub::GenerateSmis(MacroAssembler* masm) { | 2959 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
2976 DCHECK(state() == CompareICState::SMI); | 2960 DCHECK(state() == CompareICState::SMI); |
2977 Label miss; | 2961 Label miss; |
2978 __ mov(ecx, edx); | 2962 __ mov(ecx, edx); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3048 // Performing mov, because xor would destroy the flag register. | 3032 // Performing mov, because xor would destroy the flag register. |
3049 __ mov(eax, 0); // equal | 3033 __ mov(eax, 0); // equal |
3050 __ mov(ecx, Immediate(Smi::FromInt(1))); | 3034 __ mov(ecx, Immediate(Smi::FromInt(1))); |
3051 __ cmov(above, eax, ecx); | 3035 __ cmov(above, eax, ecx); |
3052 __ mov(ecx, Immediate(Smi::FromInt(-1))); | 3036 __ mov(ecx, Immediate(Smi::FromInt(-1))); |
3053 __ cmov(below, eax, ecx); | 3037 __ cmov(below, eax, ecx); |
3054 __ ret(0); | 3038 __ ret(0); |
3055 | 3039 |
3056 __ bind(&unordered); | 3040 __ bind(&unordered); |
3057 __ bind(&generic_stub); | 3041 __ bind(&generic_stub); |
3058 CompareICStub stub(isolate(), op(), strength(), CompareICState::GENERIC, | 3042 CompareICStub stub(isolate(), op(), CompareICState::GENERIC, |
3059 CompareICState::GENERIC, CompareICState::GENERIC); | 3043 CompareICState::GENERIC, CompareICState::GENERIC); |
3060 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3044 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
3061 | 3045 |
3062 __ bind(&maybe_undefined1); | 3046 __ bind(&maybe_undefined1); |
3063 if (Token::IsOrderedRelationalCompareOp(op())) { | 3047 if (Token::IsOrderedRelationalCompareOp(op())) { |
3064 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); | 3048 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); |
3065 __ j(not_equal, &miss); | 3049 __ j(not_equal, &miss); |
3066 __ JumpIfSmi(edx, &unordered); | 3050 __ JumpIfSmi(edx, &unordered); |
3067 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); | 3051 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); |
3068 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3052 __ j(not_equal, &maybe_undefined2, Label::kNear); |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3291 | 3275 |
3292 __ GetWeakValue(edi, cell); | 3276 __ GetWeakValue(edi, cell); |
3293 __ cmp(edi, FieldOperand(eax, HeapObject::kMapOffset)); | 3277 __ cmp(edi, FieldOperand(eax, HeapObject::kMapOffset)); |
3294 __ j(not_equal, &miss, Label::kNear); | 3278 __ j(not_equal, &miss, Label::kNear); |
3295 __ cmp(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 3279 __ cmp(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
3296 __ j(not_equal, &miss, Label::kNear); | 3280 __ j(not_equal, &miss, Label::kNear); |
3297 | 3281 |
3298 if (Token::IsEqualityOp(op())) { | 3282 if (Token::IsEqualityOp(op())) { |
3299 __ sub(eax, edx); | 3283 __ sub(eax, edx); |
3300 __ ret(0); | 3284 __ ret(0); |
3301 } else if (is_strong(strength())) { | |
3302 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); | |
3303 } else { | 3285 } else { |
3304 __ PopReturnAddressTo(ecx); | 3286 __ PopReturnAddressTo(ecx); |
3305 __ Push(edx); | 3287 __ Push(edx); |
3306 __ Push(eax); | 3288 __ Push(eax); |
3307 __ Push(Immediate(Smi::FromInt(NegativeComparisonResult(GetCondition())))); | 3289 __ Push(Immediate(Smi::FromInt(NegativeComparisonResult(GetCondition())))); |
3308 __ PushReturnAddressFrom(ecx); | 3290 __ PushReturnAddressFrom(ecx); |
3309 __ TailCallRuntime(Runtime::kCompare); | 3291 __ TailCallRuntime(Runtime::kCompare); |
3310 } | 3292 } |
3311 | 3293 |
3312 __ bind(&miss); | 3294 __ bind(&miss); |
(...skipping 2487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5800 return_value_operand, NULL); | 5782 return_value_operand, NULL); |
5801 } | 5783 } |
5802 | 5784 |
5803 | 5785 |
5804 #undef __ | 5786 #undef __ |
5805 | 5787 |
5806 } // namespace internal | 5788 } // namespace internal |
5807 } // namespace v8 | 5789 } // namespace v8 |
5808 | 5790 |
5809 #endif // V8_TARGET_ARCH_IA32 | 5791 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |