| 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 |