| 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 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 __ incl(FieldAddress(temp, Function::usage_counter_offset())); | 66 __ incl(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 __ pushl(result); // Preserve result. | 74 __ pushl(result); // Preserve result. |
| 74 __ pushl(temp); // Argument for runtime: function to optimize. | 75 __ pushl(temp); // Argument for runtime: function to optimize. |
| 75 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); | 76 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); |
| 76 __ popl(temp); // Remove argument. | 77 __ popl(temp); // Remove argument. |
| 77 __ popl(result); // Restore result. | 78 __ popl(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 __ pushl(result); // Preserve result. | 87 __ pushl(result); // Preserve result. |
| 86 __ pushl(temp); | 88 __ pushl(temp); |
| 87 compiler->GenerateCallRuntime(AstNode::kNoId, | 89 compiler->GenerateCallRuntime(AstNode::kNoId, |
| 88 0, | 90 0, |
| (...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 561 | 563 |
| 562 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 564 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 563 if (operands_class_id() == kSmi) { | 565 if (operands_class_id() == kSmi) { |
| 564 EmitSmiRelationalOp(compiler, this); | 566 EmitSmiRelationalOp(compiler, this); |
| 565 return; | 567 return; |
| 566 } | 568 } |
| 567 if (operands_class_id() == kDouble) { | 569 if (operands_class_id() == kDouble) { |
| 568 EmitDoubleRelationalOp(compiler, this); | 570 EmitDoubleRelationalOp(compiler, this); |
| 569 return; | 571 return; |
| 570 } | 572 } |
| 573 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 574 Label* deopt = compiler->AddDeoptStub(cid(), |
| 575 token_pos(), |
| 576 try_index(), |
| 577 kDeoptRelationalOp); |
| 578 // Load receiver into EAX, class into EDI. |
| 579 Label done; |
| 580 const intptr_t kNumArguments = 2; |
| 581 __ movl(EDI, Immediate(kSmi)); |
| 582 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
| 583 __ testl(EAX, Immediate(kSmiTagMask)); |
| 584 __ j(ZERO, &done); |
| 585 __ LoadClassId(EDI, EAX); |
| 586 __ Bind(&done); |
| 587 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), |
| 588 EDI, // Class id register. |
| 589 kNumArguments, |
| 590 Array::Handle(), // No named arguments. |
| 591 deopt, // Deoptimize target. |
| 592 NULL, // Fallthrough when done. |
| 593 cid(), |
| 594 token_pos(), |
| 595 try_index()); |
| 596 return; |
| 597 } |
| 571 const String& function_name = | 598 const String& function_name = |
| 572 String::ZoneHandle(String::NewSymbol(Token::Str(kind()))); | 599 String::ZoneHandle(String::NewSymbol(Token::Str(kind()))); |
| 573 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 600 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 574 cid(), | 601 cid(), |
| 575 token_pos(), | 602 token_pos(), |
| 576 try_index()); | 603 try_index()); |
| 577 const intptr_t kNumArguments = 2; | 604 const intptr_t kNumArguments = 2; |
| 578 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 605 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
| 579 compiler->GenerateInstanceCall(cid(), | 606 compiler->GenerateInstanceCall(cid(), |
| 580 token_pos(), | 607 token_pos(), |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 } | 675 } |
| 649 } | 676 } |
| 650 | 677 |
| 651 | 678 |
| 652 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, | 679 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 653 LoadIndexedComp* comp) { | 680 LoadIndexedComp* comp) { |
| 654 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 681 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 655 comp->token_pos(), | 682 comp->token_pos(), |
| 656 comp->try_index(), | 683 comp->try_index(), |
| 657 kDeoptLoadIndexedPolymorphic); | 684 kDeoptLoadIndexedPolymorphic); |
| 658 if (comp->ic_data()->NumberOfChecks() == 0) { | 685 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
| 659 __ jmp(deopt); | |
| 660 return; | |
| 661 } | |
| 662 ASSERT(comp->HasICData()); | 686 ASSERT(comp->HasICData()); |
| 663 const ICData& ic_data = *comp->ic_data(); | 687 const ICData& ic_data = *comp->ic_data(); |
| 664 ASSERT(ic_data.num_args_tested() == 1); | 688 ASSERT(ic_data.num_args_tested() == 1); |
| 665 // No indexed access on Smi. | 689 // No indexed access on Smi. |
| 666 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 690 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
| 667 // Load receiver into EAX. | 691 // Load receiver into EAX. |
| 668 const intptr_t kNumArguments = 2; | 692 const intptr_t kNumArguments = 2; |
| 669 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); | 693 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
| 670 __ testl(EAX, Immediate(kSmiTagMask)); | 694 __ testl(EAX, Immediate(kSmiTagMask)); |
| 671 __ j(ZERO, deopt); | 695 __ j(ZERO, deopt); |
| 672 __ LoadClassId(EDI, EAX); | 696 __ LoadClassId(EDI, EAX); |
| 673 compiler->EmitTestAndCall(ic_data, | 697 compiler->EmitTestAndCall(ic_data, |
| 674 EDI, // Class id register. | 698 EDI, // Class id register. |
| 675 kNumArguments, | 699 kNumArguments, |
| 676 Array::Handle(), // No named arguments. | 700 Array::Handle(), // No named arguments. |
| 677 deopt, // Deoptimize target. | 701 deopt, // Deoptimize target. |
| 678 NULL, // Fallthrough when done. | 702 NULL, // Fallthrough when done. |
| 679 comp->cid(), | 703 comp->cid(), |
| 680 comp->token_pos(), | 704 comp->token_pos(), |
| 681 comp->try_index()); | 705 comp->try_index()); |
| 682 } | 706 } |
| 683 | 707 |
| 684 | 708 |
| 685 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 709 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 686 if (receiver_type() == kIllegalObjectKind) { | 710 if (receiver_type() == kIllegalObjectKind) { |
| 687 if (HasICData()) { | 711 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 688 EmitLoadIndexedPolymorphic(compiler, this); | 712 EmitLoadIndexedPolymorphic(compiler, this); |
| 689 } else { | 713 } else { |
| 690 compiler->EmitLoadIndexedGeneric(this); | 714 compiler->EmitLoadIndexedGeneric(this); |
| 691 } | 715 } |
| 692 ASSERT(locs()->out().reg() == EAX); | 716 ASSERT(locs()->out().reg() == EAX); |
| 693 return; | 717 return; |
| 694 } | 718 } |
| 695 | 719 |
| 696 Register receiver = locs()->in(0).reg(); | 720 Register receiver = locs()->in(0).reg(); |
| 697 Register index = locs()->in(1).reg(); | 721 Register index = locs()->in(1).reg(); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 786 kNumArgsChecked); | 810 kNumArgsChecked); |
| 787 } | 811 } |
| 788 | 812 |
| 789 | 813 |
| 790 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, | 814 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 791 StoreIndexedComp* comp) { | 815 StoreIndexedComp* comp) { |
| 792 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 816 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 793 comp->token_pos(), | 817 comp->token_pos(), |
| 794 comp->try_index(), | 818 comp->try_index(), |
| 795 kDeoptStoreIndexedPolymorphic); | 819 kDeoptStoreIndexedPolymorphic); |
| 796 if (comp->ic_data()->NumberOfChecks() == 0) { | 820 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
| 797 __ jmp(deopt); | |
| 798 return; | |
| 799 } | |
| 800 ASSERT(comp->HasICData()); | 821 ASSERT(comp->HasICData()); |
| 801 const ICData& ic_data = *comp->ic_data(); | 822 const ICData& ic_data = *comp->ic_data(); |
| 802 ASSERT(ic_data.num_args_tested() == 1); | 823 ASSERT(ic_data.num_args_tested() == 1); |
| 803 // No indexed access on Smi. | 824 // No indexed access on Smi. |
| 804 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 825 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
| 805 // Load receiver into EAX. | 826 // Load receiver into EAX. |
| 806 const intptr_t kNumArguments = 3; | 827 const intptr_t kNumArguments = 3; |
| 807 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); | 828 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
| 808 __ testl(EAX, Immediate(kSmiTagMask)); | 829 __ testl(EAX, Immediate(kSmiTagMask)); |
| 809 __ j(ZERO, deopt); | 830 __ j(ZERO, deopt); |
| 810 __ LoadClassId(EDI, EAX); | 831 __ LoadClassId(EDI, EAX); |
| 811 compiler->EmitTestAndCall(ic_data, | 832 compiler->EmitTestAndCall(ic_data, |
| 812 EDI, // Class id register. | 833 EDI, // Class id register. |
| 813 kNumArguments, | 834 kNumArguments, |
| 814 Array::Handle(), // No named arguments. | 835 Array::Handle(), // No named arguments. |
| 815 deopt, // Deoptimize target. | 836 deopt, // Deoptimize target. |
| 816 NULL, // Fallthrough when done. | 837 NULL, // Fallthrough when done. |
| 817 comp->cid(), | 838 comp->cid(), |
| 818 comp->token_pos(), | 839 comp->token_pos(), |
| 819 comp->try_index()); | 840 comp->try_index()); |
| 820 } | 841 } |
| 821 | 842 |
| 822 | 843 |
| 823 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 844 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 824 if (receiver_type() == kIllegalObjectKind) { | 845 if (receiver_type() == kIllegalObjectKind) { |
| 825 if (HasICData()) { | 846 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 826 EmitStoreIndexedPolymorphic(compiler, this); | 847 EmitStoreIndexedPolymorphic(compiler, this); |
| 827 } else { | 848 } else { |
| 828 EmitStoreIndexedGeneric(compiler, this); | 849 EmitStoreIndexedGeneric(compiler, this); |
| 829 } | 850 } |
| 830 return; | 851 return; |
| 831 } | 852 } |
| 832 | 853 |
| 833 Register receiver = locs()->in(0).reg(); | 854 Register receiver = locs()->in(0).reg(); |
| 834 Register index = locs()->in(1).reg(); | 855 Register index = locs()->in(1).reg(); |
| 835 Register value = locs()->in(2).reg(); | 856 Register value = locs()->in(2).reg(); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 882 } | 903 } |
| 883 } | 904 } |
| 884 | 905 |
| 885 | 906 |
| 886 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { | 907 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { |
| 887 return MakeCallSummary(); | 908 return MakeCallSummary(); |
| 888 } | 909 } |
| 889 | 910 |
| 890 | 911 |
| 891 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 912 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 892 const String& function_name = | 913 Label* deopt = NULL; |
| 893 String::ZoneHandle(Field::SetterSymbol(field_name())); | 914 if (compiler->is_optimizing()) { |
| 915 deopt = compiler->AddDeoptStub(cid(), |
| 916 token_pos(), |
| 917 try_index(), |
| 918 kDeoptInstanceSetter); |
| 919 } |
| 920 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 921 // No index-setter on Smi's. |
| 922 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmi); |
| 923 // Load receiver into EAX. |
| 924 const intptr_t kNumArguments = 2; |
| 925 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
| 926 __ testl(EAX, Immediate(kSmiTagMask)); |
| 927 __ j(ZERO, deopt); |
| 928 __ LoadClassId(EDI, EAX); |
| 929 compiler->EmitTestAndCall(*ic_data(), |
| 930 EDI, // Class id register. |
| 931 kNumArguments, |
| 932 Array::Handle(), // No named arguments. |
| 933 deopt, // Deoptimize target. |
| 934 NULL, // Fallthrough when done. |
| 935 cid(), |
| 936 token_pos(), |
| 937 try_index()); |
| 894 | 938 |
| 895 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 939 } else if (compiler->is_optimizing()) { |
| 896 cid(), | 940 // Get some IC data then optimize again. |
| 897 token_pos(), | 941 __ jmp(deopt); |
| 898 try_index()); | 942 } else { |
| 899 const intptr_t kArgumentCount = 2; | 943 // Unoptimized code. |
| 900 const intptr_t kCheckedArgumentCount = 1; | 944 const String& function_name = |
| 901 compiler->GenerateInstanceCall(cid(), | 945 String::ZoneHandle(Field::SetterSymbol(field_name())); |
| 902 token_pos(), | 946 |
| 903 try_index(), | 947 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 904 function_name, | 948 cid(), |
| 905 kArgumentCount, | 949 token_pos(), |
| 906 Array::ZoneHandle(), | 950 try_index()); |
| 907 kCheckedArgumentCount); | 951 const intptr_t kArgumentCount = 2; |
| 952 const intptr_t kCheckedArgumentCount = 1; |
| 953 compiler->GenerateInstanceCall(cid(), |
| 954 token_pos(), |
| 955 try_index(), |
| 956 function_name, |
| 957 kArgumentCount, |
| 958 Array::ZoneHandle(), |
| 959 kCheckedArgumentCount); |
| 960 } |
| 908 } | 961 } |
| 909 | 962 |
| 910 | 963 |
| 911 LocationSummary* StaticSetterComp::MakeLocationSummary() const { | 964 LocationSummary* StaticSetterComp::MakeLocationSummary() const { |
| 912 const intptr_t kNumInputs = 1; | 965 const intptr_t kNumInputs = 1; |
| 913 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); | 966 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); |
| 914 } | 967 } |
| 915 | 968 |
| 916 | 969 |
| 917 void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 970 void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 1055 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1973 instance_call()->argument_names()); | 2026 instance_call()->argument_names()); |
| 1974 } | 2027 } |
| 1975 __ Bind(&done); | 2028 __ Bind(&done); |
| 1976 } | 2029 } |
| 1977 | 2030 |
| 1978 } // namespace dart | 2031 } // namespace dart |
| 1979 | 2032 |
| 1980 #undef __ | 2033 #undef __ |
| 1981 | 2034 |
| 1982 #endif // defined TARGET_ARCH_X64 | 2035 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |