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" |
(...skipping 1323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1334 __ JumpIfSmi(object, label); | 1334 __ JumpIfSmi(object, label); |
1335 __ mov(scratch, FieldOperand(object, HeapObject::kMapOffset)); | 1335 __ mov(scratch, FieldOperand(object, HeapObject::kMapOffset)); |
1336 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 1336 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
1337 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); | 1337 STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0); |
1338 __ test(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); | 1338 __ test(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask)); |
1339 __ j(not_zero, label); | 1339 __ j(not_zero, label); |
1340 } | 1340 } |
1341 | 1341 |
1342 | 1342 |
1343 void CompareICStub::GenerateGeneric(MacroAssembler* masm) { | 1343 void CompareICStub::GenerateGeneric(MacroAssembler* masm) { |
1344 Label check_unequal_objects; | 1344 Label runtime_call, check_unequal_objects; |
1345 Condition cc = GetCondition(); | 1345 Condition cc = GetCondition(); |
1346 | 1346 |
1347 Label miss; | 1347 Label miss; |
1348 CheckInputType(masm, edx, left(), &miss); | 1348 CheckInputType(masm, edx, left(), &miss); |
1349 CheckInputType(masm, eax, right(), &miss); | 1349 CheckInputType(masm, eax, right(), &miss); |
1350 | 1350 |
1351 // Compare two smis. | 1351 // Compare two smis. |
1352 Label non_smi, smi_done; | 1352 Label non_smi, smi_done; |
1353 __ mov(ecx, edx); | 1353 __ mov(ecx, edx); |
1354 __ or_(ecx, eax); | 1354 __ or_(ecx, eax); |
(...skipping 13 matching lines...) Expand all Loading... |
1368 // for NaN and undefined. | 1368 // for NaN and undefined. |
1369 Label generic_heap_number_comparison; | 1369 Label generic_heap_number_comparison; |
1370 { | 1370 { |
1371 Label not_identical; | 1371 Label not_identical; |
1372 __ cmp(eax, edx); | 1372 __ cmp(eax, edx); |
1373 __ j(not_equal, ¬_identical); | 1373 __ j(not_equal, ¬_identical); |
1374 | 1374 |
1375 if (cc != equal) { | 1375 if (cc != equal) { |
1376 // Check for undefined. undefined OP undefined is false even though | 1376 // Check for undefined. undefined OP undefined is false even though |
1377 // undefined == undefined. | 1377 // undefined == undefined. |
1378 Label check_for_nan; | |
1379 __ cmp(edx, isolate()->factory()->undefined_value()); | 1378 __ cmp(edx, isolate()->factory()->undefined_value()); |
1380 __ j(not_equal, &check_for_nan, Label::kNear); | 1379 if (strong()) { |
1381 __ Move(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); | 1380 // In strong mode, this comparison must throw, so call the runtime. |
1382 __ ret(0); | 1381 __ j(equal, &runtime_call, Label::kFar); |
1383 __ bind(&check_for_nan); | 1382 } else { |
| 1383 Label check_for_nan; |
| 1384 __ j(not_equal, &check_for_nan, Label::kNear); |
| 1385 __ Move(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); |
| 1386 __ ret(0); |
| 1387 __ bind(&check_for_nan); |
| 1388 } |
1384 } | 1389 } |
1385 | 1390 |
1386 // Test for NaN. Compare heap numbers in a general way, | 1391 // Test for NaN. Compare heap numbers in a general way, |
1387 // to hanlde NaNs correctly. | 1392 // to handle NaNs correctly. |
1388 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 1393 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
1389 Immediate(isolate()->factory()->heap_number_map())); | 1394 Immediate(isolate()->factory()->heap_number_map())); |
1390 __ j(equal, &generic_heap_number_comparison, Label::kNear); | 1395 __ j(equal, &generic_heap_number_comparison, Label::kNear); |
1391 if (cc != equal) { | 1396 if (cc != equal) { |
| 1397 __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 1398 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
1392 // Call runtime on identical JSObjects. Otherwise return equal. | 1399 // Call runtime on identical JSObjects. Otherwise return equal. |
1393 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); | 1400 __ cmpb(ecx, static_cast<uint8_t>(FIRST_SPEC_OBJECT_TYPE)); |
1394 __ j(above_equal, ¬_identical); | 1401 __ j(above_equal, &runtime_call, Label::kFar); |
1395 // Call runtime on identical symbols since we need to throw a TypeError. | 1402 // Call runtime on identical symbols since we need to throw a TypeError. |
1396 __ CmpObjectType(eax, SYMBOL_TYPE, ecx); | 1403 __ cmpb(ecx, static_cast<uint8_t>(SYMBOL_TYPE)); |
1397 __ j(equal, ¬_identical); | 1404 __ j(equal, &runtime_call, Label::kFar); |
| 1405 if (strong()) { |
| 1406 // We have already tested for smis and heap numbers, so if both |
| 1407 // arguments are not strings we must proceed to the slow case. |
| 1408 __ test(ecx, Immediate(kIsNotStringMask)); |
| 1409 __ j(not_zero, &runtime_call, Label::kFar); |
| 1410 } |
1398 } | 1411 } |
1399 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); | 1412 __ Move(eax, Immediate(Smi::FromInt(EQUAL))); |
1400 __ ret(0); | 1413 __ ret(0); |
1401 | 1414 |
1402 | 1415 |
1403 __ bind(¬_identical); | 1416 __ bind(¬_identical); |
1404 } | 1417 } |
1405 | 1418 |
1406 // Strict equality can quickly decide whether objects are equal. | 1419 // Strict equality can quickly decide whether objects are equal. |
1407 // Non-strict object equality is slower, so it is handled later in the stub. | 1420 // Non-strict object equality is slower, so it is handled later in the stub. |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1544 } | 1557 } |
1545 #ifdef DEBUG | 1558 #ifdef DEBUG |
1546 __ Abort(kUnexpectedFallThroughFromStringComparison); | 1559 __ Abort(kUnexpectedFallThroughFromStringComparison); |
1547 #endif | 1560 #endif |
1548 | 1561 |
1549 __ bind(&check_unequal_objects); | 1562 __ bind(&check_unequal_objects); |
1550 if (cc == equal && !strict()) { | 1563 if (cc == equal && !strict()) { |
1551 // Non-strict equality. Objects are unequal if | 1564 // Non-strict equality. Objects are unequal if |
1552 // they are both JSObjects and not undetectable, | 1565 // they are both JSObjects and not undetectable, |
1553 // and their pointers are different. | 1566 // and their pointers are different. |
1554 Label not_both_objects; | |
1555 Label return_unequal; | 1567 Label return_unequal; |
1556 // At most one is a smi, so we can test for smi by adding the two. | 1568 // At most one is a smi, so we can test for smi by adding the two. |
1557 // A smi plus a heap object has the low bit set, a heap object plus | 1569 // A smi plus a heap object has the low bit set, a heap object plus |
1558 // a heap object has the low bit clear. | 1570 // a heap object has the low bit clear. |
1559 STATIC_ASSERT(kSmiTag == 0); | 1571 STATIC_ASSERT(kSmiTag == 0); |
1560 STATIC_ASSERT(kSmiTagMask == 1); | 1572 STATIC_ASSERT(kSmiTagMask == 1); |
1561 __ lea(ecx, Operand(eax, edx, times_1, 0)); | 1573 __ lea(ecx, Operand(eax, edx, times_1, 0)); |
1562 __ test(ecx, Immediate(kSmiTagMask)); | 1574 __ test(ecx, Immediate(kSmiTagMask)); |
1563 __ j(not_zero, ¬_both_objects, Label::kNear); | 1575 __ j(not_zero, &runtime_call, Label::kNear); |
1564 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); | 1576 __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); |
1565 __ j(below, ¬_both_objects, Label::kNear); | 1577 __ j(below, &runtime_call, Label::kNear); |
1566 __ CmpObjectType(edx, FIRST_SPEC_OBJECT_TYPE, ebx); | 1578 __ CmpObjectType(edx, FIRST_SPEC_OBJECT_TYPE, ebx); |
1567 __ j(below, ¬_both_objects, Label::kNear); | 1579 __ j(below, &runtime_call, Label::kNear); |
1568 // We do not bail out after this point. Both are JSObjects, and | 1580 // We do not bail out after this point. Both are JSObjects, and |
1569 // they are equal if and only if both are undetectable. | 1581 // they are equal if and only if both are undetectable. |
1570 // The and of the undetectable flags is 1 if and only if they are equal. | 1582 // The and of the undetectable flags is 1 if and only if they are equal. |
1571 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), | 1583 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
1572 1 << Map::kIsUndetectable); | 1584 1 << Map::kIsUndetectable); |
1573 __ j(zero, &return_unequal, Label::kNear); | 1585 __ j(zero, &return_unequal, Label::kNear); |
1574 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), | 1586 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), |
1575 1 << Map::kIsUndetectable); | 1587 1 << Map::kIsUndetectable); |
1576 __ j(zero, &return_unequal, Label::kNear); | 1588 __ j(zero, &return_unequal, Label::kNear); |
1577 // The objects are both undetectable, so they both compare as the value | 1589 // The objects are both undetectable, so they both compare as the value |
1578 // undefined, and are equal. | 1590 // undefined, and are equal. |
1579 __ Move(eax, Immediate(EQUAL)); | 1591 __ Move(eax, Immediate(EQUAL)); |
1580 __ bind(&return_unequal); | 1592 __ bind(&return_unequal); |
1581 // Return non-equal by returning the non-zero object pointer in eax, | 1593 // Return non-equal by returning the non-zero object pointer in eax, |
1582 // or return equal if we fell through to here. | 1594 // or return equal if we fell through to here. |
1583 __ ret(0); // rax, rdx were pushed | 1595 __ ret(0); // rax, rdx were pushed |
1584 __ bind(¬_both_objects); | |
1585 } | 1596 } |
| 1597 __ bind(&runtime_call); |
1586 | 1598 |
1587 // Push arguments below the return address. | 1599 // Push arguments below the return address. |
1588 __ pop(ecx); | 1600 __ pop(ecx); |
1589 __ push(edx); | 1601 __ push(edx); |
1590 __ push(eax); | 1602 __ push(eax); |
1591 | 1603 |
1592 // Figure out which native to call and setup the arguments. | 1604 // Figure out which native to call and setup the arguments. |
1593 Builtins::JavaScript builtin; | 1605 Builtins::JavaScript builtin; |
1594 if (cc == equal) { | 1606 if (cc == equal) { |
1595 builtin = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; | 1607 builtin = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; |
1596 } else { | 1608 } else { |
1597 builtin = Builtins::COMPARE; | 1609 builtin = strong() ? Builtins::COMPARE_STRONG : Builtins::COMPARE; |
1598 __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); | 1610 __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); |
1599 } | 1611 } |
1600 | 1612 |
1601 // Restore return address on the stack. | 1613 // Restore return address on the stack. |
1602 __ push(ecx); | 1614 __ push(ecx); |
1603 | 1615 |
1604 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 1616 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
1605 // tagged as a small integer. | 1617 // tagged as a small integer. |
1606 __ InvokeBuiltin(builtin, JUMP_FUNCTION); | 1618 __ InvokeBuiltin(builtin, JUMP_FUNCTION); |
1607 | 1619 |
(...skipping 1685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3293 __ j(not_equal, &maybe_undefined1, Label::kNear); | 3305 __ j(not_equal, &maybe_undefined1, Label::kNear); |
3294 | 3306 |
3295 __ bind(&check_left); | 3307 __ bind(&check_left); |
3296 __ JumpIfSmi(edx, &generic_stub, Label::kNear); | 3308 __ JumpIfSmi(edx, &generic_stub, Label::kNear); |
3297 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 3309 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
3298 isolate()->factory()->heap_number_map()); | 3310 isolate()->factory()->heap_number_map()); |
3299 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3311 __ j(not_equal, &maybe_undefined2, Label::kNear); |
3300 | 3312 |
3301 __ bind(&unordered); | 3313 __ bind(&unordered); |
3302 __ bind(&generic_stub); | 3314 __ bind(&generic_stub); |
3303 CompareICStub stub(isolate(), op(), CompareICState::GENERIC, | 3315 CompareICStub stub(isolate(), op(), strong(), CompareICState::GENERIC, |
3304 CompareICState::GENERIC, CompareICState::GENERIC); | 3316 CompareICState::GENERIC, CompareICState::GENERIC); |
3305 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 3317 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
3306 | 3318 |
3307 __ bind(&maybe_undefined1); | 3319 __ bind(&maybe_undefined1); |
3308 if (Token::IsOrderedRelationalCompareOp(op())) { | 3320 if (Token::IsOrderedRelationalCompareOp(op())) { |
3309 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); | 3321 __ cmp(eax, Immediate(isolate()->factory()->undefined_value())); |
3310 __ j(not_equal, &miss); | 3322 __ j(not_equal, &miss); |
3311 __ JumpIfSmi(edx, &unordered); | 3323 __ JumpIfSmi(edx, &unordered); |
3312 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); | 3324 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); |
3313 __ j(not_equal, &maybe_undefined2, Label::kNear); | 3325 __ j(not_equal, &maybe_undefined2, Label::kNear); |
(...skipping 1765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5079 ApiParameterOperand(2), kStackSpace, nullptr, | 5091 ApiParameterOperand(2), kStackSpace, nullptr, |
5080 Operand(ebp, 7 * kPointerSize), NULL); | 5092 Operand(ebp, 7 * kPointerSize), NULL); |
5081 } | 5093 } |
5082 | 5094 |
5083 | 5095 |
5084 #undef __ | 5096 #undef __ |
5085 | 5097 |
5086 } } // namespace v8::internal | 5098 } } // namespace v8::internal |
5087 | 5099 |
5088 #endif // V8_TARGET_ARCH_X87 | 5100 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |