| 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 // TODO(srdjan): Replace the counting code with a type feedback | 61 // TODO(srdjan): Replace the counting code with a type feedback |
| 62 // collection and counting stub. | 62 // collection and counting stub. |
| 63 const Function& function = | 63 const Function& function = |
| 64 Function::ZoneHandle(compiler->parsed_function().function().raw()); | 64 Function::ZoneHandle(compiler->parsed_function().function().raw()); |
| 65 __ LoadObject(temp, function); | 65 __ LoadObject(temp, function); |
| 66 __ incq(FieldAddress(temp, Function::usage_counter_offset())); | 66 __ incq(FieldAddress(temp, Function::usage_counter_offset())); |
| 67 if (FlowGraphCompiler::CanOptimize()) { | 67 if (FlowGraphCompiler::CanOptimize()) { |
| 68 // Do not optimize if usage count must be reported. | 68 // Do not optimize if usage count must be reported. |
| 69 __ cmpl(FieldAddress(temp, Function::usage_counter_offset()), | 69 __ cmpl(FieldAddress(temp, Function::usage_counter_offset()), |
| 70 Immediate(FLAG_optimization_counter_threshold)); | 70 Immediate(FLAG_optimization_counter_threshold)); |
| 71 Label not_yet_hot; | 71 Label not_yet_hot, already_optimized; |
| 72 __ j(LESS_EQUAL, ¬_yet_hot, Assembler::kNearJump); | 72 __ j(LESS, ¬_yet_hot, Assembler::kNearJump); |
| 73 __ j(GREATER, &already_optimized, Assembler::kNearJump); |
| 73 __ pushq(result); // Preserve result. | 74 __ pushq(result); // Preserve result. |
| 74 __ pushq(temp); // Argument for runtime: function to optimize. | 75 __ pushq(temp); // Argument for runtime: function to optimize. |
| 75 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); | 76 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); |
| 76 __ popq(temp); // Remove argument. | 77 __ popq(temp); // Remove argument. |
| 77 __ popq(result); // Restore result. | 78 __ popq(result); // Restore result. |
| 78 __ Bind(¬_yet_hot); | 79 __ Bind(¬_yet_hot); |
| 80 __ Bind(&already_optimized); |
| 79 } | 81 } |
| 80 } | 82 } |
| 81 if (FLAG_trace_functions) { | 83 if (FLAG_trace_functions) { |
| 82 const Function& function = | 84 const Function& function = |
| 83 Function::ZoneHandle(compiler->parsed_function().function().raw()); | 85 Function::ZoneHandle(compiler->parsed_function().function().raw()); |
| 84 __ LoadObject(temp, function); | 86 __ LoadObject(temp, function); |
| 85 __ pushq(result); // Preserve result. | 87 __ pushq(result); // Preserve result. |
| 86 __ pushq(temp); | 88 __ pushq(temp); |
| 87 compiler->GenerateCallRuntime(AstNode::kNoId, | 89 compiler->GenerateCallRuntime(AstNode::kNoId, |
| 88 0, | 90 0, |
| (...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 | 572 |
| 571 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 573 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 572 if (operands_class_id() == kSmi) { | 574 if (operands_class_id() == kSmi) { |
| 573 EmitSmiRelationalOp(compiler, this); | 575 EmitSmiRelationalOp(compiler, this); |
| 574 return; | 576 return; |
| 575 } | 577 } |
| 576 if (operands_class_id() == kDouble) { | 578 if (operands_class_id() == kDouble) { |
| 577 EmitDoubleRelationalOp(compiler, this); | 579 EmitDoubleRelationalOp(compiler, this); |
| 578 return; | 580 return; |
| 579 } | 581 } |
| 582 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 583 Label* deopt = compiler->AddDeoptStub(cid(), |
| 584 token_pos(), |
| 585 try_index(), |
| 586 kDeoptRelationalOp); |
| 587 // Load receiver into RAX, class into RDI. |
| 588 Label done; |
| 589 const intptr_t kNumArguments = 2; |
| 590 __ movq(RDI, Immediate(kSmi)); |
| 591 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
| 592 __ testq(RAX, Immediate(kSmiTagMask)); |
| 593 __ j(ZERO, &done); |
| 594 __ LoadClassId(RDI, RAX); |
| 595 __ Bind(&done); |
| 596 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), |
| 597 RDI, // Class id register. |
| 598 kNumArguments, |
| 599 Array::Handle(), // No named arguments. |
| 600 deopt, // Deoptimize target. |
| 601 NULL, // Fallthrough when done. |
| 602 cid(), |
| 603 token_pos(), |
| 604 try_index()); |
| 605 return; |
| 606 } |
| 580 const String& function_name = | 607 const String& function_name = |
| 581 String::ZoneHandle(String::NewSymbol(Token::Str(kind()))); | 608 String::ZoneHandle(String::NewSymbol(Token::Str(kind()))); |
| 582 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 609 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 583 cid(), | 610 cid(), |
| 584 token_pos(), | 611 token_pos(), |
| 585 try_index()); | 612 try_index()); |
| 586 const intptr_t kNumArguments = 2; | 613 const intptr_t kNumArguments = 2; |
| 587 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 614 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
| 588 compiler->GenerateInstanceCall(cid(), | 615 compiler->GenerateInstanceCall(cid(), |
| 589 token_pos(), | 616 token_pos(), |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 } | 685 } |
| 659 } | 686 } |
| 660 | 687 |
| 661 | 688 |
| 662 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, | 689 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 663 LoadIndexedComp* comp) { | 690 LoadIndexedComp* comp) { |
| 664 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 691 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 665 comp->token_pos(), | 692 comp->token_pos(), |
| 666 comp->try_index(), | 693 comp->try_index(), |
| 667 kDeoptLoadIndexedPolymorphic); | 694 kDeoptLoadIndexedPolymorphic); |
| 668 if (comp->ic_data()->NumberOfChecks() == 0) { | 695 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
| 669 __ jmp(deopt); | |
| 670 return; | |
| 671 } | |
| 672 ASSERT(comp->HasICData()); | 696 ASSERT(comp->HasICData()); |
| 673 const ICData& ic_data = *comp->ic_data(); | 697 const ICData& ic_data = *comp->ic_data(); |
| 674 ASSERT(ic_data.num_args_tested() == 1); | 698 ASSERT(ic_data.num_args_tested() == 1); |
| 675 // No indexed access on Smi. | 699 // No indexed access on Smi. |
| 676 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 700 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
| 677 // Load receiver into RAX. | 701 // Load receiver into RAX. |
| 678 const intptr_t kNumArguments = 2; | 702 const intptr_t kNumArguments = 2; |
| 679 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 703 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
| 680 __ testq(RAX, Immediate(kSmiTagMask)); | 704 __ testq(RAX, Immediate(kSmiTagMask)); |
| 681 __ j(ZERO, deopt); | 705 __ j(ZERO, deopt); |
| 682 __ LoadClassId(RDI, RAX); | 706 __ LoadClassId(RDI, RAX); |
| 683 compiler->EmitTestAndCall(ic_data, | 707 compiler->EmitTestAndCall(ic_data, |
| 684 RDI, // Class id register. | 708 RDI, // Class id register. |
| 685 kNumArguments, | 709 kNumArguments, |
| 686 Array::Handle(), // No named arguments. | 710 Array::Handle(), // No named arguments. |
| 687 deopt, // Deoptimize target. | 711 deopt, // Deoptimize target. |
| 688 NULL, // Fallthrough when done. | 712 NULL, // Fallthrough when done. |
| 689 comp->cid(), | 713 comp->cid(), |
| 690 comp->token_pos(), | 714 comp->token_pos(), |
| 691 comp->try_index()); | 715 comp->try_index()); |
| 692 } | 716 } |
| 693 | 717 |
| 694 | 718 |
| 695 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 719 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 696 if (receiver_type() == kIllegalObjectKind) { | 720 if (receiver_type() == kIllegalObjectKind) { |
| 697 if (HasICData()) { | 721 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 698 EmitLoadIndexedPolymorphic(compiler, this); | 722 EmitLoadIndexedPolymorphic(compiler, this); |
| 699 } else { | 723 } else { |
| 700 compiler->EmitLoadIndexedGeneric(this); | 724 compiler->EmitLoadIndexedGeneric(this); |
| 701 } | 725 } |
| 702 ASSERT(locs()->out().reg() == RAX); | 726 ASSERT(locs()->out().reg() == RAX); |
| 703 return; | 727 return; |
| 704 } | 728 } |
| 705 | 729 |
| 706 Register receiver = locs()->in(0).reg(); | 730 Register receiver = locs()->in(0).reg(); |
| 707 Register index = locs()->in(1).reg(); | 731 Register index = locs()->in(1).reg(); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 kNumArgsChecked); | 820 kNumArgsChecked); |
| 797 } | 821 } |
| 798 | 822 |
| 799 | 823 |
| 800 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, | 824 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 801 StoreIndexedComp* comp) { | 825 StoreIndexedComp* comp) { |
| 802 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 826 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 803 comp->token_pos(), | 827 comp->token_pos(), |
| 804 comp->try_index(), | 828 comp->try_index(), |
| 805 kDeoptStoreIndexedPolymorphic); | 829 kDeoptStoreIndexedPolymorphic); |
| 806 if (comp->ic_data()->NumberOfChecks() == 0) { | 830 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
| 807 __ jmp(deopt); | |
| 808 return; | |
| 809 } | |
| 810 ASSERT(comp->HasICData()); | 831 ASSERT(comp->HasICData()); |
| 811 const ICData& ic_data = *comp->ic_data(); | 832 const ICData& ic_data = *comp->ic_data(); |
| 812 ASSERT(ic_data.num_args_tested() == 1); | 833 ASSERT(ic_data.num_args_tested() == 1); |
| 813 // No indexed access on Smi. | 834 // No indexed access on Smi. |
| 814 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 835 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
| 815 // Load receiver into RAX. | 836 // Load receiver into RAX. |
| 816 const intptr_t kNumArguments = 3; | 837 const intptr_t kNumArguments = 3; |
| 817 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 838 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
| 818 __ testq(RAX, Immediate(kSmiTagMask)); | 839 __ testq(RAX, Immediate(kSmiTagMask)); |
| 819 __ j(ZERO, deopt); | 840 __ j(ZERO, deopt); |
| 820 __ LoadClassId(RDI, RAX); | 841 __ LoadClassId(RDI, RAX); |
| 821 compiler->EmitTestAndCall(ic_data, | 842 compiler->EmitTestAndCall(ic_data, |
| 822 RDI, // Class id register. | 843 RDI, // Class id register. |
| 823 kNumArguments, | 844 kNumArguments, |
| 824 Array::Handle(), // No named arguments. | 845 Array::Handle(), // No named arguments. |
| 825 deopt, // deoptimize label. | 846 deopt, // deoptimize label. |
| 826 NULL, // fallthrough when done. | 847 NULL, // fallthrough when done. |
| 827 comp->cid(), | 848 comp->cid(), |
| 828 comp->token_pos(), | 849 comp->token_pos(), |
| 829 comp->try_index()); | 850 comp->try_index()); |
| 830 } | 851 } |
| 831 | 852 |
| 832 | 853 |
| 833 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 854 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 834 if (receiver_type() == kIllegalObjectKind) { | 855 if (receiver_type() == kIllegalObjectKind) { |
| 835 if (HasICData()) { | 856 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 836 EmitStoreIndexedPolymorphic(compiler, this); | 857 EmitStoreIndexedPolymorphic(compiler, this); |
| 837 } else { | 858 } else { |
| 838 EmitStoreIndexedGeneric(compiler, this); | 859 EmitStoreIndexedGeneric(compiler, this); |
| 839 } | 860 } |
| 840 return; | 861 return; |
| 841 } | 862 } |
| 842 | 863 |
| 843 Register receiver = locs()->in(0).reg(); | 864 Register receiver = locs()->in(0).reg(); |
| 844 Register index = locs()->in(1).reg(); | 865 Register index = locs()->in(1).reg(); |
| 845 Register value = locs()->in(2).reg(); | 866 Register value = locs()->in(2).reg(); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 } | 913 } |
| 893 } | 914 } |
| 894 | 915 |
| 895 | 916 |
| 896 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { | 917 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { |
| 897 return MakeCallSummary(); | 918 return MakeCallSummary(); |
| 898 } | 919 } |
| 899 | 920 |
| 900 | 921 |
| 901 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 922 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 902 const String& function_name = | 923 Label* deopt = NULL; |
| 903 String::ZoneHandle(Field::SetterSymbol(field_name())); | 924 if (compiler->is_optimizing()) { |
| 925 deopt = compiler->AddDeoptStub(cid(), |
| 926 token_pos(), |
| 927 try_index(), |
| 928 kDeoptInstanceSetter); |
| 929 } |
| 930 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 931 // No index-setter on Smi's. |
| 932 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmi); |
| 933 // Load receiver into RAX. |
| 934 const intptr_t kNumArguments = 2; |
| 935 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
| 936 __ testq(RAX, Immediate(kSmiTagMask)); |
| 937 __ j(ZERO, deopt); |
| 938 __ LoadClassId(RDI, RAX); |
| 939 compiler->EmitTestAndCall(*ic_data(), |
| 940 RDI, // Class id register. |
| 941 kNumArguments, |
| 942 Array::Handle(), // No named arguments. |
| 943 deopt, // Deoptimize target. |
| 944 NULL, // Fallthrough when done. |
| 945 cid(), |
| 946 token_pos(), |
| 947 try_index()); |
| 904 | 948 |
| 905 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 949 } else if (compiler->is_optimizing()) { |
| 906 cid(), | 950 // Get some IC data then optimize again. |
| 907 token_pos(), | 951 __ jmp(deopt); |
| 908 try_index()); | 952 } else { |
| 909 const intptr_t kArgumentCount = 2; | 953 // Unoptimized code. |
| 910 const intptr_t kCheckedArgumentCount = 1; | 954 const String& function_name = |
| 911 compiler->GenerateInstanceCall(cid(), | 955 String::ZoneHandle(Field::SetterSymbol(field_name())); |
| 912 token_pos(), | 956 |
| 913 try_index(), | 957 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 914 function_name, | 958 cid(), |
| 915 kArgumentCount, | 959 token_pos(), |
| 916 Array::ZoneHandle(), | 960 try_index()); |
| 917 kCheckedArgumentCount); | 961 const intptr_t kArgumentCount = 2; |
| 962 const intptr_t kCheckedArgumentCount = 1; |
| 963 compiler->GenerateInstanceCall(cid(), |
| 964 token_pos(), |
| 965 try_index(), |
| 966 function_name, |
| 967 kArgumentCount, |
| 968 Array::ZoneHandle(), |
| 969 kCheckedArgumentCount); |
| 970 } |
| 918 } | 971 } |
| 919 | 972 |
| 920 | 973 |
| 921 LocationSummary* StaticSetterComp::MakeLocationSummary() const { | 974 LocationSummary* StaticSetterComp::MakeLocationSummary() const { |
| 922 const intptr_t kNumInputs = 1; | 975 const intptr_t kNumInputs = 1; |
| 923 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); | 976 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); |
| 924 } | 977 } |
| 925 | 978 |
| 926 | 979 |
| 927 void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 980 void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 1051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1979 } | 2032 } |
| 1980 __ Bind(&done); | 2033 __ Bind(&done); |
| 1981 } | 2034 } |
| 1982 | 2035 |
| 1983 | 2036 |
| 1984 } // namespace dart | 2037 } // namespace dart |
| 1985 | 2038 |
| 1986 #undef __ | 2039 #undef __ |
| 1987 | 2040 |
| 1988 #endif // defined TARGET_ARCH_X64 | 2041 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |