| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 // on the stack and return the result in a fixed register RAX. | 26 // on the stack and return the result in a fixed register RAX. |
| 27 LocationSummary* Computation::MakeCallSummary() { | 27 LocationSummary* Computation::MakeCallSummary() { |
| 28 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall); | 28 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall); |
| 29 result->set_out(Location::RegisterLocation(RAX)); | 29 result->set_out(Location::RegisterLocation(RAX)); |
| 30 return result; | 30 return result; |
| 31 } | 31 } |
| 32 | 32 |
| 33 | 33 |
| 34 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 34 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 35 computation()->EmitNativeCode(compiler); | 35 computation()->EmitNativeCode(compiler); |
| 36 if (is_used() && locs()->out().IsRegister()) { | 36 if (is_used() && !compiler->is_optimizing()) { |
| 37 // TODO(vegorov): this should really happen only for comparisons fused | 37 __ pushq(locs()->out().reg()); |
| 38 // with branches. Currrently IR does not provide an easy way to remove | |
| 39 // instructions from the graph so we just leave fused comparison in it | |
| 40 // but change its result location to be NoLocation. | |
| 41 compiler->frame_register_allocator()->Push(locs()->out().reg(), this); | |
| 42 } | 38 } |
| 43 } | 39 } |
| 44 | 40 |
| 45 | 41 |
| 46 LocationSummary* ReturnInstr::MakeLocationSummary() const { | 42 LocationSummary* ReturnInstr::MakeLocationSummary() const { |
| 47 const intptr_t kNumInputs = 1; | 43 const intptr_t kNumInputs = 1; |
| 48 const intptr_t kNumTemps = 1; | 44 const intptr_t kNumTemps = 1; |
| 49 LocationSummary* locs = | 45 LocationSummary* locs = |
| 50 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 46 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 51 locs->set_in(0, Location::RegisterLocation(RAX)); | 47 locs->set_in(0, Location::RegisterLocation(RAX)); |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 BranchInstr* branch, | 453 BranchInstr* branch, |
| 458 intptr_t deopt_id, | 454 intptr_t deopt_id, |
| 459 intptr_t token_pos, | 455 intptr_t token_pos, |
| 460 intptr_t try_index) { | 456 intptr_t try_index) { |
| 461 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 457 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 462 Register left = locs.in(0).reg(); | 458 Register left = locs.in(0).reg(); |
| 463 Register right = locs.in(1).reg(); | 459 Register right = locs.in(1).reg(); |
| 464 Register temp = locs.temp(0).reg(); | 460 Register temp = locs.temp(0).reg(); |
| 465 Label* deopt = compiler->AddDeoptStub(deopt_id, | 461 Label* deopt = compiler->AddDeoptStub(deopt_id, |
| 466 try_index, | 462 try_index, |
| 467 kDeoptEquality, | 463 kDeoptEquality); |
| 468 left, | |
| 469 right); | |
| 470 __ testq(left, Immediate(kSmiTagMask)); | 464 __ testq(left, Immediate(kSmiTagMask)); |
| 471 __ j(ZERO, deopt); | 465 __ j(ZERO, deopt); |
| 472 // 'left' is not Smi. | 466 // 'left' is not Smi. |
| 473 const Immediate raw_null = | 467 const Immediate raw_null = |
| 474 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 468 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 475 Label identity_compare; | 469 Label identity_compare; |
| 476 __ cmpq(right, raw_null); | 470 __ cmpq(right, raw_null); |
| 477 __ j(EQUAL, &identity_compare); | 471 __ j(EQUAL, &identity_compare); |
| 478 __ cmpq(left, raw_null); | 472 __ cmpq(left, raw_null); |
| 479 __ j(EQUAL, &identity_compare); | 473 __ j(EQUAL, &identity_compare); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 Register left = locs.in(0).reg(); | 560 Register left = locs.in(0).reg(); |
| 567 Register right = locs.in(1).reg(); | 561 Register right = locs.in(1).reg(); |
| 568 const bool left_is_smi = (branch == NULL) ? | 562 const bool left_is_smi = (branch == NULL) ? |
| 569 false : (branch->left()->ResultCid() == kSmiCid); | 563 false : (branch->left()->ResultCid() == kSmiCid); |
| 570 const bool right_is_smi = (branch == NULL) ? | 564 const bool right_is_smi = (branch == NULL) ? |
| 571 false : (branch->right()->ResultCid() == kSmiCid); | 565 false : (branch->right()->ResultCid() == kSmiCid); |
| 572 if (!left_is_smi || !right_is_smi) { | 566 if (!left_is_smi || !right_is_smi) { |
| 573 Register temp = locs.temp(0).reg(); | 567 Register temp = locs.temp(0).reg(); |
| 574 Label* deopt = compiler->AddDeoptStub(deopt_id, | 568 Label* deopt = compiler->AddDeoptStub(deopt_id, |
| 575 try_index, | 569 try_index, |
| 576 kDeoptSmiCompareSmi, | 570 kDeoptSmiCompareSmi); |
| 577 left, | |
| 578 right); | |
| 579 __ movq(temp, left); | 571 __ movq(temp, left); |
| 580 __ orq(temp, right); | 572 __ orq(temp, right); |
| 581 __ testq(temp, Immediate(kSmiTagMask)); | 573 __ testq(temp, Immediate(kSmiTagMask)); |
| 582 __ j(NOT_ZERO, deopt); | 574 __ j(NOT_ZERO, deopt); |
| 583 } | 575 } |
| 584 | 576 |
| 585 Condition true_condition = TokenKindToSmiCondition(kind); | 577 Condition true_condition = TokenKindToSmiCondition(kind); |
| 586 __ cmpq(left, right); | 578 __ cmpq(left, right); |
| 587 | 579 |
| 588 if (branch != NULL) { | 580 if (branch != NULL) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 BranchInstr* branch, | 613 BranchInstr* branch, |
| 622 intptr_t deopt_id, | 614 intptr_t deopt_id, |
| 623 intptr_t token_pos, | 615 intptr_t token_pos, |
| 624 intptr_t try_index) { | 616 intptr_t try_index) { |
| 625 Register left = locs.in(0).reg(); | 617 Register left = locs.in(0).reg(); |
| 626 Register right = locs.in(1).reg(); | 618 Register right = locs.in(1).reg(); |
| 627 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. | 619 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. |
| 628 Register temp = locs.temp(0).reg(); | 620 Register temp = locs.temp(0).reg(); |
| 629 Label* deopt = compiler->AddDeoptStub(deopt_id, | 621 Label* deopt = compiler->AddDeoptStub(deopt_id, |
| 630 try_index, | 622 try_index, |
| 631 kDeoptDoubleComparison, | 623 kDeoptDoubleComparison); |
| 632 left, | |
| 633 right); | |
| 634 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 624 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| 635 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 625 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| 636 | 626 |
| 637 Condition true_condition = TokenKindToDoubleCondition(kind); | 627 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 638 if (branch != NULL) { | 628 if (branch != NULL) { |
| 639 compiler->EmitDoubleCompareBranch( | 629 compiler->EmitDoubleCompareBranch( |
| 640 true_condition, XMM0, XMM1, branch); | 630 true_condition, XMM0, XMM1, branch); |
| 641 } else { | 631 } else { |
| 642 compiler->EmitDoubleCompareBool( | 632 compiler->EmitDoubleCompareBool( |
| 643 true_condition, XMM0, XMM1, locs.out().reg()); | 633 true_condition, XMM0, XMM1, locs.out().reg()); |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 844 Register receiver = locs()->in(0).reg(); | 834 Register receiver = locs()->in(0).reg(); |
| 845 Register index = locs()->in(1).reg(); | 835 Register index = locs()->in(1).reg(); |
| 846 Register result = locs()->out().reg(); | 836 Register result = locs()->out().reg(); |
| 847 | 837 |
| 848 const DeoptReasonId deopt_reason = | 838 const DeoptReasonId deopt_reason = |
| 849 (receiver_type() == kGrowableObjectArrayCid) ? | 839 (receiver_type() == kGrowableObjectArrayCid) ? |
| 850 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 840 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
| 851 | 841 |
| 852 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), | 842 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
| 853 original()->try_index(), | 843 original()->try_index(), |
| 854 deopt_reason, | 844 deopt_reason); |
| 855 receiver, | |
| 856 index); | |
| 857 | 845 |
| 858 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 846 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
| 859 __ j(ZERO, deopt); | 847 __ j(ZERO, deopt); |
| 860 __ CompareClassId(receiver, receiver_type()); | 848 __ CompareClassId(receiver, receiver_type()); |
| 861 __ j(NOT_EQUAL, deopt); | 849 __ j(NOT_EQUAL, deopt); |
| 862 | 850 |
| 863 __ testq(index, Immediate(kSmiTagMask)); | 851 __ testq(index, Immediate(kSmiTagMask)); |
| 864 __ j(NOT_ZERO, deopt); | 852 __ j(NOT_ZERO, deopt); |
| 865 | 853 |
| 866 switch (receiver_type()) { | 854 switch (receiver_type()) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 914 } | 902 } |
| 915 | 903 |
| 916 | 904 |
| 917 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 905 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 918 Register receiver = locs()->in(0).reg(); | 906 Register receiver = locs()->in(0).reg(); |
| 919 Register index = locs()->in(1).reg(); | 907 Register index = locs()->in(1).reg(); |
| 920 Register value = locs()->in(2).reg(); | 908 Register value = locs()->in(2).reg(); |
| 921 | 909 |
| 922 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), | 910 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
| 923 original()->try_index(), | 911 original()->try_index(), |
| 924 kDeoptStoreIndexed, | 912 kDeoptStoreIndexed); |
| 925 receiver, | |
| 926 index, | |
| 927 value); | |
| 928 | 913 |
| 929 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 914 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
| 930 __ j(ZERO, deopt); | 915 __ j(ZERO, deopt); |
| 931 __ CompareClassId(receiver, receiver_type()); | 916 __ CompareClassId(receiver, receiver_type()); |
| 932 __ j(NOT_EQUAL, deopt); | 917 __ j(NOT_EQUAL, deopt); |
| 933 | 918 |
| 934 __ testq(index, Immediate(kSmiTagMask)); | 919 __ testq(index, Immediate(kSmiTagMask)); |
| 935 __ j(NOT_ZERO, deopt); | 920 __ j(NOT_ZERO, deopt); |
| 936 | 921 |
| 937 switch (receiver_type()) { | 922 switch (receiver_type()) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 979 | 964 |
| 980 | 965 |
| 981 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 966 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 982 Register instance_reg = locs()->in(0).reg(); | 967 Register instance_reg = locs()->in(0).reg(); |
| 983 Register result_reg = locs()->out().reg(); | 968 Register result_reg = locs()->out().reg(); |
| 984 | 969 |
| 985 if (HasICData()) { | 970 if (HasICData()) { |
| 986 ASSERT(original() != NULL); | 971 ASSERT(original() != NULL); |
| 987 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), | 972 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
| 988 original()->try_index(), | 973 original()->try_index(), |
| 989 kDeoptInstanceGetterSameTarget, | 974 kDeoptInstanceGetterSameTarget); |
| 990 instance_reg); | |
| 991 // Smis do not have instance fields (Smi class is always first). | 975 // Smis do not have instance fields (Smi class is always first). |
| 992 // Use 'result' as temporary register. | 976 // Use 'result' as temporary register. |
| 993 ASSERT(result_reg != instance_reg); | 977 ASSERT(result_reg != instance_reg); |
| 994 ASSERT(ic_data() != NULL); | 978 ASSERT(ic_data() != NULL); |
| 995 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 979 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
| 996 } | 980 } |
| 997 __ movq(result_reg, FieldAddress(instance_reg, field().Offset())); | 981 __ movq(result_reg, FieldAddress(instance_reg, field().Offset())); |
| 998 } | 982 } |
| 999 | 983 |
| 1000 | 984 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1114 } | 1098 } |
| 1115 | 1099 |
| 1116 | 1100 |
| 1117 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1101 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1118 Register instance_reg = locs()->in(0).reg(); | 1102 Register instance_reg = locs()->in(0).reg(); |
| 1119 Register result_reg = locs()->out().reg(); | 1103 Register result_reg = locs()->out().reg(); |
| 1120 if (HasICData()) { | 1104 if (HasICData()) { |
| 1121 ASSERT(original() != NULL); | 1105 ASSERT(original() != NULL); |
| 1122 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), | 1106 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
| 1123 original()->try_index(), | 1107 original()->try_index(), |
| 1124 kDeoptInstanceGetterSameTarget, | 1108 kDeoptInstanceGetterSameTarget); |
| 1125 instance_reg); | |
| 1126 // Smis do not have instance fields (Smi class is always first). | 1109 // Smis do not have instance fields (Smi class is always first). |
| 1127 // Use 'result' as temporary register. | 1110 // Use 'result' as temporary register. |
| 1128 ASSERT(result_reg != instance_reg); | 1111 ASSERT(result_reg != instance_reg); |
| 1129 ASSERT(ic_data() != NULL); | 1112 ASSERT(ic_data() != NULL); |
| 1130 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 1113 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
| 1131 } | 1114 } |
| 1132 | 1115 |
| 1133 __ movq(result_reg, FieldAddress(instance_reg, offset_in_bytes())); | 1116 __ movq(result_reg, FieldAddress(instance_reg, offset_in_bytes())); |
| 1134 } | 1117 } |
| 1135 | 1118 |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1523 case Token::kBIT_XOR: | 1506 case Token::kBIT_XOR: |
| 1524 can_deopt = !(right_is_smi && left_is_smi); | 1507 can_deopt = !(right_is_smi && left_is_smi); |
| 1525 break; | 1508 break; |
| 1526 default: | 1509 default: |
| 1527 can_deopt = true; | 1510 can_deopt = true; |
| 1528 } | 1511 } |
| 1529 Label* deopt = NULL; | 1512 Label* deopt = NULL; |
| 1530 if (can_deopt) { | 1513 if (can_deopt) { |
| 1531 deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), | 1514 deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), |
| 1532 comp->instance_call()->try_index(), | 1515 comp->instance_call()->try_index(), |
| 1533 kDeoptSmiBinaryOp, | 1516 kDeoptSmiBinaryOp); |
| 1534 temp, | |
| 1535 right); | |
| 1536 } | 1517 } |
| 1537 if (left_is_smi && right_is_smi) { | 1518 if (left_is_smi && right_is_smi) { |
| 1538 if (can_deopt) { | 1519 if (can_deopt) { |
| 1539 // Preserve left for deopt. | 1520 // Preserve left for deopt. |
| 1540 __ movq(temp, left); | 1521 __ movq(temp, left); |
| 1541 } | 1522 } |
| 1542 } else { | 1523 } else { |
| 1543 // TODO(vegorov): for many binary operations this pattern can be rearranged | 1524 // TODO(vegorov): for many binary operations this pattern can be rearranged |
| 1544 // to save one move. | 1525 // to save one move. |
| 1545 __ movq(temp, left); | 1526 __ movq(temp, left); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1689 // receiver and a Mint or Smi argument. We fall back to the run time call if | 1670 // receiver and a Mint or Smi argument. We fall back to the run time call if |
| 1690 // both receiver and argument are Mint or if one of them is Mint and the other | 1671 // both receiver and argument are Mint or if one of them is Mint and the other |
| 1691 // is a negative Smi. | 1672 // is a negative Smi. |
| 1692 Register left = comp->locs()->in(0).reg(); | 1673 Register left = comp->locs()->in(0).reg(); |
| 1693 Register right = comp->locs()->in(1).reg(); | 1674 Register right = comp->locs()->in(1).reg(); |
| 1694 Register result = comp->locs()->out().reg(); | 1675 Register result = comp->locs()->out().reg(); |
| 1695 ASSERT(left == result); | 1676 ASSERT(left == result); |
| 1696 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1677 ASSERT(comp->op_kind() == Token::kBIT_AND); |
| 1697 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), | 1678 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), |
| 1698 comp->instance_call()->try_index(), | 1679 comp->instance_call()->try_index(), |
| 1699 kDeoptMintBinaryOp, | 1680 kDeoptMintBinaryOp); |
| 1700 left, | |
| 1701 right); | |
| 1702 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1681 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
| 1703 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1682 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
| 1704 __ j(NOT_ZERO, &non_smi); | 1683 __ j(NOT_ZERO, &non_smi); |
| 1705 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1684 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1706 __ j(ZERO, &smi_smi); | 1685 __ j(ZERO, &smi_smi); |
| 1707 __ CompareClassId(right, kMintCid); // Is argument Mint? | 1686 __ CompareClassId(right, kMintCid); // Is argument Mint? |
| 1708 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. | 1687 __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint. |
| 1709 __ cmpq(left, Immediate(0)); | 1688 __ cmpq(left, Immediate(0)); |
| 1710 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. | 1689 __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument. |
| 1711 | 1690 |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1865 ASSERT(ic_data.NumberOfChecks() == 1); | 1844 ASSERT(ic_data.NumberOfChecks() == 1); |
| 1866 intptr_t test_class_id; | 1845 intptr_t test_class_id; |
| 1867 Function& target = Function::Handle(); | 1846 Function& target = Function::Handle(); |
| 1868 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1847 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
| 1869 | 1848 |
| 1870 Register value = locs()->in(0).reg(); | 1849 Register value = locs()->in(0).reg(); |
| 1871 Register result = locs()->out().reg(); | 1850 Register result = locs()->out().reg(); |
| 1872 ASSERT(value == result); | 1851 ASSERT(value == result); |
| 1873 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1852 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1874 instance_call()->try_index(), | 1853 instance_call()->try_index(), |
| 1875 kDeoptUnaryOp, | 1854 kDeoptUnaryOp); |
| 1876 value); | |
| 1877 if (test_class_id == kSmiCid) { | 1855 if (test_class_id == kSmiCid) { |
| 1878 __ testq(value, Immediate(kSmiTagMask)); | 1856 __ testq(value, Immediate(kSmiTagMask)); |
| 1879 __ j(NOT_ZERO, deopt); | 1857 __ j(NOT_ZERO, deopt); |
| 1880 switch (op_kind()) { | 1858 switch (op_kind()) { |
| 1881 case Token::kNEGATE: | 1859 case Token::kNEGATE: |
| 1882 __ negq(value); | 1860 __ negq(value); |
| 1883 __ j(OVERFLOW, deopt); | 1861 __ j(OVERFLOW, deopt); |
| 1884 break; | 1862 break; |
| 1885 case Token::kBIT_NOT: | 1863 case Token::kBIT_NOT: |
| 1886 __ notq(value); | 1864 __ notq(value); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1916 ASSERT(ic_data.NumberOfChecks() == 1); | 1894 ASSERT(ic_data.NumberOfChecks() == 1); |
| 1917 intptr_t test_class_id; | 1895 intptr_t test_class_id; |
| 1918 Function& target = Function::Handle(); | 1896 Function& target = Function::Handle(); |
| 1919 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1897 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
| 1920 | 1898 |
| 1921 Register value = locs()->in(0).reg(); | 1899 Register value = locs()->in(0).reg(); |
| 1922 Register result = locs()->out().reg(); | 1900 Register result = locs()->out().reg(); |
| 1923 ASSERT(value == result); | 1901 ASSERT(value == result); |
| 1924 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1902 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1925 instance_call()->try_index(), | 1903 instance_call()->try_index(), |
| 1926 kDeoptUnaryOp, | 1904 kDeoptUnaryOp); |
| 1927 value); | |
| 1928 if (test_class_id == kDoubleCid) { | 1905 if (test_class_id == kDoubleCid) { |
| 1929 Register temp = locs()->temp(0).reg(); | 1906 Register temp = locs()->temp(0).reg(); |
| 1930 __ testq(value, Immediate(kSmiTagMask)); | 1907 __ testq(value, Immediate(kSmiTagMask)); |
| 1931 __ j(ZERO, deopt); // Smi. | 1908 __ j(ZERO, deopt); // Smi. |
| 1932 __ CompareClassId(value, kDoubleCid); | 1909 __ CompareClassId(value, kDoubleCid); |
| 1933 __ j(NOT_EQUAL, deopt); | 1910 __ j(NOT_EQUAL, deopt); |
| 1934 // Allocate result object. | 1911 // Allocate result object. |
| 1935 const Class& double_class = compiler->double_class(); | 1912 const Class& double_class = compiler->double_class(); |
| 1936 const Code& stub = | 1913 const Code& stub = |
| 1937 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1914 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1966 return locs; | 1943 return locs; |
| 1967 } | 1944 } |
| 1968 | 1945 |
| 1969 | 1946 |
| 1970 void DoubleToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1947 void DoubleToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1971 Register value = locs()->in(0).reg(); | 1948 Register value = locs()->in(0).reg(); |
| 1972 Register result = locs()->out().reg(); | 1949 Register result = locs()->out().reg(); |
| 1973 | 1950 |
| 1974 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1951 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1975 instance_call()->try_index(), | 1952 instance_call()->try_index(), |
| 1976 kDeoptDoubleToDouble, | 1953 kDeoptDoubleToDouble); |
| 1977 value); | |
| 1978 | 1954 |
| 1979 __ testq(value, Immediate(kSmiTagMask)); | 1955 __ testq(value, Immediate(kSmiTagMask)); |
| 1980 __ j(ZERO, deopt); // Deoptimize if Smi. | 1956 __ j(ZERO, deopt); // Deoptimize if Smi. |
| 1981 __ CompareClassId(value, kDoubleCid); | 1957 __ CompareClassId(value, kDoubleCid); |
| 1982 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 1958 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
| 1983 ASSERT(value == result); | 1959 ASSERT(value == result); |
| 1984 } | 1960 } |
| 1985 | 1961 |
| 1986 | 1962 |
| 1987 LocationSummary* SmiToDoubleComp::MakeLocationSummary() const { | 1963 LocationSummary* SmiToDoubleComp::MakeLocationSummary() const { |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2219 summary->set_temp(0, Location::RequiresRegister()); | 2195 summary->set_temp(0, Location::RequiresRegister()); |
| 2220 return summary; | 2196 return summary; |
| 2221 } | 2197 } |
| 2222 | 2198 |
| 2223 | 2199 |
| 2224 void CheckClassComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 2200 void CheckClassComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2225 Register value = locs()->in(0).reg(); | 2201 Register value = locs()->in(0).reg(); |
| 2226 Register temp = locs()->temp(0).reg(); | 2202 Register temp = locs()->temp(0).reg(); |
| 2227 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 2203 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 2228 try_index(), | 2204 try_index(), |
| 2229 kDeoptCheckClass, | 2205 kDeoptCheckClass); |
| 2230 value); | |
| 2231 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmiCid); | 2206 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmiCid); |
| 2232 __ testq(value, Immediate(kSmiTagMask)); | 2207 __ testq(value, Immediate(kSmiTagMask)); |
| 2233 __ j(ZERO, deopt); | 2208 __ j(ZERO, deopt); |
| 2234 __ LoadClassId(temp, value); | 2209 __ LoadClassId(temp, value); |
| 2235 Label is_ok; | 2210 Label is_ok; |
| 2236 const intptr_t num_checks = ic_data()->NumberOfChecks(); | 2211 const intptr_t num_checks = ic_data()->NumberOfChecks(); |
| 2237 const bool use_near_jump = num_checks < 5; | 2212 const bool use_near_jump = num_checks < 5; |
| 2238 for (intptr_t i = 0; i < num_checks; i++) { | 2213 for (intptr_t i = 0; i < num_checks; i++) { |
| 2239 __ cmpl(temp, Immediate(ic_data()->GetReceiverClassIdAt(i))); | 2214 __ cmpl(temp, Immediate(ic_data()->GetReceiverClassIdAt(i))); |
| 2240 if (i == (num_checks - 1)) { | 2215 if (i == (num_checks - 1)) { |
| 2241 __ j(NOT_EQUAL, deopt); | 2216 __ j(NOT_EQUAL, deopt); |
| 2242 } else { | 2217 } else { |
| 2243 if (use_near_jump) { | 2218 if (use_near_jump) { |
| 2244 __ j(EQUAL, &is_ok, Assembler::kNearJump); | 2219 __ j(EQUAL, &is_ok, Assembler::kNearJump); |
| 2245 } else { | 2220 } else { |
| 2246 __ j(EQUAL, &is_ok); | 2221 __ j(EQUAL, &is_ok); |
| 2247 } | 2222 } |
| 2248 } | 2223 } |
| 2249 } | 2224 } |
| 2250 __ Bind(&is_ok); | 2225 __ Bind(&is_ok); |
| 2251 } | 2226 } |
| 2252 | 2227 |
| 2253 } // namespace dart | 2228 } // namespace dart |
| 2254 | 2229 |
| 2255 #undef __ | 2230 #undef __ |
| 2256 | 2231 |
| 2257 #endif // defined TARGET_ARCH_X64 | 2232 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |