Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(323)

Side by Side Diff: runtime/vm/intermediate_language_ia32.cc

Issue 10704210: Fix problem of excessive attempts to optimize, fix excessive deoptimizations for load/store indexed… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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, &not_yet_hot, Assembler::kNearJump); 72 __ j(LESS, &not_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(&not_yet_hot); 79 __ Bind(&not_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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698