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_X87 | 5 #if V8_TARGET_ARCH_X87 |
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 1275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1286 Label generic_heap_number_comparison; | 1286 Label generic_heap_number_comparison; |
1287 { | 1287 { |
1288 Label not_identical; | 1288 Label not_identical; |
1289 __ cmp(eax, edx); | 1289 __ cmp(eax, edx); |
1290 __ j(not_equal, ¬_identical); | 1290 __ j(not_equal, ¬_identical); |
1291 | 1291 |
1292 if (cc != equal) { | 1292 if (cc != equal) { |
1293 // Check for undefined. undefined OP undefined is false even though | 1293 // Check for undefined. undefined OP undefined is false even though |
1294 // undefined == undefined. | 1294 // undefined == undefined. |
1295 __ cmp(edx, isolate()->factory()->undefined_value()); | 1295 __ cmp(edx, isolate()->factory()->undefined_value()); |
1296 if (is_strong(strength())) { | 1296 Label check_for_nan; |
1297 // In strong mode, this comparison must throw, so call the runtime. | 1297 __ j(not_equal, &check_for_nan, Label::kNear); |
1298 __ j(equal, &runtime_call, Label::kFar); | 1298 __ Move(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); |
1299 } else { | 1299 __ ret(0); |
1300 Label check_for_nan; | 1300 __ bind(&check_for_nan); |
1301 __ j(not_equal, &check_for_nan, Label::kNear); | |
1302 __ Move(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); | |
1303 __ ret(0); | |
1304 __ bind(&check_for_nan); | |
1305 } | |
1306 } | 1301 } |
1307 | 1302 |
1308 // Test for NaN. Compare heap numbers in a general way, | 1303 // Test for NaN. Compare heap numbers in a general way, |
1309 // to handle NaNs correctly. | 1304 // to handle NaNs correctly. |
1310 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 1305 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
1311 Immediate(isolate()->factory()->heap_number_map())); | 1306 Immediate(isolate()->factory()->heap_number_map())); |
1312 __ j(equal, &generic_heap_number_comparison, Label::kNear); | 1307 __ j(equal, &generic_heap_number_comparison, Label::kNear); |
1313 if (cc != equal) { | 1308 if (cc != equal) { |
1314 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); | 1309 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
1315 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 1310 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
1316 // Call runtime on identical JSObjects. Otherwise return equal. | 1311 // Call runtime on identical JSObjects. Otherwise return equal. |
1317 __ cmpb(ecx, static_cast<uint8_t>(FIRST_JS_RECEIVER_TYPE)); | 1312 __ cmpb(ecx, static_cast<uint8_t>(FIRST_JS_RECEIVER_TYPE)); |
1318 __ j(above_equal, &runtime_call, Label::kFar); | 1313 __ j(above_equal, &runtime_call, Label::kFar); |
1319 // Call runtime on identical symbols since we need to throw a TypeError. | 1314 // Call runtime on identical symbols since we need to throw a TypeError. |
1320 __ cmpb(ecx, static_cast<uint8_t>(SYMBOL_TYPE)); | 1315 __ cmpb(ecx, static_cast<uint8_t>(SYMBOL_TYPE)); |
1321 __ j(equal, &runtime_call, Label::kFar); | 1316 __ j(equal, &runtime_call, Label::kFar); |
1322 // Call runtime on identical SIMD values since we must throw a TypeError. | 1317 // Call runtime on identical SIMD values since we must throw a TypeError. |
1323 __ cmpb(ecx, static_cast<uint8_t>(SIMD128_VALUE_TYPE)); | 1318 __ cmpb(ecx, static_cast<uint8_t>(SIMD128_VALUE_TYPE)); |
1324 __ j(equal, &runtime_call, Label::kFar); | 1319 __ j(equal, &runtime_call, Label::kFar); |
1325 if (is_strong(strength())) { | |
1326 // We have already tested for smis and heap numbers, so if both | |
1327 // arguments are not strings we must proceed to the slow case. | |
1328 __ test(ecx, Immediate(kIsNotStringMask)); | |
1329 __ j(not_zero, &runtime_call, Label::kFar); | |
1330 } | |
1331 } | 1320 } |
1332 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 1321 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
1333 __ ret(0); | 1322 __ ret(0); |
1334 | 1323 |
1335 | 1324 |
1336 __ bind(¬_identical); | 1325 __ bind(¬_identical); |
1337 } | 1326 } |
1338 | 1327 |
1339 // Strict equality can quickly decide whether objects are equal. | 1328 // Strict equality can quickly decide whether objects are equal. |
1340 // Non-strict object equality is slower, so it is handled later in the stub. | 1329 // Non-strict object equality is slower, so it is handled later in the stub. |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1532 __ push(ecx); | 1521 __ push(ecx); |
1533 __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals); | 1522 __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals); |
1534 } else { | 1523 } else { |
1535 __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); | 1524 __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); |
1536 | 1525 |
1537 // Restore return address on the stack. | 1526 // Restore return address on the stack. |
1538 __ push(ecx); | 1527 __ push(ecx); |
1539 | 1528 |
1540 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 1529 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
1541 // tagged as a small integer. | 1530 // tagged as a small integer. |
1542 __ TailCallRuntime(is_strong(strength()) ? Runtime::kCompare_Strong | 1531 __ TailCallRuntime(Runtime::kCompare); |
1543 : Runtime::kCompare); | |
1544 } | 1532 } |
1545 | 1533 |
1546 __ bind(&miss); | 1534 __ bind(&miss); |
1547 GenerateMiss(masm); | 1535 GenerateMiss(masm); |
1548 } | 1536 } |
1549 | 1537 |
1550 | 1538 |
1551 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { | 1539 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) { |
1552 // eax : number of arguments to the construct function | 1540 // eax : number of arguments to the construct function |
1553 // ebx : feedback vector | 1541 // ebx : feedback vector |
(...skipping 1462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3016 Label miss; | 3004 Label miss; |
3017 Label::Distance const miss_distance = | 3005 Label::Distance const miss_distance = |
3018 masm->emit_debug_code() ? Label::kFar : Label::kNear; | 3006 masm->emit_debug_code() ? Label::kFar : Label::kNear; |
3019 | 3007 |
3020 __ JumpIfSmi(edx, &miss, miss_distance); | 3008 __ JumpIfSmi(edx, &miss, miss_distance); |
3021 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 3009 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
3022 __ JumpIfSmi(eax, &miss, miss_distance); | 3010 __ JumpIfSmi(eax, &miss, miss_distance); |
3023 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 3011 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
3024 __ JumpIfNotRoot(ecx, Heap::kBooleanMapRootIndex, &miss, miss_distance); | 3012 __ JumpIfNotRoot(ecx, Heap::kBooleanMapRootIndex, &miss, miss_distance); |
3025 __ JumpIfNotRoot(ebx, Heap::kBooleanMapRootIndex, &miss, miss_distance); | 3013 __ JumpIfNotRoot(ebx, Heap::kBooleanMapRootIndex, &miss, miss_distance); |
3026 if (op() != Token::EQ_STRICT && is_strong(strength())) { | 3014 if (!Token::IsEqualityOp(op())) { |
3027 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); | 3015 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); |
3028 } else { | 3016 __ AssertSmi(eax); |
3029 if (!Token::IsEqualityOp(op())) { | 3017 __ mov(edx, FieldOperand(edx, Oddball::kToNumberOffset)); |
3030 __ mov(eax, FieldOperand(eax, Oddball::kToNumberOffset)); | 3018 __ AssertSmi(edx); |
3031 __ AssertSmi(eax); | 3019 __ xchg(eax, edx); |
3032 __ mov(edx, FieldOperand(edx, Oddball::kToNumberOffset)); | |
3033 __ AssertSmi(edx); | |
3034 __ xchg(eax, edx); | |
3035 } | |
3036 __ sub(eax, edx); | |
3037 __ Ret(); | |
3038 } | 3020 } |
| 3021 __ sub(eax, edx); |
| 3022 __ Ret(); |
3039 | 3023 |
3040 __ bind(&miss); | 3024 __ bind(&miss); |
3041 GenerateMiss(masm); | 3025 GenerateMiss(masm); |
3042 } | 3026 } |
3043 | 3027 |
3044 | 3028 |
3045 void CompareICStub::GenerateSmis(MacroAssembler* masm) { | 3029 void CompareICStub::GenerateSmis(MacroAssembler* masm) { |
3046 DCHECK(state() == CompareICState::SMI); | 3030 DCHECK(state() == CompareICState::SMI); |
3047 Label miss; | 3031 Label miss; |
3048 __ mov(ecx, edx); | 3032 __ mov(ecx, edx); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3090 __ j(not_equal, &maybe_undefined1, Label::kNear); | 3074 __ j(not_equal, &maybe_undefined1, Label::kNear); |
3091 | 3075 |
3092 __ bind(&check_left); | 3076 __ bind(&check_left); |
3093 __ JumpIfSmi(edx, &generic_stub, Label::kNear); | 3077 __ JumpIfSmi(edx, &generic_stub, Label::kNear); |
3094 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 3078 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
3095 isolate()->factory()->heap_number_map()); | 3079 isolate()->factory()->heap_number_map()); |
3096 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3080 __ j(not_equal, &maybe_undefined2, Label::kNear); |
3097 | 3081 |
3098 __ bind(&unordered); | 3082 __ bind(&unordered); |
3099 __ bind(&generic_stub); | 3083 __ bind(&generic_stub); |
3100 CompareICStub stub(isolate(), op(), strength(), CompareICState::GENERIC, | 3084 CompareICStub stub(isolate(), op(), CompareICState::GENERIC, |
3101 CompareICState::GENERIC, CompareICState::GENERIC); | 3085 CompareICState::GENERIC, CompareICState::GENERIC); |
3102 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3086 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
3103 | 3087 |
3104 __ bind(&maybe_undefined1); | 3088 __ bind(&maybe_undefined1); |
3105 if (Token::IsOrderedRelationalCompareOp(op())) { | 3089 if (Token::IsOrderedRelationalCompareOp(op())) { |
3106 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); | 3090 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); |
3107 __ j(not_equal, &miss); | 3091 __ j(not_equal, &miss); |
3108 __ JumpIfSmi(edx, &unordered); | 3092 __ JumpIfSmi(edx, &unordered); |
3109 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); | 3093 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); |
3110 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3094 __ j(not_equal, &maybe_undefined2, Label::kNear); |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3333 | 3317 |
3334 __ GetWeakValue(edi, cell); | 3318 __ GetWeakValue(edi, cell); |
3335 __ cmp(edi, FieldOperand(eax, HeapObject::kMapOffset)); | 3319 __ cmp(edi, FieldOperand(eax, HeapObject::kMapOffset)); |
3336 __ j(not_equal, &miss, Label::kNear); | 3320 __ j(not_equal, &miss, Label::kNear); |
3337 __ cmp(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 3321 __ cmp(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
3338 __ j(not_equal, &miss, Label::kNear); | 3322 __ j(not_equal, &miss, Label::kNear); |
3339 | 3323 |
3340 if (Token::IsEqualityOp(op())) { | 3324 if (Token::IsEqualityOp(op())) { |
3341 __ sub(eax, edx); | 3325 __ sub(eax, edx); |
3342 __ ret(0); | 3326 __ ret(0); |
3343 } else if (is_strong(strength())) { | |
3344 __ TailCallRuntime(Runtime::kThrowStrongModeImplicitConversion); | |
3345 } else { | 3327 } else { |
3346 __ PopReturnAddressTo(ecx); | 3328 __ PopReturnAddressTo(ecx); |
3347 __ Push(edx); | 3329 __ Push(edx); |
3348 __ Push(eax); | 3330 __ Push(eax); |
3349 __ Push(Immediate(Smi::FromInt(NegativeComparisonResult(GetCondition())))); | 3331 __ Push(Immediate(Smi::FromInt(NegativeComparisonResult(GetCondition())))); |
3350 __ PushReturnAddressFrom(ecx); | 3332 __ PushReturnAddressFrom(ecx); |
3351 __ TailCallRuntime(Runtime::kCompare); | 3333 __ TailCallRuntime(Runtime::kCompare); |
3352 } | 3334 } |
3353 | 3335 |
3354 __ bind(&miss); | 3336 __ bind(&miss); |
(...skipping 2131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5486 return_value_operand, NULL); | 5468 return_value_operand, NULL); |
5487 } | 5469 } |
5488 | 5470 |
5489 | 5471 |
5490 #undef __ | 5472 #undef __ |
5491 | 5473 |
5492 } // namespace internal | 5474 } // namespace internal |
5493 } // namespace v8 | 5475 } // namespace v8 |
5494 | 5476 |
5495 #endif // V8_TARGET_ARCH_X87 | 5477 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |