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" |
11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
12 #include "vm/locations.h" | 12 #include "vm/locations.h" |
13 #include "vm/object_store.h" | 13 #include "vm/object_store.h" |
14 #include "vm/stub_code.h" | 14 #include "vm/stub_code.h" |
15 | 15 |
16 #define __ compiler->assembler()-> | 16 #define __ compiler->assembler()-> |
17 | 17 |
18 namespace dart { | 18 namespace dart { |
19 | 19 |
20 DECLARE_FLAG(int, optimization_counter_threshold); | 20 DECLARE_FLAG(int, optimization_counter_threshold); |
21 DECLARE_FLAG(bool, trace_functions); | 21 DECLARE_FLAG(bool, trace_functions); |
22 | 22 |
23 // Generic summary for call instructions that have all arguments pushed | 23 // Generic summary for call instructions that have all arguments pushed |
24 // on the stack and return the result in a fixed register EAX. | 24 // on the stack and return the result in a fixed register EAX. |
25 LocationSummary* Computation::MakeCallSummary() { | 25 LocationSummary* Computation::MakeCallSummary() { |
26 LocationSummary* result = new LocationSummary(0, 0); | 26 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall); |
27 result->set_out(Location::RegisterLocation(EAX)); | 27 result->set_out(Location::RegisterLocation(EAX)); |
28 return result; | 28 return result; |
29 } | 29 } |
30 | 30 |
31 | 31 |
32 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 32 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
33 computation()->EmitNativeCode(compiler); | 33 computation()->EmitNativeCode(compiler); |
34 if (locs()->out().kind() == Location::kRegister) { | 34 if (locs()->out().kind() == Location::kRegister) { |
35 // TODO(vegorov): this should really happen only for comparisons fused | 35 // TODO(vegorov): this should really happen only for comparisons fused |
36 // with branches. Currrently IR does not provide an easy way to remove | 36 // with branches. Currrently IR does not provide an easy way to remove |
37 // instructions from the graph so we just leave fused comparison in it | 37 // instructions from the graph so we just leave fused comparison in it |
38 // but change its result location to be NoLocation. | 38 // but change its result location to be NoLocation. |
39 __ pushl(locs()->out().reg()); | 39 compiler->frame_register_allocator()->Push(locs()->out().reg(), this); |
40 } | 40 } |
41 } | 41 } |
42 | 42 |
43 | 43 |
44 LocationSummary* ReturnInstr::MakeLocationSummary() const { | 44 LocationSummary* ReturnInstr::MakeLocationSummary() const { |
45 const intptr_t kNumInputs = 1; | 45 const intptr_t kNumInputs = 1; |
46 const intptr_t kNumTemps = 1; | 46 const intptr_t kNumTemps = 1; |
47 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 47 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
48 locs->set_in(0, Location::RegisterLocation(EAX)); | 48 locs->set_in(0, Location::RegisterLocation(EAX)); |
49 locs->set_temp(0, Location::RequiresRegister()); | 49 locs->set_temp(0, Location::RequiresRegister()); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
98 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 98 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
99 cid(), | 99 cid(), |
100 token_index(), | 100 token_index(), |
101 CatchClauseNode::kInvalidTryIndex); | 101 CatchClauseNode::kInvalidTryIndex); |
102 } | 102 } |
103 | 103 |
104 | 104 |
105 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 105 LocationSummary* ClosureCallComp::MakeLocationSummary() const { |
106 const intptr_t kNumInputs = 0; | 106 const intptr_t kNumInputs = 0; |
107 const intptr_t kNumTemps = 1; | 107 const intptr_t kNumTemps = 1; |
108 LocationSummary* result = new LocationSummary(kNumInputs, kNumTemps); | 108 LocationSummary* result = new LocationSummary(kNumInputs, |
109 kNumTemps, | |
110 LocationSummary::kCall); | |
109 result->set_out(Location::RegisterLocation(EAX)); | 111 result->set_out(Location::RegisterLocation(EAX)); |
110 result->set_temp(0, Location::RegisterLocation(EDX)); // Arg. descriptor. | 112 result->set_temp(0, Location::RegisterLocation(EDX)); // Arg. descriptor. |
111 return result; | 113 return result; |
112 } | 114 } |
113 | 115 |
114 | 116 |
115 LocationSummary* LoadLocalComp::MakeLocationSummary() const { | 117 LocationSummary* LoadLocalComp::MakeLocationSummary() const { |
116 return LocationSummary::Make(0, Location::RequiresRegister()); | 118 return LocationSummary::Make(0, Location::RequiresRegister()); |
117 } | 119 } |
118 | 120 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
182 kConditionTypeErrorRuntimeEntry); | 184 kConditionTypeErrorRuntimeEntry); |
183 // We should never return here. | 185 // We should never return here. |
184 __ int3(); | 186 __ int3(); |
185 | 187 |
186 __ Bind(&done); | 188 __ Bind(&done); |
187 ASSERT(obj == result); | 189 ASSERT(obj == result); |
188 } | 190 } |
189 | 191 |
190 | 192 |
191 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { | 193 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { |
194 const LocationSummary::ContainsBranch contains_branch = | |
195 is_fused_with_branch() ? LocationSummary::kBranch | |
196 : LocationSummary::kNoBranch; | |
197 | |
192 const intptr_t kNumInputs = 2; | 198 const intptr_t kNumInputs = 2; |
193 if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) { | 199 if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) { |
194 const intptr_t kNumTemps = 1; | 200 const intptr_t kNumTemps = 1; |
195 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 201 LocationSummary* locs = new LocationSummary(kNumInputs, |
202 kNumTemps, | |
203 LocationSummary::kNoCall, | |
204 contains_branch); | |
196 locs->set_in(0, Location::RequiresRegister()); | 205 locs->set_in(0, Location::RequiresRegister()); |
197 locs->set_in(1, Location::RequiresRegister()); | 206 locs->set_in(1, Location::RequiresRegister()); |
198 locs->set_temp(0, Location::RequiresRegister()); | 207 locs->set_temp(0, Location::RequiresRegister()); |
199 if (!is_fused_with_branch()) { | 208 if (!is_fused_with_branch()) { |
200 locs->set_out(Location::RequiresRegister()); | 209 locs->set_out(Location::RequiresRegister()); |
201 } | 210 } |
202 return locs; | 211 return locs; |
203 } | 212 } |
204 if (NumTargets() > 0) { | 213 if (NumTargets() > 0) { |
205 const intptr_t kNumTemps = 1; | 214 const intptr_t kNumTemps = 1; |
206 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 215 LocationSummary* locs = new LocationSummary(kNumInputs, |
216 kNumTemps, | |
217 LocationSummary::kCall, | |
218 contains_branch); | |
207 locs->set_in(0, Location::RequiresRegister()); | 219 locs->set_in(0, Location::RequiresRegister()); |
208 locs->set_in(1, Location::RequiresRegister()); | 220 locs->set_in(1, Location::RequiresRegister()); |
209 locs->set_temp(0, Location::RequiresRegister()); | 221 locs->set_temp(0, Location::RequiresRegister()); |
210 if (!is_fused_with_branch()) { | 222 if (!is_fused_with_branch()) { |
211 locs->set_out(Location::RegisterLocation(EAX)); | 223 locs->set_out(Location::RegisterLocation(EAX)); |
212 } | 224 } |
213 return locs; | 225 return locs; |
214 } | 226 } |
215 const intptr_t kNumTemps = 0; | 227 const intptr_t kNumTemps = 0; |
216 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 228 LocationSummary* locs = new LocationSummary(kNumInputs, |
229 kNumTemps, | |
230 LocationSummary::kCall, | |
231 contains_branch); | |
217 locs->set_in(0, Location::RequiresRegister()); | 232 locs->set_in(0, Location::RequiresRegister()); |
218 locs->set_in(1, Location::RequiresRegister()); | 233 locs->set_in(1, Location::RequiresRegister()); |
219 if (!is_fused_with_branch()) { | 234 if (!is_fused_with_branch()) { |
220 locs->set_out(Location::RegisterLocation(EAX)); | 235 locs->set_out(Location::RegisterLocation(EAX)); |
221 } | 236 } |
222 return locs; | 237 return locs; |
223 } | 238 } |
224 | 239 |
225 | 240 |
226 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, | 241 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
396 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 411 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
397 if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) { | 412 if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) { |
398 EmitSmiEqualityCompare(compiler, this); | 413 EmitSmiEqualityCompare(compiler, this); |
399 return; | 414 return; |
400 } | 415 } |
401 EmitGenericEqualityCompare(compiler, this); | 416 EmitGenericEqualityCompare(compiler, this); |
402 } | 417 } |
403 | 418 |
404 | 419 |
405 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 420 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
421 const LocationSummary::ContainsBranch contains_branch = | |
422 is_fused_with_branch() ? LocationSummary::kBranch | |
423 : LocationSummary::kNoBranch; | |
424 | |
406 if ((operands_class_id() == kSmi) || (operands_class_id() == kDouble)) { | 425 if ((operands_class_id() == kSmi) || (operands_class_id() == kDouble)) { |
407 const intptr_t kNumInputs = 2; | 426 const intptr_t kNumInputs = 2; |
408 const intptr_t kNumTemps = 1; | 427 const intptr_t kNumTemps = 1; |
409 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 428 LocationSummary* summary = new LocationSummary(kNumInputs, |
429 kNumTemps, | |
430 LocationSummary::kNoCall, | |
431 contains_branch); | |
410 summary->set_in(0, Location::RequiresRegister()); | 432 summary->set_in(0, Location::RequiresRegister()); |
411 summary->set_in(1, Location::RequiresRegister()); | 433 summary->set_in(1, Location::RequiresRegister()); |
412 if (!is_fused_with_branch()) { | 434 if (!is_fused_with_branch()) { |
413 summary->set_out(Location::RequiresRegister()); | 435 summary->set_out(Location::RequiresRegister()); |
414 } | 436 } |
415 summary->set_temp(0, Location::RequiresRegister()); | 437 summary->set_temp(0, Location::RequiresRegister()); |
416 return summary; | 438 return summary; |
417 } | 439 } |
418 ASSERT(operands_class_id() == kObject); | 440 ASSERT(operands_class_id() == kObject); |
419 return MakeCallSummary(); | 441 return MakeCallSummary(); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
544 try_index(), | 566 try_index(), |
545 function_name, | 567 function_name, |
546 kNumArguments, | 568 kNumArguments, |
547 Array::ZoneHandle(), // No optional arguments. | 569 Array::ZoneHandle(), // No optional arguments. |
548 kNumArgsChecked); | 570 kNumArgsChecked); |
549 ASSERT(locs()->out().reg() == EAX); | 571 ASSERT(locs()->out().reg() == EAX); |
550 } | 572 } |
551 | 573 |
552 | 574 |
553 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 575 LocationSummary* NativeCallComp::MakeLocationSummary() const { |
554 LocationSummary* locs = new LocationSummary(0, 3); | 576 LocationSummary* locs = new LocationSummary(0, 3, LocationSummary::kCall); |
555 locs->set_temp(0, Location::RegisterLocation(EAX)); | 577 locs->set_temp(0, Location::RegisterLocation(EAX)); |
556 locs->set_temp(1, Location::RegisterLocation(ECX)); | 578 locs->set_temp(1, Location::RegisterLocation(ECX)); |
557 locs->set_temp(2, Location::RegisterLocation(EDX)); | 579 locs->set_temp(2, Location::RegisterLocation(EDX)); |
558 locs->set_out(Location::RequiresRegister()); | 580 locs->set_out(Location::RequiresRegister()); |
559 return locs; | 581 return locs; |
560 } | 582 } |
561 | 583 |
562 | 584 |
563 void NativeCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 585 void NativeCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
564 ASSERT(locs()->temp(0).reg() == EAX); | 586 ASSERT(locs()->temp(0).reg() == EAX); |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
761 } | 783 } |
762 | 784 |
763 default: | 785 default: |
764 UNREACHABLE(); | 786 UNREACHABLE(); |
765 break; | 787 break; |
766 } | 788 } |
767 } | 789 } |
768 | 790 |
769 | 791 |
770 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { | 792 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { |
771 const intptr_t kNumInputs = 2; | 793 return MakeCallSummary(); |
772 return LocationSummary::Make(kNumInputs, Location::NoLocation()); | |
773 } | 794 } |
774 | 795 |
775 | 796 |
776 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 797 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
777 Register receiver = locs()->in(0).reg(); | |
778 Register value = locs()->in(1).reg(); | |
779 | |
780 // Preserve the value (second argument) under the arguments as the result | |
781 // of the computation, then call the setter. | |
782 const String& function_name = | 798 const String& function_name = |
783 String::ZoneHandle(Field::SetterSymbol(field_name())); | 799 String::ZoneHandle(Field::SetterSymbol(field_name())); |
784 | 800 |
785 __ pushl(receiver); | |
786 __ pushl(value); | |
787 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 801 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
788 cid(), | 802 cid(), |
789 token_index(), | 803 token_index(), |
790 try_index()); | 804 try_index()); |
791 const intptr_t kArgumentCount = 2; | 805 const intptr_t kArgumentCount = 2; |
792 const intptr_t kCheckedArgumentCount = 1; | 806 const intptr_t kCheckedArgumentCount = 1; |
793 compiler->GenerateInstanceCall(cid(), | 807 compiler->GenerateInstanceCall(cid(), |
794 token_index(), | 808 token_index(), |
795 try_index(), | 809 try_index(), |
796 function_name, | 810 function_name, |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
892 } | 906 } |
893 | 907 |
894 | 908 |
895 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 909 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
896 // TODO(regis): The elements of the array could be considered as arguments to | 910 // TODO(regis): The elements of the array could be considered as arguments to |
897 // CreateArrayComp, thereby making CreateArrayComp a call. | 911 // CreateArrayComp, thereby making CreateArrayComp a call. |
898 // For VerifyCallComputation to work, CreateArrayComp would need an | 912 // For VerifyCallComputation to work, CreateArrayComp would need an |
899 // ArgumentCount getter and an ArgumentAt getter. | 913 // ArgumentCount getter and an ArgumentAt getter. |
900 const intptr_t kNumInputs = 1; | 914 const intptr_t kNumInputs = 1; |
901 const intptr_t kNumTemps = 1; | 915 const intptr_t kNumTemps = 1; |
902 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 916 LocationSummary* locs = new LocationSummary(kNumInputs, |
917 kNumTemps, | |
918 LocationSummary::kCall); | |
903 locs->set_in(0, Location::RegisterLocation(ECX)); | 919 locs->set_in(0, Location::RegisterLocation(ECX)); |
904 locs->set_temp(0, Location::RegisterLocation(EDX)); | 920 locs->set_temp(0, Location::RegisterLocation(EDX)); |
905 locs->set_out(Location::RegisterLocation(EAX)); | 921 locs->set_out(Location::RegisterLocation(EAX)); |
906 return locs; | 922 return locs; |
907 } | 923 } |
908 | 924 |
909 | 925 |
910 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 926 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
911 Register temp_reg = locs()->temp(0).reg(); | 927 Register temp_reg = locs()->temp(0).reg(); |
912 Register result_reg = locs()->out().reg(); | 928 Register result_reg = locs()->out().reg(); |
(...skipping 10 matching lines...) Expand all Loading... | |
923 __ leal(temp_reg, FieldAddress(result_reg, Array::data_offset())); | 939 __ leal(temp_reg, FieldAddress(result_reg, Array::data_offset())); |
924 for (int i = ElementCount() - 1; i >= 0; --i) { | 940 for (int i = ElementCount() - 1; i >= 0; --i) { |
925 ASSERT(ElementAt(i)->IsUse()); | 941 ASSERT(ElementAt(i)->IsUse()); |
926 __ popl(Address(temp_reg, i * kWordSize)); | 942 __ popl(Address(temp_reg, i * kWordSize)); |
927 } | 943 } |
928 } | 944 } |
929 | 945 |
930 | 946 |
931 LocationSummary* | 947 LocationSummary* |
932 AllocateObjectWithBoundsCheckComp::MakeLocationSummary() const { | 948 AllocateObjectWithBoundsCheckComp::MakeLocationSummary() const { |
933 return LocationSummary::Make(2, Location::RequiresRegister()); | 949 return LocationSummary::Make(2, |
950 Location::RequiresRegister(), | |
951 LocationSummary::kCall); | |
934 } | 952 } |
935 | 953 |
936 | 954 |
937 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( | 955 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( |
938 FlowGraphCompiler* compiler) { | 956 FlowGraphCompiler* compiler) { |
939 const Class& cls = Class::ZoneHandle(constructor().owner()); | 957 const Class& cls = Class::ZoneHandle(constructor().owner()); |
940 Register type_arguments = locs()->in(0).reg(); | 958 Register type_arguments = locs()->in(0).reg(); |
941 Register instantiator_type_arguments = locs()->in(1).reg(); | 959 Register instantiator_type_arguments = locs()->in(1).reg(); |
942 Register result = locs()->out().reg(); | 960 Register result = locs()->out().reg(); |
943 | 961 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
978 compiler->EmitClassChecksNoSmi(*class_ids(), instance, result, deopt); | 996 compiler->EmitClassChecksNoSmi(*class_ids(), instance, result, deopt); |
979 } | 997 } |
980 | 998 |
981 __ movl(result, FieldAddress(instance, offset_in_bytes())); | 999 __ movl(result, FieldAddress(instance, offset_in_bytes())); |
982 } | 1000 } |
983 | 1001 |
984 | 1002 |
985 LocationSummary* InstantiateTypeArgumentsComp::MakeLocationSummary() const { | 1003 LocationSummary* InstantiateTypeArgumentsComp::MakeLocationSummary() const { |
986 const intptr_t kNumInputs = 1; | 1004 const intptr_t kNumInputs = 1; |
987 const intptr_t kNumTemps = 1; | 1005 const intptr_t kNumTemps = 1; |
988 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 1006 LocationSummary* locs = new LocationSummary(kNumInputs, |
1007 kNumTemps, | |
1008 LocationSummary::kCall); | |
989 locs->set_in(0, Location::RequiresRegister()); | 1009 locs->set_in(0, Location::RequiresRegister()); |
990 locs->set_temp(0, Location::RequiresRegister()); | 1010 locs->set_temp(0, Location::RequiresRegister()); |
991 locs->set_out(Location::SameAsFirstInput()); | 1011 locs->set_out(Location::SameAsFirstInput()); |
992 return locs; | 1012 return locs; |
993 } | 1013 } |
994 | 1014 |
995 | 1015 |
996 void InstantiateTypeArgumentsComp::EmitNativeCode( | 1016 void InstantiateTypeArgumentsComp::EmitNativeCode( |
997 FlowGraphCompiler* compiler) { | 1017 FlowGraphCompiler* compiler) { |
998 Register instantiator_reg = locs()->in(0).reg(); | 1018 Register instantiator_reg = locs()->in(0).reg(); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1161 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 1181 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
1162 } | 1182 } |
1163 __ Bind(&done); | 1183 __ Bind(&done); |
1164 // instantiator_reg: instantiator or kNoInstantiator. | 1184 // instantiator_reg: instantiator or kNoInstantiator. |
1165 } | 1185 } |
1166 | 1186 |
1167 | 1187 |
1168 LocationSummary* AllocateContextComp::MakeLocationSummary() const { | 1188 LocationSummary* AllocateContextComp::MakeLocationSummary() const { |
1169 const intptr_t kNumInputs = 0; | 1189 const intptr_t kNumInputs = 0; |
1170 const intptr_t kNumTemps = 1; | 1190 const intptr_t kNumTemps = 1; |
1171 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 1191 LocationSummary* locs = new LocationSummary(kNumInputs, |
1192 kNumTemps, | |
1193 LocationSummary::kCall); | |
1172 locs->set_temp(0, Location::RegisterLocation(EDX)); | 1194 locs->set_temp(0, Location::RegisterLocation(EDX)); |
1173 locs->set_out(Location::RegisterLocation(EAX)); | 1195 locs->set_out(Location::RegisterLocation(EAX)); |
1174 return locs; | 1196 return locs; |
1175 } | 1197 } |
1176 | 1198 |
1177 | 1199 |
1178 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1200 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1179 ASSERT(locs()->temp(0).reg() == EDX); | 1201 ASSERT(locs()->temp(0).reg() == EDX); |
1180 ASSERT(locs()->out().reg() == EAX); | 1202 ASSERT(locs()->out().reg() == EAX); |
1181 | 1203 |
1182 __ movl(EDX, Immediate(num_context_variables())); | 1204 __ movl(EDX, Immediate(num_context_variables())); |
1183 const ExternalLabel label("alloc_context", | 1205 const ExternalLabel label("alloc_context", |
1184 StubCode::AllocateContextEntryPoint()); | 1206 StubCode::AllocateContextEntryPoint()); |
1185 compiler->GenerateCall(token_index(), | 1207 compiler->GenerateCall(token_index(), |
1186 try_index(), | 1208 try_index(), |
1187 &label, | 1209 &label, |
1188 PcDescriptors::kOther); | 1210 PcDescriptors::kOther); |
1189 } | 1211 } |
1190 | 1212 |
1191 | 1213 |
1192 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 1214 LocationSummary* CloneContextComp::MakeLocationSummary() const { |
1193 return LocationSummary::Make(1, Location::RequiresRegister()); | 1215 return LocationSummary::Make(1, |
1216 Location::RequiresRegister(), | |
1217 LocationSummary::kCall); | |
1194 } | 1218 } |
1195 | 1219 |
1196 | 1220 |
1197 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1221 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1198 Register context_value = locs()->in(0).reg(); | 1222 Register context_value = locs()->in(0).reg(); |
1199 Register result = locs()->out().reg(); | 1223 Register result = locs()->out().reg(); |
1200 | 1224 |
1201 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1225 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1202 __ pushl(context_value); | 1226 __ pushl(context_value); |
1203 compiler->GenerateCallRuntime(cid(), | 1227 compiler->GenerateCallRuntime(cid(), |
(...skipping 24 matching lines...) Expand all Loading... | |
1228 ASSERT(!exception_var().is_captured()); | 1252 ASSERT(!exception_var().is_captured()); |
1229 ASSERT(!stacktrace_var().is_captured()); | 1253 ASSERT(!stacktrace_var().is_captured()); |
1230 __ movl(Address(EBP, exception_var().index() * kWordSize), | 1254 __ movl(Address(EBP, exception_var().index() * kWordSize), |
1231 kExceptionObjectReg); | 1255 kExceptionObjectReg); |
1232 __ movl(Address(EBP, stacktrace_var().index() * kWordSize), | 1256 __ movl(Address(EBP, stacktrace_var().index() * kWordSize), |
1233 kStackTraceObjectReg); | 1257 kStackTraceObjectReg); |
1234 } | 1258 } |
1235 | 1259 |
1236 | 1260 |
1237 LocationSummary* CheckStackOverflowComp::MakeLocationSummary() const { | 1261 LocationSummary* CheckStackOverflowComp::MakeLocationSummary() const { |
1238 return LocationSummary::Make(0, Location::NoLocation()); | 1262 return LocationSummary::Make(0, |
1263 Location::NoLocation(), | |
1264 LocationSummary::kCall); | |
1239 } | 1265 } |
1240 | 1266 |
1241 | 1267 |
1242 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1268 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1243 __ cmpl(ESP, | 1269 __ cmpl(ESP, |
1244 Address::Absolute(Isolate::Current()->stack_limit_address())); | 1270 Address::Absolute(Isolate::Current()->stack_limit_address())); |
1245 Label no_stack_overflow; | 1271 Label no_stack_overflow; |
1246 __ j(ABOVE, &no_stack_overflow); | 1272 __ j(ABOVE, &no_stack_overflow); |
1247 compiler->GenerateCallRuntime(cid(), | 1273 compiler->GenerateCallRuntime(cid(), |
1248 token_index(), | 1274 token_index(), |
1249 try_index(), | 1275 try_index(), |
1250 kStackOverflowRuntimeEntry); | 1276 kStackOverflowRuntimeEntry); |
1251 __ Bind(&no_stack_overflow); | 1277 __ Bind(&no_stack_overflow); |
1252 } | 1278 } |
1253 | 1279 |
1254 | 1280 |
1255 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1281 LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
1256 const intptr_t kNumInputs = 2; | 1282 const intptr_t kNumInputs = 2; |
1257 if (operands_type() == kDoubleOperands) { | 1283 if (operands_type() == kDoubleOperands) { |
1258 const intptr_t kNumTemps = 1; | 1284 return MakeCallSummary(); // Calls into a stub for allocation. |
1259 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | |
1260 summary->set_in(0, Location::RequiresRegister()); | |
1261 summary->set_in(1, Location::RequiresRegister()); | |
1262 summary->set_out(Location::RegisterLocation(EAX)); | |
1263 summary->set_temp(0, Location::RequiresRegister()); | |
1264 return summary; | |
1265 } | 1285 } |
1266 ASSERT(operands_type() == kSmiOperands); | 1286 ASSERT(operands_type() == kSmiOperands); |
1267 if (op_kind() == Token::kTRUNCDIV) { | 1287 if (op_kind() == Token::kTRUNCDIV) { |
1268 const intptr_t kNumTemps = 3; | 1288 const intptr_t kNumTemps = 3; |
1269 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 1289 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); |
1270 summary->set_in(0, Location::RegisterLocation(EAX)); | 1290 summary->set_in(0, Location::RegisterLocation(EAX)); |
1271 summary->set_in(1, Location::RegisterLocation(ECX)); | 1291 summary->set_in(1, Location::RegisterLocation(ECX)); |
1272 summary->set_out(Location::SameAsFirstInput()); | 1292 summary->set_out(Location::SameAsFirstInput()); |
1273 summary->set_temp(0, Location::RegisterLocation(EBX)); | 1293 summary->set_temp(0, Location::RegisterLocation(EBX)); |
1274 // Will be used for for sign extension. | 1294 // Will be used for for sign extension. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1309 Register right = comp->locs()->in(1).reg(); | 1329 Register right = comp->locs()->in(1).reg(); |
1310 Register result = comp->locs()->out().reg(); | 1330 Register result = comp->locs()->out().reg(); |
1311 Register temp = comp->locs()->temp(0).reg(); | 1331 Register temp = comp->locs()->temp(0).reg(); |
1312 ASSERT(left == result); | 1332 ASSERT(left == result); |
1313 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1333 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
1314 comp->instance_call()->token_index(), | 1334 comp->instance_call()->token_index(), |
1315 comp->instance_call()->try_index(), | 1335 comp->instance_call()->try_index(), |
1316 kDeoptSmiBinaryOp, | 1336 kDeoptSmiBinaryOp, |
1317 temp, | 1337 temp, |
1318 right); | 1338 right); |
1339 // TODO(vegorov): for many binary operations this pattern can be rearrange | |
srdjan
2012/06/18 16:33:20
rearranged
Vyacheslav Egorov (Google)
2012/06/18 17:51:16
Done.
| |
1340 // to save one move. | |
1319 __ movl(temp, left); | 1341 __ movl(temp, left); |
1320 __ orl(left, right); | 1342 __ orl(left, right); |
1321 __ testl(left, Immediate(kSmiTagMask)); | 1343 __ testl(left, Immediate(kSmiTagMask)); |
1322 __ j(NOT_ZERO, deopt); | 1344 __ j(NOT_ZERO, deopt); |
1323 __ movl(left, temp); | 1345 __ movl(left, temp); |
1324 switch (comp->op_kind()) { | 1346 switch (comp->op_kind()) { |
1325 case Token::kADD: { | 1347 case Token::kADD: { |
1326 __ addl(left, right); | 1348 __ addl(left, right); |
1327 __ j(OVERFLOW, deopt); | 1349 __ j(OVERFLOW, deopt); |
1328 break; | 1350 break; |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1431 } | 1453 } |
1432 default: | 1454 default: |
1433 UNREACHABLE(); | 1455 UNREACHABLE(); |
1434 break; | 1456 break; |
1435 } | 1457 } |
1436 } | 1458 } |
1437 | 1459 |
1438 | 1460 |
1439 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, | 1461 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, |
1440 BinaryOpComp* comp) { | 1462 BinaryOpComp* comp) { |
1441 Register left = comp->locs()->in(0).reg(); | 1463 Register left = EBX; |
1442 Register right = comp->locs()->in(1).reg(); | 1464 Register right = ECX; |
1443 Register temp = comp->locs()->temp(0).reg(); | 1465 Register temp = EDX; |
1444 Register result = comp->locs()->out().reg(); | 1466 Register result = comp->locs()->out().reg(); |
1445 | 1467 |
1446 const Class& double_class = compiler->double_class(); | 1468 const Class& double_class = compiler->double_class(); |
1447 const Code& stub = | 1469 const Code& stub = |
1448 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1470 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1449 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1471 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1450 __ pushl(left); | |
1451 __ pushl(right); | |
1452 compiler->GenerateCall(comp->instance_call()->token_index(), | 1472 compiler->GenerateCall(comp->instance_call()->token_index(), |
1453 comp->instance_call()->try_index(), | 1473 comp->instance_call()->try_index(), |
1454 &label, | 1474 &label, |
1455 PcDescriptors::kOther); | 1475 PcDescriptors::kOther); |
1456 // Newly allocated object is now in the result register (RAX). | 1476 // Newly allocated object is now in the result register (RAX). |
1457 ASSERT(result == EAX); | 1477 ASSERT(result == EAX); |
1458 __ popl(right); | 1478 __ popl(right); |
1459 __ popl(left); | 1479 __ popl(left); |
1460 | 1480 |
1461 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1481 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1541 } | 1561 } |
1542 } else { | 1562 } else { |
1543 UNREACHABLE(); | 1563 UNREACHABLE(); |
1544 } | 1564 } |
1545 } | 1565 } |
1546 | 1566 |
1547 | 1567 |
1548 LocationSummary* NumberNegateComp::MakeLocationSummary() const { | 1568 LocationSummary* NumberNegateComp::MakeLocationSummary() const { |
1549 const intptr_t kNumInputs = 1; | 1569 const intptr_t kNumInputs = 1; |
1550 const intptr_t kNumTemps = 1; // Needed for doubles. | 1570 const intptr_t kNumTemps = 1; // Needed for doubles. |
1551 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 1571 LocationSummary* summary = new LocationSummary(kNumInputs, |
1572 kNumTemps, | |
1573 LocationSummary::kCall); | |
1552 summary->set_in(0, Location::RequiresRegister()); | 1574 summary->set_in(0, Location::RequiresRegister()); |
1553 summary->set_out(Location::SameAsFirstInput()); | 1575 summary->set_out(Location::SameAsFirstInput()); |
1554 summary->set_temp(0, Location::RequiresRegister()); | 1576 summary->set_temp(0, Location::RequiresRegister()); |
1555 return summary; | 1577 return summary; |
1556 } | 1578 } |
1557 | 1579 |
1558 | 1580 |
1559 void NumberNegateComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1581 void NumberNegateComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1560 const ICData& ic_data = *instance_call()->ic_data(); | 1582 const ICData& ic_data = *instance_call()->ic_data(); |
1561 ASSERT(!ic_data.IsNull()); | 1583 ASSERT(!ic_data.IsNull()); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1605 | 1627 |
1606 | 1628 |
1607 LocationSummary* ToDoubleComp::MakeLocationSummary() const { | 1629 LocationSummary* ToDoubleComp::MakeLocationSummary() const { |
1608 const intptr_t kNumInputs = 1; | 1630 const intptr_t kNumInputs = 1; |
1609 if (from() == kDouble) { | 1631 if (from() == kDouble) { |
1610 const intptr_t kNumTemps = 1; | 1632 const intptr_t kNumTemps = 1; |
1611 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 1633 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
1612 locs->set_in(0, Location::RequiresRegister()); | 1634 locs->set_in(0, Location::RequiresRegister()); |
1613 locs->set_temp(0, Location::RequiresRegister()); | 1635 locs->set_temp(0, Location::RequiresRegister()); |
1614 locs->set_out(Location::SameAsFirstInput()); | 1636 locs->set_out(Location::SameAsFirstInput()); |
1637 locs->set_temp(0, Location::RequiresRegister()); | |
1615 return locs; | 1638 return locs; |
1616 } else { | 1639 } else { |
1617 ASSERT(from() == kSmi); | 1640 ASSERT(from() == kSmi); |
1618 return LocationSummary::Make(kNumInputs, Location::RegisterLocation(EAX)); | 1641 return MakeCallSummary(); // Calls a stub to allocate result. |
1619 } | 1642 } |
1620 } | 1643 } |
1621 | 1644 |
1622 | 1645 |
1623 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1646 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1624 Register value = locs()->in(0).reg(); | |
1625 Register result = locs()->out().reg(); | 1647 Register result = locs()->out().reg(); |
1648 Register value = (from() == kDouble) ? locs()->in(0).reg() : EBX; | |
1626 | 1649 |
1627 const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1650 const DeoptReasonId deopt_reason = (from() == kDouble) ? |
1628 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1651 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
1629 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1652 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
1630 instance_call()->token_index(), | 1653 instance_call()->token_index(), |
1631 instance_call()->try_index(), | 1654 instance_call()->try_index(), |
1632 deopt_reason, | 1655 deopt_reason, |
1633 value); | 1656 value); |
1634 | 1657 |
1635 if (from() == kDouble) { | 1658 if (from() == kDouble) { |
1636 Register temp = locs()->temp(0).reg(); | 1659 Register temp = locs()->temp(0).reg(); |
1637 __ testl(value, Immediate(kSmiTagMask)); | 1660 __ testl(value, Immediate(kSmiTagMask)); |
1638 __ j(ZERO, deopt); // Deoptimize if Smi. | 1661 __ j(ZERO, deopt); // Deoptimize if Smi. |
1639 __ CompareClassId(value, kDouble, temp); | 1662 __ CompareClassId(value, kDouble, temp); |
1640 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 1663 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
1641 ASSERT(value == result); | 1664 ASSERT(value == result); |
1642 return; | 1665 return; |
1643 } | 1666 } |
1644 | 1667 |
1645 ASSERT(from() == kSmi); | 1668 ASSERT(from() == kSmi); |
1646 | 1669 |
1647 const Class& double_class = compiler->double_class(); | 1670 const Class& double_class = compiler->double_class(); |
1648 const Code& stub = | 1671 const Code& stub = |
1649 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1672 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1650 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1673 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1651 | 1674 |
1652 // TODO(vegorov): allocate box in the driver loop to avoid pushing and poping. | 1675 // TODO(vegorov): allocate box in the driver loop to avoid pushing and poping. |
Florian Schneider
2012/06/18 16:50:55
s/poping/popping/
Vyacheslav Egorov (Google)
2012/06/18 17:51:16
Done.
| |
1653 __ pushl(value); | |
1654 compiler->GenerateCall(instance_call()->token_index(), | 1676 compiler->GenerateCall(instance_call()->token_index(), |
1655 instance_call()->try_index(), | 1677 instance_call()->try_index(), |
1656 &label, | 1678 &label, |
1657 PcDescriptors::kOther); | 1679 PcDescriptors::kOther); |
1658 ASSERT(result == EAX); | 1680 ASSERT(result == EAX); |
1659 __ popl(value); | 1681 __ popl(value); |
1660 | 1682 |
1661 __ testl(value, Immediate(kSmiTagMask)); | 1683 __ testl(value, Immediate(kSmiTagMask)); |
1662 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. | 1684 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. |
1663 __ SmiUntag(value); | 1685 __ SmiUntag(value); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1713 } | 1735 } |
1714 __ Bind(&done); | 1736 __ Bind(&done); |
1715 } | 1737 } |
1716 | 1738 |
1717 | 1739 |
1718 } // namespace dart | 1740 } // namespace dart |
1719 | 1741 |
1720 #undef __ | 1742 #undef __ |
1721 | 1743 |
1722 #endif // defined TARGET_ARCH_X64 | 1744 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |