| 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 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 const LocationSummary& locs, | 319 const LocationSummary& locs, |
| 320 BranchInstr* branch, | 320 BranchInstr* branch, |
| 321 Token::Kind kind, | 321 Token::Kind kind, |
| 322 intptr_t deopt_id, | 322 intptr_t deopt_id, |
| 323 intptr_t token_pos, | 323 intptr_t token_pos, |
| 324 intptr_t try_index) { | 324 intptr_t try_index) { |
| 325 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 325 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 326 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); | 326 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); |
| 327 ASSERT(ic_data.NumberOfChecks() > 0); | 327 ASSERT(ic_data.NumberOfChecks() > 0); |
| 328 ASSERT(ic_data.num_args_tested() == 1); | 328 ASSERT(ic_data.num_args_tested() == 1); |
| 329 Label* deopt = compiler->AddDeoptStub(deopt_id, | 329 Label* deopt = compiler->AddDeoptStub(deopt_id, try_index, kDeoptEquality); |
| 330 token_pos, | |
| 331 try_index, | |
| 332 kDeoptEquality); | |
| 333 Register left = locs.in(0).reg(); | 330 Register left = locs.in(0).reg(); |
| 334 Register right = locs.in(1).reg(); | 331 Register right = locs.in(1).reg(); |
| 335 __ testq(left, Immediate(kSmiTagMask)); | 332 __ testq(left, Immediate(kSmiTagMask)); |
| 336 Register temp = locs.temp(0).reg(); | 333 Register temp = locs.temp(0).reg(); |
| 337 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { | 334 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { |
| 338 Label done, load_class_id; | 335 Label done, load_class_id; |
| 339 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 336 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
| 340 __ movq(temp, Immediate(kSmiCid)); | 337 __ movq(temp, Immediate(kSmiCid)); |
| 341 __ jmp(&done, Assembler::kNearJump); | 338 __ jmp(&done, Assembler::kNearJump); |
| 342 __ Bind(&load_class_id); | 339 __ Bind(&load_class_id); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 const LocationSummary& locs, | 450 const LocationSummary& locs, |
| 454 Token::Kind kind, | 451 Token::Kind kind, |
| 455 BranchInstr* branch, | 452 BranchInstr* branch, |
| 456 intptr_t deopt_id, | 453 intptr_t deopt_id, |
| 457 intptr_t token_pos, | 454 intptr_t token_pos, |
| 458 intptr_t try_index) { | 455 intptr_t try_index) { |
| 459 Register left = locs.in(0).reg(); | 456 Register left = locs.in(0).reg(); |
| 460 Register right = locs.in(1).reg(); | 457 Register right = locs.in(1).reg(); |
| 461 Register temp = locs.temp(0).reg(); | 458 Register temp = locs.temp(0).reg(); |
| 462 Label* deopt = compiler->AddDeoptStub(deopt_id, | 459 Label* deopt = compiler->AddDeoptStub(deopt_id, |
| 463 token_pos, | |
| 464 try_index, | 460 try_index, |
| 465 kDeoptSmiCompareSmi, | 461 kDeoptSmiCompareSmi, |
| 466 left, | 462 left, |
| 467 right); | 463 right); |
| 468 __ movq(temp, left); | 464 __ movq(temp, left); |
| 469 __ orq(temp, right); | 465 __ orq(temp, right); |
| 470 __ testq(temp, Immediate(kSmiTagMask)); | 466 __ testq(temp, Immediate(kSmiTagMask)); |
| 471 __ j(NOT_ZERO, deopt); | 467 __ j(NOT_ZERO, deopt); |
| 472 | 468 |
| 473 Condition true_condition = TokenKindToSmiCondition(kind); | 469 Condition true_condition = TokenKindToSmiCondition(kind); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 Token::Kind kind, | 504 Token::Kind kind, |
| 509 BranchInstr* branch, | 505 BranchInstr* branch, |
| 510 intptr_t deopt_id, | 506 intptr_t deopt_id, |
| 511 intptr_t token_pos, | 507 intptr_t token_pos, |
| 512 intptr_t try_index) { | 508 intptr_t try_index) { |
| 513 Register left = locs.in(0).reg(); | 509 Register left = locs.in(0).reg(); |
| 514 Register right = locs.in(1).reg(); | 510 Register right = locs.in(1).reg(); |
| 515 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. | 511 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. |
| 516 Register temp = locs.temp(0).reg(); | 512 Register temp = locs.temp(0).reg(); |
| 517 Label* deopt = compiler->AddDeoptStub(deopt_id, | 513 Label* deopt = compiler->AddDeoptStub(deopt_id, |
| 518 token_pos, | |
| 519 try_index, | 514 try_index, |
| 520 kDeoptDoubleComparison, | 515 kDeoptDoubleComparison, |
| 521 left, | 516 left, |
| 522 right); | 517 right); |
| 523 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 518 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| 524 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 519 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| 525 | 520 |
| 526 Condition true_condition = TokenKindToDoubleCondition(kind); | 521 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 527 if (branch != NULL) { | 522 if (branch != NULL) { |
| 528 compiler->EmitDoubleCompareBranch( | 523 compiler->EmitDoubleCompareBranch( |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 deopt_id(), token_pos(), try_index()); | 576 deopt_id(), token_pos(), try_index()); |
| 582 return; | 577 return; |
| 583 } | 578 } |
| 584 if (operands_class_id() == kDoubleCid) { | 579 if (operands_class_id() == kDoubleCid) { |
| 585 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, | 580 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, |
| 586 deopt_id(), token_pos(), try_index()); | 581 deopt_id(), token_pos(), try_index()); |
| 587 return; | 582 return; |
| 588 } | 583 } |
| 589 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 584 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 590 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 585 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 591 token_pos(), | |
| 592 try_index(), | 586 try_index(), |
| 593 kDeoptRelationalOp); | 587 kDeoptRelationalOp); |
| 594 // Load receiver into RAX, class into RDI. | 588 // Load receiver into RAX, class into RDI. |
| 595 Label done; | 589 Label done; |
| 596 const intptr_t kNumArguments = 2; | 590 const intptr_t kNumArguments = 2; |
| 597 __ movq(RDI, Immediate(kSmiCid)); | 591 __ movq(RDI, Immediate(kSmiCid)); |
| 598 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 592 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
| 599 __ testq(RAX, Immediate(kSmiTagMask)); | 593 __ testq(RAX, Immediate(kSmiTagMask)); |
| 600 __ j(ZERO, &done); | 594 __ j(ZERO, &done); |
| 601 __ LoadClassId(RDI, RAX); | 595 __ LoadClassId(RDI, RAX); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 } else { | 685 } else { |
| 692 ASSERT(receiver_type() == kIllegalCid); | 686 ASSERT(receiver_type() == kIllegalCid); |
| 693 return MakeCallSummary(); | 687 return MakeCallSummary(); |
| 694 } | 688 } |
| 695 } | 689 } |
| 696 | 690 |
| 697 | 691 |
| 698 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, | 692 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 699 LoadIndexedComp* comp) { | 693 LoadIndexedComp* comp) { |
| 700 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), | 694 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
| 701 comp->token_pos(), | |
| 702 comp->try_index(), | 695 comp->try_index(), |
| 703 kDeoptLoadIndexedPolymorphic); | 696 kDeoptLoadIndexedPolymorphic); |
| 704 ASSERT(comp->ic_data()->NumberOfChecks() > 0); | 697 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
| 705 ASSERT(comp->HasICData()); | 698 ASSERT(comp->HasICData()); |
| 706 const ICData& ic_data = *comp->ic_data(); | 699 const ICData& ic_data = *comp->ic_data(); |
| 707 ASSERT(ic_data.num_args_tested() == 1); | 700 ASSERT(ic_data.num_args_tested() == 1); |
| 708 // No indexed access on Smi. | 701 // No indexed access on Smi. |
| 709 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmiCid); | 702 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmiCid); |
| 710 // Load receiver into RAX. | 703 // Load receiver into RAX. |
| 711 const intptr_t kNumArguments = 2; | 704 const intptr_t kNumArguments = 2; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 738 | 731 |
| 739 Register receiver = locs()->in(0).reg(); | 732 Register receiver = locs()->in(0).reg(); |
| 740 Register index = locs()->in(1).reg(); | 733 Register index = locs()->in(1).reg(); |
| 741 Register result = locs()->out().reg(); | 734 Register result = locs()->out().reg(); |
| 742 | 735 |
| 743 const DeoptReasonId deopt_reason = | 736 const DeoptReasonId deopt_reason = |
| 744 (receiver_type() == kGrowableObjectArrayCid) ? | 737 (receiver_type() == kGrowableObjectArrayCid) ? |
| 745 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 738 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
| 746 | 739 |
| 747 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 740 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 748 token_pos(), | |
| 749 try_index(), | 741 try_index(), |
| 750 deopt_reason, | 742 deopt_reason, |
| 751 receiver, | 743 receiver, |
| 752 index); | 744 index); |
| 753 | 745 |
| 754 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 746 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
| 755 __ j(ZERO, deopt); | 747 __ j(ZERO, deopt); |
| 756 __ CompareClassId(receiver, receiver_type()); | 748 __ CompareClassId(receiver, receiver_type()); |
| 757 __ j(NOT_EQUAL, deopt); | 749 __ j(NOT_EQUAL, deopt); |
| 758 | 750 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 830 function_name, | 822 function_name, |
| 831 kNumArguments, | 823 kNumArguments, |
| 832 Array::ZoneHandle(), // No named arguments. | 824 Array::ZoneHandle(), // No named arguments. |
| 833 kNumArgsChecked); | 825 kNumArgsChecked); |
| 834 } | 826 } |
| 835 | 827 |
| 836 | 828 |
| 837 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, | 829 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 838 StoreIndexedComp* comp) { | 830 StoreIndexedComp* comp) { |
| 839 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), | 831 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
| 840 comp->token_pos(), | |
| 841 comp->try_index(), | 832 comp->try_index(), |
| 842 kDeoptStoreIndexedPolymorphic); | 833 kDeoptStoreIndexedPolymorphic); |
| 843 ASSERT(comp->ic_data()->NumberOfChecks() > 0); | 834 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
| 844 ASSERT(comp->HasICData()); | 835 ASSERT(comp->HasICData()); |
| 845 const ICData& ic_data = *comp->ic_data(); | 836 const ICData& ic_data = *comp->ic_data(); |
| 846 ASSERT(ic_data.num_args_tested() == 1); | 837 ASSERT(ic_data.num_args_tested() == 1); |
| 847 // No indexed access on Smi. | 838 // No indexed access on Smi. |
| 848 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmiCid); | 839 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmiCid); |
| 849 // Load receiver into RAX. | 840 // Load receiver into RAX. |
| 850 const intptr_t kNumArguments = 3; | 841 const intptr_t kNumArguments = 3; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 872 EmitStoreIndexedGeneric(compiler, this); | 863 EmitStoreIndexedGeneric(compiler, this); |
| 873 } | 864 } |
| 874 return; | 865 return; |
| 875 } | 866 } |
| 876 | 867 |
| 877 Register receiver = locs()->in(0).reg(); | 868 Register receiver = locs()->in(0).reg(); |
| 878 Register index = locs()->in(1).reg(); | 869 Register index = locs()->in(1).reg(); |
| 879 Register value = locs()->in(2).reg(); | 870 Register value = locs()->in(2).reg(); |
| 880 | 871 |
| 881 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 872 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 882 token_pos(), | |
| 883 try_index(), | 873 try_index(), |
| 884 kDeoptStoreIndexed, | 874 kDeoptStoreIndexed, |
| 885 receiver, | 875 receiver, |
| 886 index, | 876 index, |
| 887 value); | 877 value); |
| 888 | 878 |
| 889 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 879 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
| 890 __ j(ZERO, deopt); | 880 __ j(ZERO, deopt); |
| 891 __ CompareClassId(receiver, receiver_type()); | 881 __ CompareClassId(receiver, receiver_type()); |
| 892 __ j(NOT_EQUAL, deopt); | 882 __ j(NOT_EQUAL, deopt); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 938 } | 928 } |
| 939 | 929 |
| 940 | 930 |
| 941 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 931 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 942 Register instance_reg = locs()->in(0).reg(); | 932 Register instance_reg = locs()->in(0).reg(); |
| 943 Register result_reg = locs()->out().reg(); | 933 Register result_reg = locs()->out().reg(); |
| 944 | 934 |
| 945 if (HasICData()) { | 935 if (HasICData()) { |
| 946 ASSERT(original() != NULL); | 936 ASSERT(original() != NULL); |
| 947 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), | 937 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
| 948 original()->token_pos(), | |
| 949 original()->try_index(), | 938 original()->try_index(), |
| 950 kDeoptInstanceGetterSameTarget, | 939 kDeoptInstanceGetterSameTarget, |
| 951 instance_reg); | 940 instance_reg); |
| 952 // Smis do not have instance fields (Smi class is always first). | 941 // Smis do not have instance fields (Smi class is always first). |
| 953 // Use 'result' as temporary register. | 942 // Use 'result' as temporary register. |
| 954 ASSERT(result_reg != instance_reg); | 943 ASSERT(result_reg != instance_reg); |
| 955 ASSERT(ic_data() != NULL); | 944 ASSERT(ic_data() != NULL); |
| 956 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 945 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
| 957 } | 946 } |
| 958 __ movq(result_reg, FieldAddress(instance_reg, field().Offset())); | 947 __ movq(result_reg, FieldAddress(instance_reg, field().Offset())); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1071 LocationSummary::kNoCall); | 1060 LocationSummary::kNoCall); |
| 1072 } | 1061 } |
| 1073 | 1062 |
| 1074 | 1063 |
| 1075 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1064 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1076 Register instance_reg = locs()->in(0).reg(); | 1065 Register instance_reg = locs()->in(0).reg(); |
| 1077 Register result_reg = locs()->out().reg(); | 1066 Register result_reg = locs()->out().reg(); |
| 1078 if (HasICData()) { | 1067 if (HasICData()) { |
| 1079 ASSERT(original() != NULL); | 1068 ASSERT(original() != NULL); |
| 1080 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), | 1069 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
| 1081 original()->token_pos(), | |
| 1082 original()->try_index(), | 1070 original()->try_index(), |
| 1083 kDeoptInstanceGetterSameTarget, | 1071 kDeoptInstanceGetterSameTarget, |
| 1084 instance_reg); | 1072 instance_reg); |
| 1085 // Smis do not have instance fields (Smi class is always first). | 1073 // Smis do not have instance fields (Smi class is always first). |
| 1086 // Use 'result' as temporary register. | 1074 // Use 'result' as temporary register. |
| 1087 ASSERT(result_reg != instance_reg); | 1075 ASSERT(result_reg != instance_reg); |
| 1088 ASSERT(ic_data() != NULL); | 1076 ASSERT(ic_data() != NULL); |
| 1089 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 1077 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
| 1090 } | 1078 } |
| 1091 | 1079 |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1445 } | 1433 } |
| 1446 | 1434 |
| 1447 | 1435 |
| 1448 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1436 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
| 1449 Register left = comp->locs()->in(0).reg(); | 1437 Register left = comp->locs()->in(0).reg(); |
| 1450 Register right = comp->locs()->in(1).reg(); | 1438 Register right = comp->locs()->in(1).reg(); |
| 1451 Register result = comp->locs()->out().reg(); | 1439 Register result = comp->locs()->out().reg(); |
| 1452 Register temp = comp->locs()->temp(0).reg(); | 1440 Register temp = comp->locs()->temp(0).reg(); |
| 1453 ASSERT(left == result); | 1441 ASSERT(left == result); |
| 1454 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), | 1442 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), |
| 1455 comp->instance_call()->token_pos(), | |
| 1456 comp->instance_call()->try_index(), | 1443 comp->instance_call()->try_index(), |
| 1457 kDeoptSmiBinaryOp, | 1444 kDeoptSmiBinaryOp, |
| 1458 temp, | 1445 temp, |
| 1459 right); | 1446 right); |
| 1460 // TODO(vegorov): for many binary operations this pattern can be rearranged | 1447 // TODO(vegorov): for many binary operations this pattern can be rearranged |
| 1461 // to save one move. | 1448 // to save one move. |
| 1462 __ movq(temp, left); | 1449 __ movq(temp, left); |
| 1463 __ orq(left, right); | 1450 __ orq(left, right); |
| 1464 __ testq(left, Immediate(kSmiTagMask)); | 1451 __ testq(left, Immediate(kSmiTagMask)); |
| 1465 __ j(NOT_ZERO, deopt); | 1452 __ j(NOT_ZERO, deopt); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1602 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1589 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
| 1603 // receiver and a Mint or Smi argument. We fall back to the run time call if | 1590 // receiver and a Mint or Smi argument. We fall back to the run time call if |
| 1604 // both receiver and argument are Mint or if one of them is Mint and the other | 1591 // both receiver and argument are Mint or if one of them is Mint and the other |
| 1605 // is a negative Smi. | 1592 // is a negative Smi. |
| 1606 Register left = comp->locs()->in(0).reg(); | 1593 Register left = comp->locs()->in(0).reg(); |
| 1607 Register right = comp->locs()->in(1).reg(); | 1594 Register right = comp->locs()->in(1).reg(); |
| 1608 Register result = comp->locs()->out().reg(); | 1595 Register result = comp->locs()->out().reg(); |
| 1609 ASSERT(left == result); | 1596 ASSERT(left == result); |
| 1610 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1597 ASSERT(comp->op_kind() == Token::kBIT_AND); |
| 1611 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), | 1598 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), |
| 1612 comp->instance_call()->token_pos(), | |
| 1613 comp->instance_call()->try_index(), | 1599 comp->instance_call()->try_index(), |
| 1614 kDeoptMintBinaryOp, | 1600 kDeoptMintBinaryOp, |
| 1615 left, | 1601 left, |
| 1616 right); | 1602 right); |
| 1617 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1603 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
| 1618 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1604 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
| 1619 __ j(NOT_ZERO, &non_smi); | 1605 __ j(NOT_ZERO, &non_smi); |
| 1620 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1606 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1621 __ j(ZERO, &smi_smi); | 1607 __ j(ZERO, &smi_smi); |
| 1622 __ CompareClassId(right, kMintCid); // Is argument Mint? | 1608 __ CompareClassId(right, kMintCid); // Is argument Mint? |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1723 compiler->GenerateCall(instance_call()->token_pos(), | 1709 compiler->GenerateCall(instance_call()->token_pos(), |
| 1724 instance_call()->try_index(), | 1710 instance_call()->try_index(), |
| 1725 &label, | 1711 &label, |
| 1726 PcDescriptors::kOther); | 1712 PcDescriptors::kOther); |
| 1727 // Newly allocated object is now in the result register (RAX). | 1713 // Newly allocated object is now in the result register (RAX). |
| 1728 ASSERT(result == RAX); | 1714 ASSERT(result == RAX); |
| 1729 __ popq(right); | 1715 __ popq(right); |
| 1730 __ popq(left); | 1716 __ popq(left); |
| 1731 | 1717 |
| 1732 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1718 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1733 instance_call()->token_pos(), | |
| 1734 instance_call()->try_index(), | 1719 instance_call()->try_index(), |
| 1735 kDeoptDoubleBinaryOp, | 1720 kDeoptDoubleBinaryOp, |
| 1736 left, | 1721 left, |
| 1737 right); | 1722 right); |
| 1738 | 1723 |
| 1739 // Binary operation of two Smi's produces a Smi not a double. | 1724 // Binary operation of two Smi's produces a Smi not a double. |
| 1740 __ movq(temp, left); | 1725 __ movq(temp, left); |
| 1741 __ orq(temp, right); | 1726 __ orq(temp, right); |
| 1742 __ testq(temp, Immediate(kSmiTagMask)); | 1727 __ testq(temp, Immediate(kSmiTagMask)); |
| 1743 __ j(ZERO, deopt); | 1728 __ j(ZERO, deopt); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1775 // TODO(srdjan): Implement for more checks. | 1760 // TODO(srdjan): Implement for more checks. |
| 1776 ASSERT(ic_data.NumberOfChecks() == 1); | 1761 ASSERT(ic_data.NumberOfChecks() == 1); |
| 1777 intptr_t test_class_id; | 1762 intptr_t test_class_id; |
| 1778 Function& target = Function::Handle(); | 1763 Function& target = Function::Handle(); |
| 1779 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1764 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
| 1780 | 1765 |
| 1781 Register value = locs()->in(0).reg(); | 1766 Register value = locs()->in(0).reg(); |
| 1782 Register result = locs()->out().reg(); | 1767 Register result = locs()->out().reg(); |
| 1783 ASSERT(value == result); | 1768 ASSERT(value == result); |
| 1784 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1769 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1785 instance_call()->token_pos(), | |
| 1786 instance_call()->try_index(), | 1770 instance_call()->try_index(), |
| 1787 kDeoptUnaryOp, | 1771 kDeoptUnaryOp, |
| 1788 value); | 1772 value); |
| 1789 if (test_class_id == kSmiCid) { | 1773 if (test_class_id == kSmiCid) { |
| 1790 __ testq(value, Immediate(kSmiTagMask)); | 1774 __ testq(value, Immediate(kSmiTagMask)); |
| 1791 __ j(NOT_ZERO, deopt); | 1775 __ j(NOT_ZERO, deopt); |
| 1792 switch (op_kind()) { | 1776 switch (op_kind()) { |
| 1793 case Token::kNEGATE: | 1777 case Token::kNEGATE: |
| 1794 __ negq(value); | 1778 __ negq(value); |
| 1795 __ j(OVERFLOW, deopt); | 1779 __ j(OVERFLOW, deopt); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1827 // TODO(srdjan): Implement for more checks. | 1811 // TODO(srdjan): Implement for more checks. |
| 1828 ASSERT(ic_data.NumberOfChecks() == 1); | 1812 ASSERT(ic_data.NumberOfChecks() == 1); |
| 1829 intptr_t test_class_id; | 1813 intptr_t test_class_id; |
| 1830 Function& target = Function::Handle(); | 1814 Function& target = Function::Handle(); |
| 1831 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1815 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
| 1832 | 1816 |
| 1833 Register value = locs()->in(0).reg(); | 1817 Register value = locs()->in(0).reg(); |
| 1834 Register result = locs()->out().reg(); | 1818 Register result = locs()->out().reg(); |
| 1835 ASSERT(value == result); | 1819 ASSERT(value == result); |
| 1836 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1820 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1837 instance_call()->token_pos(), | |
| 1838 instance_call()->try_index(), | 1821 instance_call()->try_index(), |
| 1839 kDeoptUnaryOp, | 1822 kDeoptUnaryOp, |
| 1840 value); | 1823 value); |
| 1841 if (test_class_id == kDoubleCid) { | 1824 if (test_class_id == kDoubleCid) { |
| 1842 Register temp = locs()->temp(0).reg(); | 1825 Register temp = locs()->temp(0).reg(); |
| 1843 __ testq(value, Immediate(kSmiTagMask)); | 1826 __ testq(value, Immediate(kSmiTagMask)); |
| 1844 __ j(ZERO, deopt); // Smi. | 1827 __ j(ZERO, deopt); // Smi. |
| 1845 __ CompareClassId(value, kDoubleCid); | 1828 __ CompareClassId(value, kDoubleCid); |
| 1846 __ j(NOT_EQUAL, deopt); | 1829 __ j(NOT_EQUAL, deopt); |
| 1847 // Allocate result object. | 1830 // Allocate result object. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1883 } | 1866 } |
| 1884 | 1867 |
| 1885 | 1868 |
| 1886 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1869 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1887 Register value = (from() == kDoubleCid) ? locs()->in(0).reg() : RBX; | 1870 Register value = (from() == kDoubleCid) ? locs()->in(0).reg() : RBX; |
| 1888 Register result = locs()->out().reg(); | 1871 Register result = locs()->out().reg(); |
| 1889 | 1872 |
| 1890 const DeoptReasonId deopt_reason = (from() == kDoubleCid) ? | 1873 const DeoptReasonId deopt_reason = (from() == kDoubleCid) ? |
| 1891 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1874 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
| 1892 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1875 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1893 instance_call()->token_pos(), | |
| 1894 instance_call()->try_index(), | 1876 instance_call()->try_index(), |
| 1895 deopt_reason, | 1877 deopt_reason, |
| 1896 value); | 1878 value); |
| 1897 | 1879 |
| 1898 if (from() == kDoubleCid) { | 1880 if (from() == kDoubleCid) { |
| 1899 __ testq(value, Immediate(kSmiTagMask)); | 1881 __ testq(value, Immediate(kSmiTagMask)); |
| 1900 __ j(ZERO, deopt); // Deoptimize if Smi. | 1882 __ j(ZERO, deopt); // Deoptimize if Smi. |
| 1901 __ CompareClassId(value, kDoubleCid); | 1883 __ CompareClassId(value, kDoubleCid); |
| 1902 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 1884 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
| 1903 ASSERT(value == result); | 1885 ASSERT(value == result); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1927 } | 1909 } |
| 1928 | 1910 |
| 1929 | 1911 |
| 1930 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 1912 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { |
| 1931 return MakeCallSummary(); | 1913 return MakeCallSummary(); |
| 1932 } | 1914 } |
| 1933 | 1915 |
| 1934 | 1916 |
| 1935 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1917 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1936 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1918 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1937 instance_call()->token_pos(), | |
| 1938 instance_call()->try_index(), | 1919 instance_call()->try_index(), |
| 1939 kDeoptPolymorphicInstanceCallTestFail); | 1920 kDeoptPolymorphicInstanceCallTestFail); |
| 1940 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 1921 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
| 1941 __ jmp(deopt); | 1922 __ jmp(deopt); |
| 1942 return; | 1923 return; |
| 1943 } | 1924 } |
| 1944 ASSERT(HasICData()); | 1925 ASSERT(HasICData()); |
| 1945 ASSERT(ic_data()->num_args_tested() == 1); | 1926 ASSERT(ic_data()->num_args_tested() == 1); |
| 1946 Label handle_smi; | 1927 Label handle_smi; |
| 1947 Label* is_smi_label = | 1928 Label* is_smi_label = |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2078 ASSERT(locs()->out().reg() == RAX); | 2059 ASSERT(locs()->out().reg() == RAX); |
| 2079 __ CompareObject(locs()->out().reg(), compiler->bool_true()); | 2060 __ CompareObject(locs()->out().reg(), compiler->bool_true()); |
| 2080 EmitBranchOnCondition(compiler, branch_condition); | 2061 EmitBranchOnCondition(compiler, branch_condition); |
| 2081 } | 2062 } |
| 2082 | 2063 |
| 2083 } // namespace dart | 2064 } // namespace dart |
| 2084 | 2065 |
| 2085 #undef __ | 2066 #undef __ |
| 2086 | 2067 |
| 2087 #endif // defined TARGET_ARCH_X64 | 2068 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |