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 10 matching lines...) Expand all Loading... | |
21 DECLARE_FLAG(int, optimization_counter_threshold); | 21 DECLARE_FLAG(int, optimization_counter_threshold); |
22 DECLARE_FLAG(bool, trace_functions); | 22 DECLARE_FLAG(bool, trace_functions); |
23 | 23 |
24 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 24 void BindInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
25 computation()->EmitNativeCode(compiler); | 25 computation()->EmitNativeCode(compiler); |
26 if (locs()->out().kind() == Location::kRegister) { | 26 if (locs()->out().kind() == Location::kRegister) { |
27 // TODO(vegorov): this should really happen only for comparisons fused | 27 // TODO(vegorov): this should really happen only for comparisons fused |
28 // with branches. Currrently IR does not provide an easy way to remove | 28 // with branches. Currrently IR does not provide an easy way to remove |
29 // instructions from the graph so we just leave fused comparison in it | 29 // instructions from the graph so we just leave fused comparison in it |
30 // but change its result location to be NoLocation. | 30 // but change its result location to be NoLocation. |
31 __ pushq(locs()->out().reg()); | 31 compiler->frame_register_allocator()->Push(locs()->out().reg(), this); |
32 } | 32 } |
33 } | 33 } |
34 | 34 |
35 | 35 |
36 LocationSummary* ReturnInstr::MakeLocationSummary() const { | 36 LocationSummary* ReturnInstr::MakeLocationSummary() const { |
37 const intptr_t kNumInputs = 1; | 37 const intptr_t kNumInputs = 1; |
38 const intptr_t kNumTemps = 1; | 38 const intptr_t kNumTemps = 1; |
39 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 39 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
40 locs->set_in(0, Location::RegisterLocation(RAX)); | 40 locs->set_in(0, Location::RegisterLocation(RAX)); |
41 locs->set_temp(0, Location::RequiresRegister()); | 41 locs->set_temp(0, Location::RequiresRegister()); |
(...skipping 56 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 // Generic summary for call instructions that have all arguments pushed | 105 // Generic summary for call instructions that have all arguments pushed |
106 // on the stack and return the result in a fixed register RAX. | 106 // on the stack and return the result in a fixed register RAX. |
107 LocationSummary* Computation::MakeCallSummary() { | 107 LocationSummary* Computation::MakeCallSummary() { |
108 LocationSummary* result = new LocationSummary(0, 0); | 108 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall); |
109 result->set_out(Location::RegisterLocation(RAX)); | 109 result->set_out(Location::RegisterLocation(RAX)); |
110 return result; | 110 return result; |
111 } | 111 } |
112 | 112 |
113 | 113 |
114 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 114 LocationSummary* ClosureCallComp::MakeLocationSummary() const { |
115 const intptr_t kNumInputs = 0; | 115 const intptr_t kNumInputs = 0; |
116 const intptr_t kNumTemps = 1; | 116 const intptr_t kNumTemps = 1; |
117 LocationSummary* result = new LocationSummary(kNumInputs, kNumTemps); | 117 LocationSummary* result = new LocationSummary(kNumInputs, |
118 kNumTemps, | |
119 LocationSummary::kCall); | |
118 result->set_out(Location::RegisterLocation(RAX)); | 120 result->set_out(Location::RegisterLocation(RAX)); |
119 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. | 121 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. |
120 return result; | 122 return result; |
121 } | 123 } |
122 | 124 |
123 | 125 |
124 LocationSummary* LoadLocalComp::MakeLocationSummary() const { | 126 LocationSummary* LoadLocalComp::MakeLocationSummary() const { |
125 return LocationSummary::Make(0, Location::RequiresRegister()); | 127 return LocationSummary::Make(0, Location::RequiresRegister()); |
126 } | 128 } |
127 | 129 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
191 kConditionTypeErrorRuntimeEntry); | 193 kConditionTypeErrorRuntimeEntry); |
192 // We should never return here. | 194 // We should never return here. |
193 __ int3(); | 195 __ int3(); |
194 | 196 |
195 __ Bind(&done); | 197 __ Bind(&done); |
196 ASSERT(obj == result); | 198 ASSERT(obj == result); |
197 } | 199 } |
198 | 200 |
199 | 201 |
200 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { | 202 LocationSummary* EqualityCompareComp::MakeLocationSummary() const { |
203 const LocationSummary::ContainsBranch contains_branch = | |
204 is_fused_with_branch() ? LocationSummary::kBranch | |
205 : LocationSummary::kNoBranch; | |
206 | |
201 const intptr_t kNumInputs = 2; | 207 const intptr_t kNumInputs = 2; |
202 if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) { | 208 if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) { |
203 const intptr_t kNumTemps = 1; | 209 const intptr_t kNumTemps = 1; |
204 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 210 LocationSummary* locs = new LocationSummary(kNumInputs, |
211 kNumTemps, | |
212 LocationSummary::kNoCall, | |
213 contains_branch); | |
205 locs->set_in(0, Location::RequiresRegister()); | 214 locs->set_in(0, Location::RequiresRegister()); |
206 locs->set_in(1, Location::RequiresRegister()); | 215 locs->set_in(1, Location::RequiresRegister()); |
207 locs->set_temp(0, Location::RequiresRegister()); | 216 locs->set_temp(0, Location::RequiresRegister()); |
208 if (!is_fused_with_branch()) { | 217 if (!is_fused_with_branch()) { |
209 locs->set_out(Location::RequiresRegister()); | 218 locs->set_out(Location::RequiresRegister()); |
210 } | 219 } |
211 return locs; | 220 return locs; |
212 } | 221 } |
213 if (NumTargets() > 0) { | 222 if (NumTargets() > 0) { |
214 const intptr_t kNumTemps = 1; | 223 const intptr_t kNumTemps = 1; |
215 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 224 LocationSummary* locs = new LocationSummary(kNumInputs, |
225 kNumTemps, | |
226 LocationSummary::kCall, | |
227 contains_branch); | |
216 locs->set_in(0, Location::RequiresRegister()); | 228 locs->set_in(0, Location::RequiresRegister()); |
217 locs->set_in(1, Location::RequiresRegister()); | 229 locs->set_in(1, Location::RequiresRegister()); |
218 locs->set_temp(0, Location::RequiresRegister()); | 230 locs->set_temp(0, Location::RequiresRegister()); |
219 if (!is_fused_with_branch()) { | 231 if (!is_fused_with_branch()) { |
220 locs->set_out(Location::RegisterLocation(RAX)); | 232 locs->set_out(Location::RegisterLocation(RAX)); |
221 } | 233 } |
222 return locs; | 234 return locs; |
223 } | 235 } |
224 const intptr_t kNumTemps = 0; | 236 const intptr_t kNumTemps = 0; |
225 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 237 LocationSummary* locs = new LocationSummary(kNumInputs, |
238 kNumTemps, | |
239 LocationSummary::kCall, | |
240 contains_branch); | |
226 locs->set_in(0, Location::RequiresRegister()); | 241 locs->set_in(0, Location::RequiresRegister()); |
227 locs->set_in(1, Location::RequiresRegister()); | 242 locs->set_in(1, Location::RequiresRegister()); |
228 if (!is_fused_with_branch()) { | 243 if (!is_fused_with_branch()) { |
229 locs->set_out(Location::RegisterLocation(RAX)); | 244 locs->set_out(Location::RegisterLocation(RAX)); |
230 } | 245 } |
231 return locs; | 246 return locs; |
232 } | 247 } |
233 | 248 |
234 | 249 |
235 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, | 250 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
406 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 421 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
407 if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) { | 422 if ((NumTargets() == 1) && (ClassIdAt(0) == kSmi)) { |
408 EmitSmiEqualityCompare(compiler, this); | 423 EmitSmiEqualityCompare(compiler, this); |
409 return; | 424 return; |
410 } | 425 } |
411 EmitGenericEqualityCompare(compiler, this); | 426 EmitGenericEqualityCompare(compiler, this); |
412 } | 427 } |
413 | 428 |
414 | 429 |
415 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 430 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
431 const LocationSummary::ContainsBranch contains_branch = | |
432 is_fused_with_branch() ? LocationSummary::kBranch | |
433 : LocationSummary::kNoBranch; | |
434 | |
416 if (operands_class_id() == kSmi || operands_class_id() == kDouble) { | 435 if (operands_class_id() == kSmi || operands_class_id() == kDouble) { |
417 const intptr_t kNumInputs = 2; | 436 const intptr_t kNumInputs = 2; |
418 const intptr_t kNumTemps = 1; | 437 const intptr_t kNumTemps = 1; |
419 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 438 LocationSummary* summary = new LocationSummary(kNumInputs, |
439 kNumTemps, | |
440 LocationSummary::kCall, | |
441 contains_branch); | |
420 summary->set_in(0, Location::RequiresRegister()); | 442 summary->set_in(0, Location::RequiresRegister()); |
421 summary->set_in(1, Location::RequiresRegister()); | 443 summary->set_in(1, Location::RequiresRegister()); |
422 if (!is_fused_with_branch()) { | 444 if (!is_fused_with_branch()) { |
423 summary->set_out(Location::RequiresRegister()); | 445 summary->set_out(Location::RequiresRegister()); |
424 } | 446 } |
425 summary->set_temp(0, Location::RequiresRegister()); | 447 summary->set_temp(0, Location::RequiresRegister()); |
426 return summary; | 448 return summary; |
427 } | 449 } |
428 ASSERT(!is_fused_with_branch()); | 450 ASSERT(!is_fused_with_branch()); |
429 ASSERT(operands_class_id() == kObject); | 451 ASSERT(operands_class_id() == kObject); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
553 try_index(), | 575 try_index(), |
554 function_name, | 576 function_name, |
555 kNumArguments, | 577 kNumArguments, |
556 Array::ZoneHandle(), // No optional arguments. | 578 Array::ZoneHandle(), // No optional arguments. |
557 kNumArgsChecked); | 579 kNumArgsChecked); |
558 ASSERT(locs()->out().reg() == RAX); | 580 ASSERT(locs()->out().reg() == RAX); |
559 } | 581 } |
560 | 582 |
561 | 583 |
562 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 584 LocationSummary* NativeCallComp::MakeLocationSummary() const { |
563 LocationSummary* locs = new LocationSummary(0, 3); | 585 const intptr_t kNumInputs = 0; |
586 const intptr_t kNumTemps = 3; | |
587 LocationSummary* locs = new LocationSummary(kNumInputs, | |
588 kNumTemps, | |
589 LocationSummary::kCall); | |
564 locs->set_temp(0, Location::RegisterLocation(RAX)); | 590 locs->set_temp(0, Location::RegisterLocation(RAX)); |
565 locs->set_temp(1, Location::RegisterLocation(RBX)); | 591 locs->set_temp(1, Location::RegisterLocation(RBX)); |
566 locs->set_temp(2, Location::RegisterLocation(R10)); | 592 locs->set_temp(2, Location::RegisterLocation(R10)); |
567 locs->set_out(Location::RequiresRegister()); | 593 locs->set_out(Location::RequiresRegister()); |
568 return locs; | 594 return locs; |
569 } | 595 } |
570 | 596 |
571 | 597 |
572 void NativeCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 598 void NativeCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
573 ASSERT(locs()->temp(0).reg() == RAX); | 599 ASSERT(locs()->temp(0).reg() == RAX); |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
772 } | 798 } |
773 | 799 |
774 default: | 800 default: |
775 UNREACHABLE(); | 801 UNREACHABLE(); |
776 break; | 802 break; |
777 } | 803 } |
778 } | 804 } |
779 | 805 |
780 | 806 |
781 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { | 807 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { |
782 const intptr_t kNumInputs = 2; | 808 return MakeCallSummary(); |
783 return LocationSummary::Make(kNumInputs, Location::NoLocation()); | |
784 return NULL; | |
785 } | 809 } |
786 | 810 |
787 | 811 |
788 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 812 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
789 Register receiver = locs()->in(0).reg(); | |
790 Register value = locs()->in(1).reg(); | |
791 | |
792 // Preserve the value (second argument) under the arguments as the result | |
793 // of the computation, then call the setter. | |
794 const String& function_name = | 813 const String& function_name = |
795 String::ZoneHandle(Field::SetterSymbol(field_name())); | 814 String::ZoneHandle(Field::SetterSymbol(field_name())); |
796 | 815 |
797 __ pushq(receiver); | |
798 __ pushq(value); | |
799 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 816 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
800 cid(), | 817 cid(), |
801 token_index(), | 818 token_index(), |
802 try_index()); | 819 try_index()); |
803 const intptr_t kArgumentCount = 2; | 820 const intptr_t kArgumentCount = 2; |
804 const intptr_t kCheckedArgumentCount = 1; | 821 const intptr_t kCheckedArgumentCount = 1; |
805 compiler->GenerateInstanceCall(cid(), | 822 compiler->GenerateInstanceCall(cid(), |
806 token_index(), | 823 token_index(), |
807 try_index(), | 824 try_index(), |
808 function_name, | 825 function_name, |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
904 } | 921 } |
905 | 922 |
906 | 923 |
907 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 924 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
908 // TODO(regis): The elements of the array could be considered as arguments to | 925 // TODO(regis): The elements of the array could be considered as arguments to |
909 // CreateArrayComp, thereby making CreateArrayComp a call. | 926 // CreateArrayComp, thereby making CreateArrayComp a call. |
910 // For VerifyCallComputation to work, CreateArrayComp would need an | 927 // For VerifyCallComputation to work, CreateArrayComp would need an |
911 // ArgumentCount getter and an ArgumentAt getter. | 928 // ArgumentCount getter and an ArgumentAt getter. |
912 const intptr_t kNumInputs = 1; | 929 const intptr_t kNumInputs = 1; |
913 const intptr_t kNumTemps = 1; | 930 const intptr_t kNumTemps = 1; |
914 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 931 LocationSummary* locs = new LocationSummary(kNumInputs, |
932 kNumTemps, | |
933 LocationSummary::kCall); | |
915 locs->set_in(0, Location::RegisterLocation(RBX)); | 934 locs->set_in(0, Location::RegisterLocation(RBX)); |
916 locs->set_temp(0, Location::RegisterLocation(R10)); | 935 locs->set_temp(0, Location::RegisterLocation(R10)); |
917 locs->set_out(Location::RegisterLocation(RAX)); | 936 locs->set_out(Location::RegisterLocation(RAX)); |
918 return locs; | 937 return locs; |
919 } | 938 } |
920 | 939 |
921 | 940 |
922 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 941 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
923 Register temp_reg = locs()->temp(0).reg(); | 942 Register temp_reg = locs()->temp(0).reg(); |
924 Register result_reg = locs()->out().reg(); | 943 Register result_reg = locs()->out().reg(); |
(...skipping 11 matching lines...) Expand all Loading... | |
936 __ leaq(temp_reg, FieldAddress(result_reg, Array::data_offset())); | 955 __ leaq(temp_reg, FieldAddress(result_reg, Array::data_offset())); |
937 for (int i = ElementCount() - 1; i >= 0; --i) { | 956 for (int i = ElementCount() - 1; i >= 0; --i) { |
938 ASSERT(ElementAt(i)->IsUse()); | 957 ASSERT(ElementAt(i)->IsUse()); |
939 __ popq(Address(temp_reg, i * kWordSize)); | 958 __ popq(Address(temp_reg, i * kWordSize)); |
940 } | 959 } |
941 } | 960 } |
942 | 961 |
943 | 962 |
944 LocationSummary* AllocateObjectWithBoundsCheckComp:: | 963 LocationSummary* AllocateObjectWithBoundsCheckComp:: |
945 MakeLocationSummary() const { | 964 MakeLocationSummary() const { |
946 return LocationSummary::Make(2, Location::RequiresRegister()); | 965 return LocationSummary::Make(2, |
966 Location::RequiresRegister(), | |
967 LocationSummary::kCall); | |
947 } | 968 } |
948 | 969 |
949 | 970 |
950 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( | 971 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( |
951 FlowGraphCompiler* compiler) { | 972 FlowGraphCompiler* compiler) { |
952 const Class& cls = Class::ZoneHandle(constructor().owner()); | 973 const Class& cls = Class::ZoneHandle(constructor().owner()); |
953 Register type_arguments = locs()->in(0).reg(); | 974 Register type_arguments = locs()->in(0).reg(); |
954 Register instantiator_type_arguments = locs()->in(1).reg(); | 975 Register instantiator_type_arguments = locs()->in(1).reg(); |
955 Register result = locs()->out().reg(); | 976 Register result = locs()->out().reg(); |
956 | 977 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
992 compiler->EmitClassChecksNoSmi(*class_ids(), instance, result, deopt); | 1013 compiler->EmitClassChecksNoSmi(*class_ids(), instance, result, deopt); |
993 } | 1014 } |
994 | 1015 |
995 __ movq(result, FieldAddress(instance, offset_in_bytes())); | 1016 __ movq(result, FieldAddress(instance, offset_in_bytes())); |
996 } | 1017 } |
997 | 1018 |
998 | 1019 |
999 LocationSummary* InstantiateTypeArgumentsComp::MakeLocationSummary() const { | 1020 LocationSummary* InstantiateTypeArgumentsComp::MakeLocationSummary() const { |
1000 const intptr_t kNumInputs = 1; | 1021 const intptr_t kNumInputs = 1; |
1001 const intptr_t kNumTemps = 0; | 1022 const intptr_t kNumTemps = 0; |
1002 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 1023 LocationSummary* locs = new LocationSummary(kNumInputs, |
1024 kNumTemps, | |
1025 LocationSummary::kCall); | |
1003 locs->set_in(0, Location::RequiresRegister()); | 1026 locs->set_in(0, Location::RequiresRegister()); |
1004 locs->set_out(Location::SameAsFirstInput()); | 1027 locs->set_out(Location::SameAsFirstInput()); |
1005 return locs; | 1028 return locs; |
1006 } | 1029 } |
1007 | 1030 |
1008 | 1031 |
1009 void InstantiateTypeArgumentsComp::EmitNativeCode( | 1032 void InstantiateTypeArgumentsComp::EmitNativeCode( |
1010 FlowGraphCompiler* compiler) { | 1033 FlowGraphCompiler* compiler) { |
1011 Register instantiator_reg = locs()->in(0).reg(); | 1034 Register instantiator_reg = locs()->in(0).reg(); |
1012 Register result_reg = locs()->out().reg(); | 1035 Register result_reg = locs()->out().reg(); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1171 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 1194 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
1172 } | 1195 } |
1173 __ Bind(&done); | 1196 __ Bind(&done); |
1174 // instantiator_reg: instantiator or kNoInstantiator. | 1197 // instantiator_reg: instantiator or kNoInstantiator. |
1175 } | 1198 } |
1176 | 1199 |
1177 | 1200 |
1178 LocationSummary* AllocateContextComp::MakeLocationSummary() const { | 1201 LocationSummary* AllocateContextComp::MakeLocationSummary() const { |
1179 const intptr_t kNumInputs = 0; | 1202 const intptr_t kNumInputs = 0; |
1180 const intptr_t kNumTemps = 1; | 1203 const intptr_t kNumTemps = 1; |
1181 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 1204 LocationSummary* locs = new LocationSummary(kNumInputs, |
1205 kNumTemps, | |
1206 LocationSummary::kCall); | |
1182 locs->set_temp(0, Location::RegisterLocation(R10)); | 1207 locs->set_temp(0, Location::RegisterLocation(R10)); |
1183 locs->set_out(Location::RegisterLocation(RAX)); | 1208 locs->set_out(Location::RegisterLocation(RAX)); |
1184 return locs; | 1209 return locs; |
1185 } | 1210 } |
1186 | 1211 |
1187 | 1212 |
1188 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1213 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1189 ASSERT(locs()->temp(0).reg() == R10); | 1214 ASSERT(locs()->temp(0).reg() == R10); |
1190 | 1215 |
1191 __ movq(R10, Immediate(num_context_variables())); | 1216 __ movq(R10, Immediate(num_context_variables())); |
1192 const ExternalLabel label("alloc_context", | 1217 const ExternalLabel label("alloc_context", |
1193 StubCode::AllocateContextEntryPoint()); | 1218 StubCode::AllocateContextEntryPoint()); |
1194 compiler->GenerateCall(token_index(), | 1219 compiler->GenerateCall(token_index(), |
1195 try_index(), | 1220 try_index(), |
1196 &label, | 1221 &label, |
1197 PcDescriptors::kOther); | 1222 PcDescriptors::kOther); |
1198 } | 1223 } |
1199 | 1224 |
1200 | 1225 |
1201 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 1226 LocationSummary* CloneContextComp::MakeLocationSummary() const { |
1202 return LocationSummary::Make(1, Location::RequiresRegister()); | 1227 return LocationSummary::Make(1, |
1228 Location::RequiresRegister(), | |
1229 LocationSummary::kCall); | |
1203 } | 1230 } |
1204 | 1231 |
1205 | 1232 |
1206 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1233 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1207 Register context_value = locs()->in(0).reg(); | 1234 Register context_value = locs()->in(0).reg(); |
1208 Register result = locs()->out().reg(); | 1235 Register result = locs()->out().reg(); |
1209 | 1236 |
1210 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1237 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1211 __ pushq(context_value); | 1238 __ pushq(context_value); |
1212 compiler->GenerateCallRuntime(cid(), | 1239 compiler->GenerateCallRuntime(cid(), |
(...skipping 26 matching lines...) Expand all Loading... | |
1239 __ movq(Address(RBP, exception_var().index() * kWordSize), | 1266 __ movq(Address(RBP, exception_var().index() * kWordSize), |
1240 kExceptionObjectReg); | 1267 kExceptionObjectReg); |
1241 __ movq(Address(RBP, stacktrace_var().index() * kWordSize), | 1268 __ movq(Address(RBP, stacktrace_var().index() * kWordSize), |
1242 kStackTraceObjectReg); | 1269 kStackTraceObjectReg); |
1243 } | 1270 } |
1244 | 1271 |
1245 | 1272 |
1246 LocationSummary* CheckStackOverflowComp::MakeLocationSummary() const { | 1273 LocationSummary* CheckStackOverflowComp::MakeLocationSummary() const { |
1247 const intptr_t kNumInputs = 0; | 1274 const intptr_t kNumInputs = 0; |
1248 const intptr_t kNumTemps = 1; | 1275 const intptr_t kNumTemps = 1; |
1249 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 1276 // TODO(vegorov): spilling is required only on infrequently executed path. |
srdjan
2012/06/18 16:33:20
A quick fix could be to use the deoptimization stu
Vyacheslav Egorov (Google)
2012/06/18 17:51:16
Yes, I agree.
In V8 we have a generic "deferred
| |
1277 LocationSummary* summary = new LocationSummary(kNumInputs, | |
1278 kNumTemps, | |
1279 LocationSummary::kCall); | |
1250 summary->set_temp(0, Location::RequiresRegister()); | 1280 summary->set_temp(0, Location::RequiresRegister()); |
1251 return summary; | 1281 return summary; |
1252 } | 1282 } |
1253 | 1283 |
1254 | 1284 |
1255 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1285 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1256 Register temp = locs()->temp(0).reg(); | 1286 Register temp = locs()->temp(0).reg(); |
1257 // Generate stack overflow check. | 1287 // Generate stack overflow check. |
1258 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); | 1288 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); |
1259 __ cmpq(RSP, Address(temp, 0)); | 1289 __ cmpq(RSP, Address(temp, 0)); |
1260 Label no_stack_overflow; | 1290 Label no_stack_overflow; |
1261 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); | 1291 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); |
1262 compiler->GenerateCallRuntime(cid(), | 1292 compiler->GenerateCallRuntime(cid(), |
1263 token_index(), | 1293 token_index(), |
1264 try_index(), | 1294 try_index(), |
1265 kStackOverflowRuntimeEntry); | 1295 kStackOverflowRuntimeEntry); |
1266 __ Bind(&no_stack_overflow); | 1296 __ Bind(&no_stack_overflow); |
1267 } | 1297 } |
1268 | 1298 |
1269 | 1299 |
1270 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1300 LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
1271 const intptr_t kNumInputs = 2; | 1301 const intptr_t kNumInputs = 2; |
1272 | 1302 |
1273 if (operands_type() == kDoubleOperands) { | 1303 if (operands_type() == kDoubleOperands) { |
1274 const intptr_t kNumTemps = 1; | 1304 return MakeCallSummary(); // Calls into a stub for allocation. |
1275 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | |
1276 summary->set_in(0, Location::RequiresRegister()); | |
1277 summary->set_in(1, Location::RequiresRegister()); | |
1278 summary->set_out(Location::RegisterLocation(RAX)); | |
1279 summary->set_temp(0, Location::RequiresRegister()); | |
1280 return summary; | |
1281 } | 1305 } |
1282 | 1306 |
1283 ASSERT(operands_type() == kSmiOperands); | 1307 ASSERT(operands_type() == kSmiOperands); |
1284 | 1308 |
1285 if (op_kind() == Token::kTRUNCDIV) { | 1309 if (op_kind() == Token::kTRUNCDIV) { |
1286 const intptr_t kNumTemps = 3; | 1310 const intptr_t kNumTemps = 3; |
1287 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 1311 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); |
1288 summary->set_in(0, Location::RegisterLocation(RAX)); | 1312 summary->set_in(0, Location::RegisterLocation(RAX)); |
1289 summary->set_in(1, Location::RegisterLocation(RCX)); | 1313 summary->set_in(1, Location::RegisterLocation(RCX)); |
1290 summary->set_out(Location::SameAsFirstInput()); | 1314 summary->set_out(Location::SameAsFirstInput()); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1449 } | 1473 } |
1450 default: | 1474 default: |
1451 UNREACHABLE(); | 1475 UNREACHABLE(); |
1452 break; | 1476 break; |
1453 } | 1477 } |
1454 } | 1478 } |
1455 | 1479 |
1456 | 1480 |
1457 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, | 1481 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, |
1458 BinaryOpComp* comp) { | 1482 BinaryOpComp* comp) { |
1459 Register left = comp->locs()->in(0).reg(); | 1483 Register left = RBX; |
1460 Register right = comp->locs()->in(1).reg(); | 1484 Register right = RCX; |
1461 Register temp = comp->locs()->temp(0).reg(); | 1485 Register temp = RDX; |
1462 Register result = comp->locs()->out().reg(); | 1486 Register result = comp->locs()->out().reg(); |
1463 | 1487 |
1464 const Class& double_class = compiler->double_class(); | 1488 const Class& double_class = compiler->double_class(); |
1465 const Code& stub = | 1489 const Code& stub = |
1466 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1490 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1467 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1491 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1468 __ pushq(left); | |
1469 __ pushq(right); | |
1470 compiler->GenerateCall(comp->instance_call()->token_index(), | 1492 compiler->GenerateCall(comp->instance_call()->token_index(), |
1471 comp->instance_call()->try_index(), | 1493 comp->instance_call()->try_index(), |
1472 &label, | 1494 &label, |
1473 PcDescriptors::kOther); | 1495 PcDescriptors::kOther); |
1474 // Newly allocated object is now in the result register (RAX). | 1496 // Newly allocated object is now in the result register (RAX). |
1475 ASSERT(result == RAX); | 1497 ASSERT(result == RAX); |
1476 __ popq(right); | 1498 __ popq(right); |
1477 __ popq(left); | 1499 __ popq(left); |
1478 | 1500 |
1479 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1501 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1559 } | 1581 } |
1560 } else { | 1582 } else { |
1561 UNREACHABLE(); | 1583 UNREACHABLE(); |
1562 } | 1584 } |
1563 } | 1585 } |
1564 | 1586 |
1565 | 1587 |
1566 LocationSummary* NumberNegateComp::MakeLocationSummary() const { | 1588 LocationSummary* NumberNegateComp::MakeLocationSummary() const { |
1567 const intptr_t kNumInputs = 1; | 1589 const intptr_t kNumInputs = 1; |
1568 const intptr_t kNumTemps = 1; // Needed for doubles. | 1590 const intptr_t kNumTemps = 1; // Needed for doubles. |
1569 LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps); | 1591 LocationSummary* summary = new LocationSummary(kNumInputs, |
1592 kNumTemps, | |
1593 LocationSummary::kCall); | |
1570 summary->set_in(0, Location::RequiresRegister()); | 1594 summary->set_in(0, Location::RequiresRegister()); |
1571 summary->set_out(Location::SameAsFirstInput()); | 1595 summary->set_out(Location::SameAsFirstInput()); |
1572 summary->set_temp(0, Location::RequiresRegister()); | 1596 summary->set_temp(0, Location::RequiresRegister()); |
1573 return summary; | 1597 return summary; |
1574 } | 1598 } |
1575 | 1599 |
1576 | 1600 |
1577 void NumberNegateComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1601 void NumberNegateComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1578 const ICData& ic_data = *instance_call()->ic_data(); | 1602 const ICData& ic_data = *instance_call()->ic_data(); |
1579 ASSERT(!ic_data.IsNull()); | 1603 ASSERT(!ic_data.IsNull()); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1625 LocationSummary* ToDoubleComp::MakeLocationSummary() const { | 1649 LocationSummary* ToDoubleComp::MakeLocationSummary() const { |
1626 const intptr_t kNumInputs = 1; | 1650 const intptr_t kNumInputs = 1; |
1627 if (from() == kDouble) { | 1651 if (from() == kDouble) { |
1628 const intptr_t kNumTemps = 0; | 1652 const intptr_t kNumTemps = 0; |
1629 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 1653 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
1630 locs->set_in(0, Location::RequiresRegister()); | 1654 locs->set_in(0, Location::RequiresRegister()); |
1631 locs->set_out(Location::SameAsFirstInput()); | 1655 locs->set_out(Location::SameAsFirstInput()); |
1632 return locs; | 1656 return locs; |
1633 } else { | 1657 } else { |
1634 ASSERT(from() == kSmi); | 1658 ASSERT(from() == kSmi); |
1635 return LocationSummary::Make(kNumInputs, Location::RegisterLocation(RAX)); | 1659 return MakeCallSummary(); |
1636 } | 1660 } |
1637 } | 1661 } |
1638 | 1662 |
1639 | 1663 |
1640 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1664 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1641 Register value = locs()->in(0).reg(); | 1665 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; |
1642 Register result = locs()->out().reg(); | 1666 Register result = locs()->out().reg(); |
1643 | 1667 |
1644 const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1668 const DeoptReasonId deopt_reason = (from() == kDouble) ? |
1645 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1669 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
1646 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1670 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
1647 instance_call()->token_index(), | 1671 instance_call()->token_index(), |
1648 instance_call()->try_index(), | 1672 instance_call()->try_index(), |
1649 deopt_reason, | 1673 deopt_reason, |
1650 value); | 1674 value); |
1651 | 1675 |
1652 if (from() == kDouble) { | 1676 if (from() == kDouble) { |
1653 __ testq(value, Immediate(kSmiTagMask)); | 1677 __ testq(value, Immediate(kSmiTagMask)); |
1654 __ j(ZERO, deopt); // Deoptimize if Smi. | 1678 __ j(ZERO, deopt); // Deoptimize if Smi. |
1655 __ CompareClassId(value, kDouble); | 1679 __ CompareClassId(value, kDouble); |
1656 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 1680 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
1657 ASSERT(value == result); | 1681 ASSERT(value == result); |
1658 return; | 1682 return; |
1659 } | 1683 } |
1660 | 1684 |
1661 ASSERT(from() == kSmi); | 1685 ASSERT(from() == kSmi); |
1662 | 1686 |
1663 const Class& double_class = compiler->double_class(); | 1687 const Class& double_class = compiler->double_class(); |
1664 const Code& stub = | 1688 const Code& stub = |
1665 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1689 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1666 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1690 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1667 | 1691 |
1668 // TODO(vegorov): allocate box in the driver loop to avoid pushing and poping. | 1692 // TODO(vegorov): allocate box in the driver loop to avoid pushing and poping. |
1669 __ pushq(value); | |
1670 compiler->GenerateCall(instance_call()->token_index(), | 1693 compiler->GenerateCall(instance_call()->token_index(), |
1671 instance_call()->try_index(), | 1694 instance_call()->try_index(), |
1672 &label, | 1695 &label, |
1673 PcDescriptors::kOther); | 1696 PcDescriptors::kOther); |
1674 ASSERT(result == RAX); | 1697 ASSERT(result == RAX); |
1675 __ popq(value); | 1698 __ popq(value); |
1676 | 1699 |
1677 __ testq(value, Immediate(kSmiTagMask)); | 1700 __ testq(value, Immediate(kSmiTagMask)); |
1678 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. | 1701 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. |
1679 __ SmiUntag(value); | 1702 __ SmiUntag(value); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1728 instance_call()->argument_names()); | 1751 instance_call()->argument_names()); |
1729 } | 1752 } |
1730 __ Bind(&done); | 1753 __ Bind(&done); |
1731 } | 1754 } |
1732 | 1755 |
1733 } // namespace dart | 1756 } // namespace dart |
1734 | 1757 |
1735 #undef __ | 1758 #undef __ |
1736 | 1759 |
1737 #endif // defined TARGET_ARCH_X64 | 1760 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |